def challenge(self, data, session='', typ='raw', challenge=None): ''' the challenge method is for creating an transaction / challenge object remark: the transaction has a maximum lifetime and a reference to the OcraSuite token (serial) :param data: data, which is the base for the challenge or None :type data: string or None :param session: session support for ocratokens :type session: string :type typ: define, which kind of challenge base should be used could be raw - take the data input as is (extract chars accordind challenge definition Q) or random - will generate a random input or hased - will take the hash of the input data :return: challenge response containing the transcation id and the challenge for the ocrasuite :rtype : tuple of (transId(string), challenge(string)) ''' log.debug('[challenge] %r: %r: %r' % (data, session, challenge)) secretHOtp = self.token.getHOtpKey() ocraSuite = OcraSuite(self.getOcraSuiteSuite(), secretHOtp) if data is None or len(data) == 0: typ = 'random' if challenge is None: if typ == 'raw': challenge = ocraSuite.data2rawChallenge(data) elif typ == 'random': challenge = ocraSuite.data2randomChallenge(data) elif typ == 'hash': challenge = ocraSuite.data2hashChallenge(data) log.debug('[Ocra2TokenClass] challenge: %r ' % (challenge)) counter = self.getOtpCount() ## set the pin onyl in the compliant hashed mode pin = '' if ocraSuite.P is not None: pinObj = self.token.getUserPin() pin = pinObj.getKey() try: param = {} param['C'] = counter param['Q'] = challenge param['P'] = pin param['S'] = session if ocraSuite.T is not None: now = datetime.datetime.now() stime = now.strftime("%s") itime = int(stime) param['T'] = itime ''' verify that the data is compliant with the OcraSuitesuite and the client is able to calc the otp ''' c_data = ocraSuite.combineData(**param) ocraSuite.compute(c_data) except Exception as ex: log.error("[Ocra2TokenClass] %r" % (traceback.format_exc())) raise Exception('[Ocra2TokenClass] Failed to create ocrasuite ' 'challenge: %r' % (ex)) ## create a non exisiting challenge try: (res, opt) = create_challenge(self, options={'messgae': data}) transid = opt.get('transactionid') challenge = opt.get('challenge') except Exception as ex: ## this might happen if we have a db problem or ## the uniqnes constrain does not fit log.error("[Ocra2TokenClass] %r" % (traceback.format_exc())) raise Exception('[Ocra2TokenClass] Failed to create ' 'challenge object: %s' % (ex)) realm = None realms = self.token.getRealms() if len(realms) > 0: realm = realms[0] url = '' if realm is not None: url = get_qrtan_url(realm.name) log.debug('[challenge]: %r: %r: %r' % (transid, challenge, url)) return (transid, challenge, True, url)
def createChallenge(self, state, options=None): ''' standard API to create an ocra challenge ''' res = True ## which kind of challenge gen should be used typ = 'raw' input = None challenge = None session = None message = "" if options is not None: input = options.get('challenge', None) if input is None: input = options.get('message', None) if input is None: input = options.get('data', None) typ = options.get('challenge_type', 'raw') ## ocra token could contain a session attribute session = options.get('ocra_session', None) if input is None or len(input) == 0: typ = 'random' secretHOtp = self.token.getHOtpKey() ocraSuite = OcraSuite(self.getOcraSuiteSuite(), secretHOtp) if typ == 'raw': challenge = ocraSuite.data2rawChallenge(input) elif typ == 'random': challenge = ocraSuite.data2randomChallenge(input) elif typ == 'hash': challenge = ocraSuite.data2hashChallenge(input) log.debug('[Ocra2TokenClass] challenge: %r ' % (challenge)) store_data = { 'challenge' : "%s" % (challenge), 'serial' : self.token.getSerial(), 'input' : '', 'url' : '', } if input is not None: store_data['input'] = input if session is not None: store_data["session"] = session res = self.verify_challenge_is_valid(challenge, session) ## add Info: so depending on the Info, the rendering could be done ## as a callback into the token via ## token.getQRImageData(opt=details) realms = self.token.getRealms() if len(realms) > 0: store_data["url"] = get_qrtan_url(realms[0].name) ## we will return a dict of all attributes = self.prepare_message(store_data, state) attributes['challenge'] = challenge if attributes != None and "data" in attributes: message = attributes.get("data") del attributes['data'] return (res, message, store_data, attributes)