def auth_user_passthru(wrapped_function, user_object, passw, options=None): """ This decorator checks the policy settings of ACTION.PASSTHRU. If the authentication against the userstore is not successful, the wrapped function is called. The wrapped function is usually token.check_user_pass, which takes the arguments (user, passw, options={}) :param wrapped_function: :param user_object: :param passw: :param options: Dict containing values for "g" and "clientip" :return: Tuple of True/False and reply-dictionary """ from privacyidea.lib.token import get_tokens options = options or {} g = options.get("g") if g: clientip = options.get("clientip") policy_object = g.policy_object pass_thru = policy_object.get_policies(action=ACTION.PASSTHRU, scope=SCOPE.AUTH, realm=user_object.realm, resolver=user_object.resolver, user=user_object.login, client=clientip, active=True) if len(pass_thru) > 1: raise PolicyError("Contradicting passthru policies.") if pass_thru and get_tokens(user=user_object, count=True) == 0: # If the user has NO Token, authenticate against the user store # Now we need to check the userstore password pass_thru_action = pass_thru[0].get("action").get("passthru") policy_name = pass_thru[0].get("name") if pass_thru_action in ["userstore", True]: if user_object.check_password(passw): return True, { "message": "The user authenticated against " "his userstore according to " "policy '%s'." % policy_name } else: # We are doing RADIUS passthru log.info("Forwarding the authentication request to the radius " "server %s" % pass_thru_action) radius = get_radius(pass_thru_action) r = radius.request(radius.config, user_object.login, passw) if r: return True, { 'message': "The user authenticated against " "the RADIUS server %s according " "to policy '%s'." % (pass_thru_action, policy_name) } # If nothing else returned, we return the wrapped function return wrapped_function(user_object, passw, options)
def test_07_non_ascii(self): radiusmock.setdata(response=radiusmock.AccessAccept) r = add_radius(identifier="myserver", server="1.2.3.4", secret="testing123", dictionary=DICT_FILE) self.assertTrue(r > 0) radius = get_radius("myserver") r = RADIUSServer.request(radius.config, u"nönäscii", u"passwörd") self.assertEqual(r, True)
def test_05_RADIUS_request(self): radiusmock.setdata(success=True, timeout=True) r = add_radius(identifier="myserver", server="1.2.3.4", secret="testing123", dictionary=DICT_FILE) self.assertTrue(r > 0) radius = get_radius("myserver") # A timeout will return false r = RADIUSServer.request(radius.config, "user", "password") self.assertEqual(r, False)
def test_05_RADIUS_request(self): radiusmock.setdata(response=radiusmock.AccessAccept, timeout=True) r = add_radius(identifier="myserver", server="1.2.3.4", secret="testing123", dictionary=DICT_FILE) self.assertTrue(r > 0) radius = get_radius("myserver") # A timeout will return false r = RADIUSServer.request(radius.config, "user", "password") self.assertEqual(r, False)
def auth_user_passthru(wrapped_function, user_object, passw, options=None): """ This decorator checks the policy settings of ACTION.PASSTHRU. If the authentication against the userstore is not successful, the wrapped function is called. The wrapped function is usually token.check_user_pass, which takes the arguments (user, passw, options={}) :param wrapped_function: :param user_object: :param passw: :param options: Dict containing values for "g" and "clientip" :return: Tuple of True/False and reply-dictionary """ from privacyidea.lib.token import get_tokens options = options or {} g = options.get("g") if g: policy_object = g.policy_object clientip = options.get("clientip") pass_thru = policy_object.get_policies(action=ACTION.PASSTHRU, scope=SCOPE.AUTH, realm=user_object.realm, resolver=user_object.resolver, user=user_object.login, client=clientip, active=True, sort_by_priority=True) # We only go to passthru, if the user has no tokens! if pass_thru and get_tokens(user=user_object, count=True) == 0: # Ensure that there are no conflicting action values within the same priority policy_object.check_for_conflicts(pass_thru, "passthru") pass_thru_action = pass_thru[0].get("action").get("passthru") policy_name = pass_thru[0].get("name") if pass_thru_action in ["userstore", True]: # Now we need to check the userstore password if user_object.check_password(passw): g.audit_object.add_policy([p.get("name") for p in pass_thru]) return True, {"message": u"against userstore due to '{!s}'".format( policy_name)} else: # We are doing RADIUS passthru log.info("Forwarding the authentication request to the radius " "server %s" % pass_thru_action) radius = get_radius(pass_thru_action) r = radius.request(radius.config, user_object.login, passw) if r: g.audit_object.add_policy([p.get("name") for p in pass_thru]) return True, {'message': u"against RADIUS server {!s} due to '{!s}'".format( pass_thru_action, policy_name)} # If nothing else returned, we return the wrapped function return wrapped_function(user_object, passw, options)
def auth_user_passthru(wrapped_function, user_object, passw, options=None): """ This decorator checks the policy settings of ACTION.PASSTHRU. If the authentication against the userstore is not successful, the wrapped function is called. The wrapped function is usually token.check_user_pass, which takes the arguments (user, passw, options={}) :param wrapped_function: :param user_object: :param passw: :param options: Dict containing values for "g" and "clientip" :return: Tuple of True/False and reply-dictionary """ from privacyidea.lib.token import get_tokens options = options or {} g = options.get("g") if g: clientip = options.get("clientip") policy_object = g.policy_object pass_thru = policy_object.get_policies(action=ACTION.PASSTHRU, scope=SCOPE.AUTH, realm=user_object.realm, resolver=user_object.resolver, user=user_object.login, client=clientip, active=True) if len(pass_thru) > 1: raise PolicyError("Contradicting passthru policies.") if pass_thru and get_tokens(user=user_object, count=True) == 0: # If the user has NO Token, authenticate against the user store # Now we need to check the userstore password pass_thru_action = pass_thru[0].get("action").get("passthru") policy_name = pass_thru[0].get("name") if pass_thru_action in ["userstore", True]: if user_object.check_password(passw): return True, {"message": "The user authenticated against " "his userstore according to " "policy '%s'." % policy_name} else: # We are doing RADIUS passthru log.info("Forwarding the authentication request to the radius " "server %s" % pass_thru_action) radius = get_radius(pass_thru_action) r = radius.request(radius.config, user_object.login, passw) if r: return True, {'message': "The user authenticated against " "the RADIUS server %s according " "to policy '%s'." % (pass_thru_action, policy_name)} # If nothing else returned, we return the wrapped function return wrapped_function(user_object, passw, options)
def auth_user_passthru(wrapped_function, user_object, passw, options=None): """ This decorator checks the policy settings of ACTION.PASSTHRU. If the authentication against the userstore is not successful, the wrapped function is called. The wrapped function is usually token.check_user_pass, which takes the arguments (user, passw, options={}) :param wrapped_function: :param user_object: :param passw: :param options: Dict containing values for "g" and "clientip" :return: Tuple of True/False and reply-dictionary """ from privacyidea.lib.token import get_tokens options = options or {} g = options.get("g") if get_tokens(user=user_object, count=True) == 0 and g: # We only go to passthru, if the user has no tokens! clientip = options.get("clientip") policy_object = g.policy_object pass_thru = policy_object.get_policies(action=ACTION.PASSTHRU, scope=SCOPE.AUTH, realm=user_object.realm, resolver=user_object.resolver, user=user_object.login, client=clientip, active=True, sort_by_priority=True) # Ensure that there are no conflicting action values within the same priority policy_object.check_for_conflicts(pass_thru, "passthru") if pass_thru: pass_thru_action = pass_thru[0].get("action").get("passthru") policy_name = pass_thru[0].get("name") if pass_thru_action in ["userstore", True]: # Now we need to check the userstore password if user_object.check_password(passw): g.audit_object.add_policy([p.get("name") for p in pass_thru]) return True, {"message": u"against userstore due to '{!s}'".format( policy_name)} else: # We are doing RADIUS passthru log.info("Forwarding the authentication request to the radius " "server %s" % pass_thru_action) radius = get_radius(pass_thru_action) r = radius.request(radius.config, user_object.login, passw) if r: g.audit_object.add_policy([p.get("name") for p in pass_thru]) return True, {'message': u"against RADIUS server {!s} due to '{!s}'".format( pass_thru_action, policy_name)} # If nothing else returned, we return the wrapped function return wrapped_function(user_object, passw, options)
def test_04_RADIUS_request(self): radiusmock.setdata(success=True) r = add_radius(identifier="myserver", server="1.2.3.4", secret="testing123", dictionary=DICT_FILE) self.assertTrue(r > 0) radius = get_radius("myserver") r = RADIUSServer.request(radius.config, "user", "password") self.assertEqual(r, True) radiusmock.setdata(success=False) r = RADIUSServer.request(radius.config, "user", "password") self.assertEqual(r, False)
def check_otp(self, otpval, counter=None, window=None, options=None): """ run the RADIUS request against the RADIUS server :param otpval: the OTP value :param counter: The counter for counter based otp values :type counter: int :param window: a counter window :type counter: int :param options: additional token specific options :type options: dict :return: counter of the matching OTP value. :rtype: int """ otp_count = -1 options = options or {} radius_dictionary = None radius_identifier = self.get_tokeninfo("radius.identifier") radius_user = self.get_tokeninfo("radius.user") system_radius_settings = self.get_tokeninfo("radius.system_settings") if radius_identifier: # New configuration radius_server_object = get_radius(radius_identifier) radius_server = radius_server_object.config.server radius_port = radius_server_object.config.port radius_server = "%s:%s" % (radius_server, radius_port) radius_secret = radius_server_object.get_secret() radius_dictionary = radius_server_object.config.dictionary elif system_radius_settings: # system configuration radius_server = get_from_config("radius.server") radius_secret = get_from_config("radius.secret") # Is returned as unicode, so we convert it to utf-8 radius_secret = radius_secret.encode("utf-8") else: # individual token settings radius_server = self.get_tokeninfo("radius.server") # Read the secret secret = self.token.get_otpkey() radius_secret = binascii.unhexlify(secret.getKey()) # here we also need to check for radius.user log.debug("checking OTP len:%s on radius server: %s, user: %s" % (len(otpval), radius_server, radius_user)) try: # pyrad does not allow to set timeout and retries. # it defaults to retries=3, timeout=5 # TODO: At the moment we support only one radius server. # No round robin. server = radius_server.split(':') r_server = server[0] r_authport = 1812 if len(server) >= 2: r_authport = int(server[1]) nas_identifier = get_from_config("radius.nas_identifier", "privacyIDEA") if not radius_dictionary: radius_dictionary = get_from_config("radius.dictfile", "/etc/privacyidea/" "dictionary") log.debug("NAS Identifier: %r, " "Dictionary: %r" % (nas_identifier, radius_dictionary)) log.debug("constructing client object " "with server: %r, port: %r, secret: %r" % (r_server, r_authport, radius_secret)) srv = Client(server=r_server, authport=r_authport, secret=radius_secret, dict=Dictionary(radius_dictionary)) req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest, User_Name=radius_user.encode('ascii'), NAS_Identifier=nas_identifier.encode('ascii')) req["User-Password"] = req.PwCrypt(otpval) if "transactionid" in options: req["State"] = str(options.get("transactionid")) response = srv.SendPacket(req) c = response.code # TODO: handle the RADIUS challenge """ if response.code == pyrad.packet.AccessChallenge: opt = {} for attr in response.keys(): opt[attr] = response[attr] res = False log.debug("challenge returned %r " % opt) # now we map this to a privacyidea challenge if "State" in opt: reply["transactionid"] = opt["State"][0] if "Reply-Message" in opt: reply["message"] = opt["Reply-Message"][0] """ if response.code == pyrad.packet.AccessAccept: log.info("Radiusserver %s granted " "access to user %s." % (r_server, radius_user)) otp_count = 0 else: log.warning("Radiusserver %s" "rejected access to user %s." % (r_server, radius_user)) except Exception as ex: # pragma: no cover log.error("Error contacting radius Server: %r" % (ex)) log.debug("%s" % traceback.format_exc()) return otp_count
def auth_user_passthru(wrapped_function, user_object, passw, options=None): """ This decorator checks the policy settings of ACTION.PASSTHRU. If the authentication against the userstore is not successful, the wrapped function is called. The wrapped function is usually token.check_user_pass, which takes the arguments (user, passw, options={}) :param wrapped_function: :param user_object: :param passw: :param options: Dict containing values for "g" and "clientip" :return: Tuple of True/False and reply-dictionary """ from privacyidea.lib.token import get_tokens from privacyidea.lib.token import assign_token options = options or {} g = options.get("g") if g: policy_object = g.policy_object pass_thru = Match.user( g, scope=SCOPE.AUTH, action=ACTION.PASSTHRU, user_object=user_object).policies(write_to_audit_log=False) # We only go to passthru, if the user has no tokens! if pass_thru and get_tokens(user=user_object, count=True) == 0: # Ensure that there are no conflicting action values within the same priority policy_object.check_for_conflicts(pass_thru, "passthru") pass_thru_action = pass_thru[0].get("action").get("passthru") policy_name = pass_thru[0].get("name") if pass_thru_action in ["userstore", True]: # Now we need to check the userstore password if user_object.check_password(passw): g.audit_object.add_policy( [p.get("name") for p in pass_thru]) return True, { "message": u"against userstore due to '{!s}'".format(policy_name) } else: # We are doing RADIUS passthru log.info("Forwarding the authentication request to the radius " "server %s" % pass_thru_action) radius = get_radius(pass_thru_action) r = radius.request(radius.config, user_object.login, passw) if r: g.audit_object.add_policy( [p.get("name") for p in pass_thru]) # TODO: here we can check, if the token should be assigned. passthru_assign = Match.user( g, scope=SCOPE.AUTH, action=ACTION.PASSTHRU_ASSIGN, user_object=user_object).action_values(unique=True) messages = [] if passthru_assign: components = list(passthru_assign)[0].split(":") if len(components) >= 2: prepend_pin = components[0] == "pin" otp_length = int(components[int(prepend_pin)]) pin, otp = split_pin_pass(passw, otp_length, prepend_pin) realm_tokens = get_tokens(realm=user_object.realm, assigned=False) window = 100 if len(components) == 3: window = int(components[2]) for token_obj in realm_tokens: otp_check = token_obj.check_otp(otp, window=window) if otp_check >= 0: # We do not check any max tokens per realm or user, # since this very user currently has no token # and the unassigned token already was contained in the user's realm assign_token(serial=token_obj.token.serial, user=user_object, pin=pin) messages.append( u"autoassigned {0!s}".format( token_obj.token.serial)) break else: log.warning( "Wrong value in passthru_assign policy: {0!s}". format(passthru_assign)) messages.append( u"against RADIUS server {!s} due to '{!s}'".format( pass_thru_action, policy_name)) return True, {'message': ",".join(messages)} # If nothing else returned, we return the wrapped function return wrapped_function(user_object, passw, options)
def _check_radius(self, otpval, options=None, radius_state=None): """ run the RADIUS request against the RADIUS server :param otpval: the OTP value :param options: additional token specific options :type options: dict :return: counter of the matching OTP value. :rtype: AccessAccept, AccessReject, AccessChallenge """ result = AccessReject radius_message = None if options is None: options = {} radius_dictionary = None radius_identifier = self.get_tokeninfo("radius.identifier") radius_user = self.get_tokeninfo("radius.user") system_radius_settings = self.get_tokeninfo("radius.system_settings") radius_timeout = 5 radius_retries = 3 if radius_identifier: # New configuration radius_server_object = get_radius(radius_identifier) radius_server = radius_server_object.config.server radius_port = radius_server_object.config.port radius_server = u"{0!s}:{1!s}".format(radius_server, radius_port) radius_secret = radius_server_object.get_secret() radius_dictionary = radius_server_object.config.dictionary radius_timeout = int(radius_server_object.config.timeout or 10) radius_retries = int(radius_server_object.config.retries or 1) elif system_radius_settings: # system configuration radius_server = get_from_config("radius.server") radius_secret = get_from_config("radius.secret") else: # individual token settings radius_server = self.get_tokeninfo("radius.server") # Read the secret secret = self.token.get_otpkey() radius_secret = binascii.unhexlify(secret.getKey()) # here we also need to check for radius.user log.debug(u"checking OTP len:{0!s} on radius server: " u"{1!s}, user: {2!r}".format(len(otpval), radius_server, radius_user)) try: # pyrad does not allow to set timeout and retries. # it defaults to retries=3, timeout=5 # TODO: At the moment we support only one radius server. # No round robin. server = radius_server.split(':') r_server = server[0] r_authport = 1812 if len(server) >= 2: r_authport = int(server[1]) nas_identifier = get_from_config("radius.nas_identifier", "privacyIDEA") if not radius_dictionary: radius_dictionary = get_from_config( "radius.dictfile", "/etc/privacyidea/dictionary") log.debug(u"NAS Identifier: %r, " u"Dictionary: %r" % (nas_identifier, radius_dictionary)) log.debug(u"constructing client object " u"with server: %r, port: %r, secret: %r" % (r_server, r_authport, to_unicode(radius_secret))) srv = Client(server=r_server, authport=r_authport, secret=to_bytes(radius_secret), dict=Dictionary(radius_dictionary)) # Set retries and timeout of the client srv.timeout = radius_timeout srv.retries = radius_retries req = srv.CreateAuthPacket( code=pyrad.packet.AccessRequest, User_Name=radius_user.encode('utf-8'), NAS_Identifier=nas_identifier.encode('ascii')) req["User-Password"] = req.PwCrypt(otpval) if radius_state: req["State"] = radius_state log.info( u"Sending saved challenge to radius server: {0!r} ".format( radius_state)) try: response = srv.SendPacket(req) except Timeout: log.warning( u"The remote RADIUS server {0!s} timeout out for user {1!s}." .format(r_server, radius_user)) return AccessReject # handle the RADIUS challenge if response.code == pyrad.packet.AccessChallenge: # now we map this to a privacyidea challenge if "State" in response: radius_state = response["State"][0] if "Reply-Message" in response: radius_message = response["Reply-Message"][0] result = AccessChallenge elif response.code == pyrad.packet.AccessAccept: radius_state = '<SUCCESS>' radius_message = 'RADIUS authentication succeeded' log.info(u"RADIUS server {0!s} granted " u"access to user {1!s}.".format( r_server, radius_user)) result = AccessAccept else: radius_state = '<REJECTED>' radius_message = 'RADIUS authentication failed' log.debug(u'radius response code {0!s}'.format(response.code)) log.info(u"Radiusserver {0!s} " u"rejected access to user {1!s}.".format( r_server, radius_user)) result = AccessReject except Exception as ex: # pragma: no cover log.error("Error contacting radius Server: {0!r}".format((ex))) log.info("{0!s}".format(traceback.format_exc())) options.update({'radius_result': result}) options.update({'radius_state': radius_state}) options.update({'radius_message': radius_message}) return result
def check_otp(self, otpval, counter=None, window=None, options=None): """ run the RADIUS request against the RADIUS server :param otpval: the OTP value :param counter: The counter for counter based otp values :type counter: int :param window: a counter window :type counter: int :param options: additional token specific options :type options: dict :return: counter of the matching OTP value. :rtype: int """ otp_count = -1 options = options or {} radius_dictionary = None radius_identifier = self.get_tokeninfo("radius.identifier") radius_user = self.get_tokeninfo("radius.user") system_radius_settings = self.get_tokeninfo("radius.system_settings") if radius_identifier: # New configuration radius_server_object = get_radius(radius_identifier) radius_server = radius_server_object.config.server radius_port = radius_server_object.config.port radius_server = "{0!s}:{1!s}".format(radius_server, radius_port) radius_secret = radius_server_object.get_secret() radius_dictionary = radius_server_object.config.dictionary elif system_radius_settings: # system configuration radius_server = get_from_config("radius.server") radius_secret = get_from_config("radius.secret") # Is returned as unicode, so we convert it to utf-8 radius_secret = radius_secret.encode("utf-8") else: # individual token settings radius_server = self.get_tokeninfo("radius.server") # Read the secret secret = self.token.get_otpkey() radius_secret = binascii.unhexlify(secret.getKey()) # here we also need to check for radius.user log.debug( "checking OTP len:{0!s} on radius server: {1!s}, user: {2!r}". format(len(otpval), radius_server, radius_user)) try: # pyrad does not allow to set timeout and retries. # it defaults to retries=3, timeout=5 # TODO: At the moment we support only one radius server. # No round robin. server = radius_server.split(':') r_server = server[0] r_authport = 1812 if len(server) >= 2: r_authport = int(server[1]) nas_identifier = get_from_config("radius.nas_identifier", "privacyIDEA") if not radius_dictionary: radius_dictionary = get_from_config( "radius.dictfile", "/etc/privacyidea/" "dictionary") log.debug("NAS Identifier: %r, " "Dictionary: %r" % (nas_identifier, radius_dictionary)) log.debug("constructing client object " "with server: %r, port: %r, secret: %r" % (r_server, r_authport, radius_secret)) srv = Client(server=r_server, authport=r_authport, secret=radius_secret, dict=Dictionary(radius_dictionary)) req = srv.CreateAuthPacket( code=pyrad.packet.AccessRequest, User_Name=radius_user.encode('ascii'), NAS_Identifier=nas_identifier.encode('ascii')) req["User-Password"] = req.PwCrypt(otpval) if "transactionid" in options: req["State"] = str(options.get("transactionid")) response = srv.SendPacket(req) c = response.code # TODO: handle the RADIUS challenge """ if response.code == pyrad.packet.AccessChallenge: opt = {} for attr in response.keys(): opt[attr] = response[attr] res = False log.debug("challenge returned %r " % opt) # now we map this to a privacyidea challenge if "State" in opt: reply["transactionid"] = opt["State"][0] if "Reply-Message" in opt: reply["message"] = opt["Reply-Message"][0] """ if response.code == pyrad.packet.AccessAccept: log.info("Radiusserver %s granted " "access to user %s." % (r_server, radius_user)) otp_count = 0 else: log.warning("Radiusserver %s" "rejected access to user %s." % (r_server, radius_user)) except Exception as ex: # pragma: no cover log.error("Error contacting radius Server: {0!r}".format((ex))) log.debug("{0!s}".format(traceback.format_exc())) return otp_count
def auth_user_passthru(wrapped_function, user_object, passw, options=None): """ This decorator checks the policy settings of ACTION.PASSTHRU. If the authentication against the userstore is not successful, the wrapped function is called. The wrapped function is usually token.check_user_pass, which takes the arguments (user, passw, options={}) :param wrapped_function: :param user_object: :param passw: :param options: Dict containing values for "g" and "clientip" :return: Tuple of True/False and reply-dictionary """ from privacyidea.lib.token import get_tokens from privacyidea.lib.token import assign_token options = options or {} g = options.get("g") if g: policy_object = g.policy_object clientip = options.get("clientip") pass_thru = policy_object.get_policies(action=ACTION.PASSTHRU, scope=SCOPE.AUTH, realm=user_object.realm, resolver=user_object.resolver, user=user_object.login, client=clientip, active=True, sort_by_priority=True) # We only go to passthru, if the user has no tokens! if pass_thru and get_tokens(user=user_object, count=True) == 0: # Ensure that there are no conflicting action values within the same priority policy_object.check_for_conflicts(pass_thru, "passthru") pass_thru_action = pass_thru[0].get("action").get("passthru") policy_name = pass_thru[0].get("name") if pass_thru_action in ["userstore", True]: # Now we need to check the userstore password if user_object.check_password(passw): g.audit_object.add_policy([p.get("name") for p in pass_thru]) return True, {"message": u"against userstore due to '{!s}'".format( policy_name)} else: # We are doing RADIUS passthru log.info("Forwarding the authentication request to the radius " "server %s" % pass_thru_action) radius = get_radius(pass_thru_action) r = radius.request(radius.config, user_object.login, passw) if r: g.audit_object.add_policy([p.get("name") for p in pass_thru]) # TODO: here we can check, if the token should be assigned. passthru_assign = policy_object.get_action_values(action=ACTION.PASSTHRU_ASSIGN, scope=SCOPE.AUTH, realm=user_object.realm, resolver=user_object.resolver, user=user_object.login, client=clientip, unique=True, audit_data=g.audit_object.audit_data) messages = [] if passthru_assign: components = list(passthru_assign)[0].split(":") if len(components) >= 2: prepend_pin = components[0] == "pin" otp_length = int(components[int(prepend_pin)]) pin, otp = split_pin_pass(passw, otp_length, prepend_pin) realm_tokens = get_tokens(realm=user_object.realm, assigned=False) window = 100 if len(components) == 3: window = int(components[2]) for token_obj in realm_tokens: otp_check = token_obj.check_otp(otp, window=window) if otp_check >= 0: # We do not check any max tokens per realm or user, # since this very user currently has no token # and the unassigned token already was contained in the user's realm assign_token(serial=token_obj.token.serial, user=user_object, pin=pin) messages.append(u"autoassigned {0!s}".format(token_obj.token.serial)) break else: log.warning("Wrong value in passthru_assign policy: {0!s}".format(passthru_assign)) messages.append(u"against RADIUS server {!s} due to '{!s}'".format(pass_thru_action, policy_name)) return True, {'message': ",".join(messages)} # If nothing else returned, we return the wrapped function return wrapped_function(user_object, passw, options)