def delete_challenges(serial, challenges): """ delete some challenges of a token :param serial: the serial number of the token :param challenges: list of (dict|int|str|challenge objects) :return: result of the delete operation """ challenge_ids = [] for challenge in challenges: if type(challenge) == dict: if 'id' in challenge: challenge_id = challenge.get('id') elif type(challenge) == Challenge: challenge_id = challenge.get('id') elif type(challenge) in (unicode, str, int): challenge_id = challenge try: challenge_ids.append(int(challenge_id)) except ValueError: # ignore log.warning("failed to convert the challengeId %r to int()" % challenge_id) res = 1 # gather all challenges with one sql 'in' statement if len(challenge_ids) > 0: conditions = () if serial: conditions += (and_(Challenge.tokenserial == serial),) conditions += (and_(Challenge.id.in_(challenge_ids)),) # SQLAlchemy requires the conditions in one arg as tupple condition = and_(*conditions) del_challes = Session.query(Challenge).filter(condition).all() # and delete them via session for dell in del_challes: Session.delete(dell) return res
def delete_challenges(serial, challenges): """ delete some challenges of a token :param serial: the serial number of the token :param challenges: list of (dict|int|str|challenge objects) :return: result of the delete operation """ challenge_ids = [] for challenge in challenges: if type(challenge) == dict: if 'id' in challenge: challenge_id = challenge.get('id') elif type(challenge) == Challenge: challenge_id = challenge.get('id') elif type(challenge) in (unicode, str, int): challenge_id = challenge try: challenge_ids.append(int(challenge_id)) except ValueError: # ignore log.warning("failed to convert the challenge id %r to integer", challenge_id) res = 1 # gather all challenges with one sql 'in' statement if len(challenge_ids) > 0: conditions = () if serial: conditions += (and_(Challenge.tokenserial == serial),) conditions += (and_(Challenge.id.in_(challenge_ids)),) # SQLAlchemy requires the conditions in one arg as tupple condition = and_(*conditions) del_challes = Session.query(Challenge).filter(condition).all() # and delete them via session for dell in del_challes: Session.delete(dell) return res
def delete_challenges(serial, challenges): """ delete some challenges of a token :param serial: the serial number of the token :param challenges: list of (dict|int|str|challenge objects) :return: result of the delete operation """ challenge_ids = [] for challenge in challenges: if type(challenge) == dict: if "id" in challenge: challenge_id = challenge.get("id") elif type(challenge) == Challenge: challenge_id = challenge.get("id") elif type(challenge) in (unicode, str, int): challenge_id = challenge try: challenge_ids.append(int(challenge_id)) except ValueError: # ignore log.warning("failed to convert the challengeId %r to int()" % challenge_id) res = 1 # gather all challenges with one sql 'in' statement if len(challenge_ids) > 0: del_challes = ( Session.query(Challenge) .filter(Challenge.tokenserial == serial) .filter(Challenge.id.in_(challenge_ids)) .all() ) # and delete them via session for dell in del_challes: Session.delete(dell) return res
def create_challenge(token, options=None, challenge_id=None, id_postfix=''): """ dedicated method to create a challenge to support the implementation of challenge policies in future :param options: optional parameters for token specific tokens eg. request a signed challenge :return: a tuple of (boolean, and a dict, which contains the {'challenge' : challenge} description) """ # response dict, describing the challenge reply challenge = {} # the allocated db challenge object challenge_obj = None retry_counter = 0 reason = None hsm = context['hsm'].get('obj') id_length = int( context.get('Config', None).get('TransactionIdLength', 12)) - \ len(id_postfix) while True: try: if not challenge_id: transactionid = "%s%s" % ( Challenge.createTransactionId(length=id_length), id_postfix) else: transactionid = challenge_id num_challenges = Session.query(Challenge). \ filter(Challenge.transid == transactionid).count() if num_challenges == 0: challenge_obj = Challenge(transid=transactionid, tokenserial=token.getSerial()) if challenge_obj is not None: break except Exception as exce: log.info("Failed to create Challenge: %r", exce) reason = exce # prevent an unlimited loop retry_counter = retry_counter + 1 if retry_counter > 100: log.info( "Failed to create Challenge for %d times: %r -quiting!", retry_counter, reason) raise Exception('Failed to create challenge %r' % reason) expired_challenges, valid_challenges = Challenges.get_challenges(token) # carefully create a new challenge try: # we got a challenge object allocated and initialize the challenge (res, open_transactionid, message, attributes) = \ token.initChallenge(transactionid, challenges=valid_challenges, options=options) if res is False: # if a different transid is returned, this indicates, that there # is already an outstanding challenge we can refere to if open_transactionid != transactionid: transactionid = open_transactionid else: # in case the init was successfull, we preserve no the # challenge data to support the implementation of a blocking # based on the previous stored data challenge_obj.setChallenge(message) challenge_obj.save() (res, message, data, attributes) = \ token.createChallenge(transactionid, options=options) if res is True: # persist the final challenge data + message challenge_obj.setChallenge(message) challenge_obj.setData(data) challenge_obj.signChallenge(hsm) challenge_obj.save() else: transactionid = '' reason = Exception(message) except Exception as exce: reason = exce res = False # if something goes wrong with the challenge, remove it if res is False and challenge_obj is not None: try: log.debug("deleting session") Session.delete(challenge_obj) Session.commit() except Exception as exx: log.debug("deleting session failed: %r" % exx) try: Session.expunge(challenge_obj) Session.commit() except Exception as exx: log.debug("expunge session failed: %r" % exx) # in case that create challenge fails, we must raise this reason if reason is not None: message = "%r" % reason log.error("Failed to create or init challenge %r " % reason) raise reason # prepare the response for the user if transactionid is not None: challenge['transactionid'] = transactionid if message is not None: challenge['message'] = message if attributes is not None and type(attributes) == dict: challenge.update(attributes) return (res, challenge)
def create_challenge(token, options=None, challenge_id=None, id_postfix=''): """ dedicated method to create a challenge to support the implementation of challenge policies in future :param options: optional parameters for token specific tokens eg. request a signed challenge :return: a tuple of (boolean, and a dict, which contains the {'challenge' : challenge} description) """ # response dict, describing the challenge reply challenge = {} # the allocated db challenge object challenge_obj = None retry_counter = 0 reason = None ReasonException = Exception() hsm = context['hsm'].get('obj') transid_len = Challenges.get_tranactionid_length() id_length = transid_len - len(id_postfix) while True: try: if not challenge_id: transactionid = u"%s%s" % ( Challenge.createTransactionId(length=id_length), id_postfix) else: transactionid = challenge_id num_challenges = Session.query(Challenge). \ filter(Challenge.transid == transactionid).count() if num_challenges == 0: challenge_obj = Challenge(transid=transactionid, tokenserial=token.getSerial()) if challenge_obj is not None: break except Exception as exce: log.exception("Failed to create challenge: %r", exce) reason = "%r" % exce ReasonException = exce # prevent an unlimited loop retry_counter = retry_counter + 1 if retry_counter > 100: log.error( "Failed to create challenge for %d times: %r - quiting!", retry_counter, reason) raise Exception('Failed to create challenge %r' % reason) expired_challenges, valid_challenges = Challenges.get_challenges(token) # carefully create a new challenge try: # we got a challenge object allocated and initialize the challenge (res, open_transactionid, message, attributes) = \ token.initChallenge(transactionid, challenges=valid_challenges, options=options) if res is False: # if a different transid is returned, this indicates, that there # is already an outstanding challenge we can refere to if open_transactionid != transactionid: transactionid = open_transactionid else: # in case the init was successful, we preserve no the # challenge data to support the implementation of a blocking # based on the previous stored data challenge_obj.setChallenge(message) challenge_obj.save() (res, message, data, attributes) = \ token.createChallenge(transactionid, options=options) if res is True: # persist the final challenge data + message challenge_obj.setChallenge(message) challenge_obj.setData(data) challenge_obj.signChallenge(hsm) challenge_obj.save() else: transactionid = '' reason = message ReasonException = Exception(message) except Exception as exce: log.exception("Failed to create challenge: %r", exce) reason = "%r" % exce ReasonException = exce res = False # if something goes wrong with the challenge, remove it if res is False and challenge_obj is not None: try: log.debug("Deleting challenge from database session, because " "of earlier error") Session.delete(challenge_obj) Session.commit() except Exception as exx: log.debug("Deleting challenge from database session failed. " "Retrying with expunge. Exception was: %r", exx) try: Session.expunge(challenge_obj) Session.commit() except Exception as exx: log.debug("Expunging challenge from database session " "failed. Exception was: %r", exx) # in case that create challenge fails, we must raise this reason if reason is not None: log.error("Failed to create or init challenge. Reason was %r ", reason) raise ReasonException # prepare the response for the user if transactionid is not None: challenge['transactionid'] = transactionid if message is not None: challenge['message'] = message if attributes is not None and type(attributes) == dict: challenge.update(attributes) # # add token specific info like tokentype and serial # challenge["linotp_tokenserial"] = token.getSerial() challenge["linotp_tokentype"] = token.type return (res, challenge)