def test_30_split_pin_pass(self): pin, otp = split_pin_pass("test1234", 4, True) self.assertEqual(pin, "test") self.assertEqual(otp, "1234") pin, otp = split_pin_pass("12345678hallo", 8, False) self.assertEqual(pin, "hallo") self.assertEqual(otp, "12345678")
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 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)