Example #1
0
def autoassign(request, response):
    """
    This decorator decorates the function /validate/check.
    Depending on ACTION.AUTOASSIGN it checks if the user has no token and if
    the given OTP-value matches a token in the users realm, that is not yet
    assigned to any user.

    If a token can be found, it assigns the token to the user also taking
    into account ACTION.MAXTOKENUSER and ACTION.MAXTOKENREALM.
    :return:
    """
    content = json.loads(response.data)
    # check, if the authentication was successful, then we need to do nothing
    if content.get("result").get("value") is False:
        user_obj = get_user_from_param(request.all_data)
        password = request.all_data.get("pass", "")
        if user_obj.login and user_obj.realm:
            # If there is no user in the request (because it is a serial
            # authentication request) we immediately bail out
            # check if the policy is defined
            policy_object = g.policy_object

            autoassign_bool = policy_object.get_policies(
                action=ACTION.AUTOASSIGN,
                scope=SCOPE.ENROLL,
                user=user_obj.login,
                realm=user_obj.realm,
                client=request.remote_addr,
                active=True,
            )

            if len(autoassign_bool) >= 1:
                # check if the user has no token
                if get_tokens(user=user_obj, count=True) == 0:
                    # Check is the token would match
                    # get all unassigned tokens in the realm and look for a matching OTP:
                    realm_tokens = get_tokens(realm=user_obj.realm, assigned=False)
                    for token_obj in realm_tokens:
                        (res, pin, otp) = token_obj.split_pin_pass(password)
                        # TODO: What do we want to do with the PIN?
                        # Check it against userstore?
                        if token_obj.check_otp(otp) >= 0:
                            # we found a matching token
                            #    check MAXTOKENUSER and MAXTOKENREALM
                            check_max_token_user(request=request)
                            check_max_token_realm(request=request)
                            #    Assign token
                            assign_token(serial=token_obj.token.serial, user=user_obj, pin=pin)
                            # Set the response to true
                            content.get("result")["value"] = True
                            # Set the serial number
                            if not content.get("detail"):
                                content["detail"] = {}
                            content.get("detail")["serial"] = token_obj.token.serial
                            content.get("detail")["type"] = token_obj.type
                            content.get("detail")["message"] = "Token " "assigned to " "user via " "Autoassignment"
                            response.data = json.dumps(content)
                            break

    return response
Example #2
0
    def test_43_encryptpin(self):
        serial = "ENC01"
        # encrypt pin on init
        init_token({
            "serial": serial,
            "genkey": 1,
            "pin": "Hallo",
            "encryptpin": True
        })
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")

        # set a hashed pin
        set_pin(serial, "test", encrypt_pin=False)
        tokenobj = get_tokens(serial=serial)[0]
        self.assertTrue(tokenobj.token.pin_hash[0:2] != "@@")

        # set an encrypted PIN
        set_pin(serial, "test", encrypt_pin=True)
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")

        # assign the token with a PIN
        assign_token(serial,
                     User(login="******", realm=self.realm1),
                     pin="WellWell",
                     encrypt_pin=True)
        # check if pinhash starts with "@@" to indicate the encryption
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")
Example #3
0
    def test_43_encryptpin(self):
        serial = "ENC01"
        # encrypt pin on init
        init_token({"serial": serial,
                    "genkey": 1,
                    "pin": "Hallo",
                    "encryptpin": True})
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")

        # set a hashed pin
        set_pin(serial, "test", encrypt_pin=False)
        tokenobj = get_tokens(serial=serial)[0]
        self.assertTrue(tokenobj.token.pin_hash[0:2] != "@@")

        # set an encrypted PIN
        set_pin(serial, "test", encrypt_pin=True)
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")

        # assign the token with a PIN
        assign_token(serial, User(login="******", realm=self.realm1),
                     pin="WellWell", encrypt_pin=True)
        # check if pinhash starts with "@@" to indicate the encryption
        tokenobj = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")
Example #4
0
 def test_04_user_can_not_lost_another_token(self):
     self.authenticate_selfserive_user()
     assign_token(self.foreign_serial, User("cornelius", self.realm1))
     with self.app.test_request_context('/token/lost/%s' %
                                                self.foreign_serial,
                                        method='POST',
                                        headers={'Authorization':
                                                     self.at_user}):
         self.assertRaises(TokenAdminError, self.app.full_dispatch_request)
Example #5
0
 def test_04_user_can_not_lost_another_token(self):
     self.authenticate_selfserive_user()
     assign_token(self.foreign_serial, User("cornelius", self.realm1))
     with self.app.test_request_context(
             '/token/lost/{0!s}'.format(self.foreign_serial),
             method='POST',
             headers={'Authorization': self.at_user}):
         res = self.app.full_dispatch_request()
         self.assertTrue(res.status_code == 400, res)
Example #6
0
 def test_04_user_can_not_lost_another_token(self):
     self.authenticate_selfserive_user()
     assign_token(self.foreign_serial, User("cornelius", self.realm1))
     with self.app.test_request_context('/token/lost/%s' %
                                                self.foreign_serial,
                                        method='POST',
                                        headers={'Authorization':
                                                     self.at_user}):
         res = self.app.full_dispatch_request()
         self.assertTrue(res.status_code == 400, res)
Example #7
0
def reassign_token(serial, username):
    app = Flask(__name__, static_folder="static",
                template_folder="static/templates")
    app.config.from_pyfile("/etc/privacyidea/pi.cfg", silent=True)
    db = SQLAlchemy()
    db.init_app(app)
    
    with app.app_context():
        # Set global values
        unassign_token(serial)
        assign_token(serial, User(username, NEW_REALM))
Example #8
0
 def test_04_user_can_not_delete_another_token(self):
     self.authenticate_selfservice_user()
     assign_token(self.foreign_serial, User("cornelius", self.realm1))
     with self.app.test_request_context('/token/{0!s}'.format(self.foreign_serial),
                                        method='DELETE',
                                        headers={'Authorization':
                                                     self.at_user}):
         res = self.app.full_dispatch_request()
         self.assertEqual(res.status_code, 404)
         response = json.loads(res.data.decode('utf8'))
         self.assertFalse(response["result"]["status"])
     # check if the token still exists!
     tokenobject_list = get_tokens(serial=self.foreign_serial)
     self.assertTrue(len(tokenobject_list) == 1, len(tokenobject_list))
Example #9
0
 def test_04_user_can_not_delete_another_token(self):
     self.authenticate_selfserive_user()
     assign_token(self.foreign_serial, User("cornelius", self.realm1))
     with self.app.test_request_context(
             '/token/%s' % self.foreign_serial,
             method='DELETE',
             headers={'Authorization': self.at_user}):
         res = self.app.full_dispatch_request()
         self.assertTrue(res.status_code == 200, res)
         response = json.loads(res.data)
         self.assertFalse(
             response.get("result").get("value"), response.get("result"))
     # check if the token still exists!
     tokenobject_list = get_tokens(serial=self.foreign_serial)
     self.assertTrue(len(tokenobject_list) == 1, len(tokenobject_list))
Example #10
0
 def test_04_user_can_not_delete_another_token(self):
     self.authenticate_selfserive_user()
     assign_token(self.foreign_serial, User("cornelius", self.realm1))
     with self.app.test_request_context('/token/%s' % self.foreign_serial,
                                        method='DELETE',
                                        headers={'Authorization':
                                                     self.at_user}):
         res = self.app.full_dispatch_request()
         self.assertTrue(res.status_code == 200, res)
         response = json.loads(res.data)
         self.assertFalse(response.get("result").get("value"),
                         response.get("result"))
     # check if the token still exists!
     tokenobject_list = get_tokens(serial=self.foreign_serial)
     self.assertTrue(len(tokenobject_list) == 1, len(tokenobject_list))
Example #11
0
    def test_18_assign_token(self):
        serial = "ASSTOKEN"
        user = User("cornelius", resolver=self.resolvername1,
                    realm=self.realm1)
        tokenobject = init_token({"serial": serial,
                                  "otpkey": "1234567890123456"})

        r = assign_token(serial, user, pin="1234")
        self.assertTrue(r)
        self.assertTrue(tokenobject.token.user_id == "1000",
                        tokenobject.token.user_id)

        # token already assigned...
        self.assertRaises(TokenAdminError, assign_token, serial,
                          User("shadow", realm=self.realm1))

        # unassign token
        r = unassign_token(serial)
        self.assertTrue(r)
        self.assertTrue(tokenobject.token.user_id == "",
                        tokenobject.token.user_id)

        remove_token(serial)
        # assign or unassign a token, that does not exist
        self.assertRaises(TokenAdminError, assign_token, serial, user)
        self.assertRaises(TokenAdminError, unassign_token, serial)
Example #12
0
 def test_04_user_can_not_disable_another_token(self):
     self.authenticate_selfservice_user()
     assign_token(self.foreign_serial, User("cornelius", self.realm1))
     with self.app.test_request_context(
             '/token/disable/{0!s}'.format(self.foreign_serial),
             method='POST',
             headers={'Authorization': self.at_user}):
         res = self.app.full_dispatch_request()
         self.assertTrue(res.status_code == 200, res)
         response = json.loads(res.data)
         self.assertFalse(
             response.get("result").get("value"), response.get("result"))
     # check if the token still is enabled!
     tokenobject_list = get_tokens(serial=self.foreign_serial)
     self.assertTrue(len(tokenobject_list) == 1, len(tokenobject_list))
     self.assertTrue(tokenobject_list[0].token.active)
Example #13
0
    def test_18_assign_token(self):
        serial = "ASSTOKEN"
        user = User("cornelius",
                    resolver=self.resolvername1,
                    realm=self.realm1)
        tokenobject = init_token({
            "serial": serial,
            "otpkey": "1234567890123456"
        })

        r = assign_token(serial, user, pin="1234")
        self.assertTrue(r)
        self.assertTrue(tokenobject.token.user_id == "1000",
                        tokenobject.token.user_id)

        # token already assigned...
        self.assertRaises(TokenAdminError, assign_token, serial,
                          User("shadow", realm=self.realm1))

        # unassign token
        r = unassign_token(serial)
        self.assertTrue(r)
        self.assertTrue(tokenobject.token.user_id == "",
                        tokenobject.token.user_id)

        remove_token(serial)
        # assign or unassign a token, that does not exist
        self.assertRaises(TokenAdminError, assign_token, serial, user)
        self.assertRaises(TokenAdminError, unassign_token, serial)
Example #14
0
    def test_37_challenge(self):
        # We create a challenge by first sending the PIN of the HOTP token
        # then we answer the challenge by sending the OTP.

        num1 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # The correct PIN will create a challenge
        r, reply = check_serial_pass("hotptoken", "hotppin")
        self.assertTrue(r is False, r)
        num2 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # check that the challenge is created
        self.assertTrue(num1 + 1 == num2, (num1, num2))
        self.assertTrue(type(reply) == dict, reply)
        transaction_id = reply.get("transaction_id", "")
        self.assertTrue(len(transaction_id) > 10, reply)

        # Challenge Response, with the transaction id
        r, reply = check_serial_pass("hotptoken", "436521",
                                     {"transaction_id": transaction_id})
        self.assertTrue(r)
        self.assertTrue(
            reply.get("message") == "Found matching challenge", reply)

        # create two tokens with the same OTP Key and the same PIN, so
        # this token will create the same challenge
        # creating a challenge will not work!
        tokenobject = init_token({
            "serial": "CHALL001",
            "type": "hotp",
            "otpkey": self.otpkey
        })
        tokenobject = init_token({
            "serial": "CHALL002",
            "type": "hotp",
            "otpkey": self.otpkey
        })
        user = User("cornelius", realm=self.realm1)
        assign_token("CHALL001", user)
        assign_token("CHALL002", user)
        set_pin("CHALL001", "challpin")
        set_pin("CHALL002", "challpin")
        r, reply = check_user_pass(user, "challpin")
        self.assertFalse(r)
        self.assertTrue(
            "Multiple tokens to create a challenge found"
            in reply.get("message"), reply)
        remove_token("CHALL001")
        remove_token("CHALL002")
Example #15
0
 def test_04_user_can_not_disable_another_token(self):
     self.authenticate_selfservice_user()
     assign_token(self.foreign_serial, User("cornelius", self.realm1))
     with self.app.test_request_context('/token/disable/{0!s}'.format(
                                                self.foreign_serial),
                                        method='POST',
                                        headers={'Authorization':
                                                     self.at_user}):
         res = self.app.full_dispatch_request()
         self.assertTrue(res.status_code == 200, res)
         response = json.loads(res.data)
         self.assertFalse(response.get("result").get("value"),
                          response.get("result"))
     # check if the token still is enabled!
     tokenobject_list = get_tokens(serial=self.foreign_serial)
     self.assertTrue(len(tokenobject_list) == 1, len(tokenobject_list))
     self.assertTrue(tokenobject_list[0].token.active)
Example #16
0
    def test_37_challenge(self):
        # We create a challenge by first sending the PIN of the HOTP token
        # then we answer the challenge by sending the OTP.

        num1 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # The correct PIN will create a challenge
        r, reply = check_serial_pass("hotptoken", "hotppin")
        self.assertTrue(r is False, r)
        num2 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # check that the challenge is created
        self.assertTrue(num1 + 1 == num2, (num1, num2))
        self.assertTrue(type(reply) == dict, reply)
        transaction_id = reply.get("transaction_id","")
        self.assertTrue(len(transaction_id) > 10, reply)

        # Challenge Response, with the transaction id
        r, reply = check_serial_pass("hotptoken", "436521",
                                     {"transaction_id": transaction_id})
        self.assertTrue(r)
        self.assertTrue(reply.get("message") == "Found matching challenge",
                        reply)

        # create two tokens with the same OTP Key and the same PIN, so
        # this token will create the same challenge
        # creating a challenge will not work!
        tokenobject = init_token({"serial": "CHALL001", "type": "hotp",
                                  "otpkey": self.otpkey})
        tokenobject = init_token({"serial": "CHALL002", "type": "hotp",
                                  "otpkey": self.otpkey})
        user = User("cornelius", realm=self.realm1)
        assign_token("CHALL001", user)
        assign_token("CHALL002", user)
        set_pin("CHALL001", "challpin")
        set_pin("CHALL002", "challpin")
        r, reply = check_user_pass(user, "challpin")
        self.assertFalse(r)
        self.assertTrue("Multiple tokens to create a challenge found"
                        in reply.get("message"), reply)
        remove_token("CHALL001")
        remove_token("CHALL002")
Example #17
0
    def test_33_lost_token(self):
        # create a token with a user
        serial1 = "losttoken"
        tobject1 = init_token({"serial": serial1, "genkey": 1})
        r = assign_token(serial1, User(login="******", realm=self.realm1))
        self.assertTrue(r, r)

        # call the losttoken
        self.assertRaises(TokenAdminError, lost_token, "doesnotexist")
        r = lost_token(serial1)
        """
        r = {'end_date': '16/12/14 23:59',
             'pin': True, 'valid_to': 'xxxx', 'init': True, 'disable': 1,
             'user': True, 'serial': 'lostlosttoken', 'password':
             '******'}
        """
        self.assertTrue(r.get("pin") == True, r)
        self.assertTrue(r.get("init") == True, r)
        self.assertTrue(r.get("user") == True, r)
        self.assertTrue(r.get("serial") == "lost%s" % serial1, r)
        remove_token("losttoken")
        remove_token("lostlosttoken")
Example #18
0
    def test_33_lost_token(self):
        # create a token with a user
        serial1 = "losttoken"
        tobject1 = init_token({"serial": serial1, "genkey": 1})
        r = assign_token(serial1, User(login="******", realm=self.realm1))
        self.assertTrue(r, r)

        # call the losttoken
        self.assertRaises(TokenAdminError, lost_token, "doesnotexist")
        r = lost_token(serial1)
        """
        r = {'end_date': '16/12/14 23:59',
             'pin': True, 'valid_to': 'xxxx', 'init': True, 'disable': 1,
             'user': True, 'serial': 'lostlosttoken', 'password':
             '******'}
        """
        self.assertTrue(r.get("pin") == True, r)
        self.assertTrue(r.get("init") == True, r)
        self.assertTrue(r.get("user") == True, r)
        self.assertTrue(r.get("serial") == "lost%s" % serial1, r)
        remove_token("losttoken")
        remove_token("lostlosttoken")
Example #19
0
def assign_user(resolver, realm, username, email, givenname, surname, serial, pin):
    app = create_app(config_name="production",
                     config_file="/etc/privacyidea/pi.cfg",
                     silent=True)

    with app.app_context():
        # User operations
        try:
            print("+ Processing user {0!s} in {1!s}/{2!s}.".format(username, resolver, realm))
            user_obj = User(username, realm, resolver=resolver)
        except UserError as err:
            sys.stderr.write(" +-- Failed finding user: {0!s}.\n".format(err))
            return

        if not user_obj.exist():
            print(" +- Creating user {0!s} in {1!s}/{2!s}.".format(username, resolver, realm))
            try:
                create_user(resolver, {"username": username,
                                       "email": email,
                                       "givenname": givenname,
                                       "surname": surname}, password="")
                user_obj = User(username, realm, resolver=resolver)
            except UserError as err:
                sys.stderr.write("+-- Failed to create user: {0!s}.\n".format(err))
                return
            except Exception as err:
                sys.stderr.write("+-- Failed to create user: {0!s}.\n".format(err))
                return

        # Token operations
        try:
            print(" +- Processing token {0!s}".format(serial))
            t = assign_token(serial, user_obj, pin)
            print(" +-- Assigned token to user {0!s}.".format(user_obj))
        except TokenAdminError as err:
            sys.stderr.write(" +-- Failed assigning token {0!s}: {1!s}.\n".format(serial, err))
        except ResourceNotFoundError as err:
            sys.stderr.write(" +-- Failed assigning token {0!s}: {1!s}.\n".format(serial, err))
Example #20
0
    def test_32_copy_token_user(self):
        serial1 = "tcopy1"
        tobject1 = init_token({"serial": serial1, "genkey": 1})
        r = assign_token(serial1, User(login="******", realm=self.realm1))
        self.assertTrue(r, r)
        serial2 = "tcopy2"
        tobject2 = init_token({"serial": serial2, "genkey": 1})

        r = copy_token_user(serial1, serial2)
        assert isinstance(tobject2, TokenClass)
        self.assertTrue(tobject2.token.user_id == "1000",
                        tobject2.token.user_id)
        self.assertTrue(tobject2.token.resolver == self.resolvername1)
        self.assertTrue(tobject2.token.resolver_type == "passwdresolver")

        # check if the realms where copied:
        self.assertTrue(tobject2.get_realms() == [self.realm1])

        # check exceptions
        self.assertRaises(TokenAdminError, copy_token_user, serial1, "none")
        self.assertRaises(TokenAdminError, copy_token_user, "none", serial2)

        remove_token(serial1)
        remove_token(serial2)
Example #21
0
    def test_32_copy_token_user(self):
        serial1 = "tcopy1"
        tobject1 = init_token({"serial": serial1, "genkey": 1})
        r = assign_token(serial1, User(login="******", realm=self.realm1))
        self.assertTrue(r, r)
        serial2 = "tcopy2"
        tobject2 = init_token({"serial": serial2, "genkey": 1})

        r = copy_token_user(serial1, serial2)
        assert isinstance(tobject2, TokenClass)
        self.assertTrue(tobject2.token.user_id == "1000",
                        tobject2.token.user_id)
        self.assertTrue(tobject2.token.resolver == self.resolvername1)
        self.assertTrue(tobject2.token.resolver_type == "passwdresolver")

        # check if the realms where copied:
        self.assertTrue(tobject2.get_realms() == [self.realm1])

        # check exceptions
        self.assertRaises(TokenAdminError, copy_token_user, serial1, "none")
        self.assertRaises(TokenAdminError, copy_token_user, "none", serial2)

        remove_token(serial1)
        remove_token(serial2)
Example #22
0
def autoassign(request, response):
    """
    This decorator decorates the function /validate/check.
    Depending on ACTION.AUTOASSIGN it checks if the user has no token and if
    the given OTP-value matches a token in the users realm, that is not yet
    assigned to any user.

    If a token can be found, it assigns the token to the user also taking
    into account ACTION.MAXTOKENUSER and ACTION.MAXTOKENREALM.
    :return:
    """
    content = json.loads(response.data)
    # check, if the authentication was successful, then we need to do nothing
    if content.get("result").get("value") is False:
        user_obj = request.User
        #user_obj = get_user_from_param(request.all_data)
        password = request.all_data.get("pass", "")
        if user_obj.login and user_obj.realm:
            # If there is no user in the request (because it is a serial
            # authentication request) we immediately bail out
            # check if the policy is defined
            policy_object = g.policy_object

            autoassign_values = policy_object.\
                get_action_values(action=ACTION.AUTOASSIGN,
                                  scope=SCOPE.ENROLL,
                                  user=user_obj.login,
                                  resolver=user_obj.resolver,
                                  realm=user_obj.realm,
                                  client=g.client_ip)

            if len(autoassign_values) > 1:
                raise PolicyError("Contradicting Autoassign policies.")
            # check if the user has no token
            if autoassign_values and get_tokens(user=user_obj,
                                                count=True) == 0:
                # Check is the token would match
                # get all unassigned tokens in the realm and look for
                # a matching OTP:
                realm_tokens = get_tokens(realm=user_obj.realm, assigned=False)

                for token_obj in realm_tokens:
                    (res, pin, otp) = token_obj.split_pin_pass(password)
                    if res:
                        pin_check = True
                        if autoassign_values[0] == \
                                AUTOASSIGNVALUE.USERSTORE:
                            # If the autoassign policy is set to userstore,
                            # we need to check against the userstore.
                            pin_check = user_obj.check_password(pin)
                        if pin_check:
                            otp_check = token_obj.check_otp(otp)
                            if otp_check >= 0:
                                # we found a matching token
                                #    check MAXTOKENUSER and MAXTOKENREALM
                                check_max_token_user(request=request)
                                check_max_token_realm(request=request)
                                #    Assign token
                                assign_token(serial=token_obj.token.serial,
                                             user=user_obj,
                                             pin=pin)
                                # Set the response to true
                                content.get("result")["value"] = True
                                # Set the serial number
                                if not content.get("detail"):
                                    content["detail"] = {}
                                content.get("detail")["serial"] = \
                                    token_obj.token.serial
                                content.get("detail")["otplen"] = \
                                    token_obj.token.otplen
                                content.get("detail")["type"] = token_obj.type
                                content.get("detail")["message"] = "Token " \
                                                                   "assigned to " \
                                                                   "user via " \
                                                                   "Autoassignment"
                                response.data = json.dumps(content)

                                g.audit_object.log({
                                    "success":
                                    True,
                                    "action_info":
                                    "Token assigned via auto assignment",
                                    "serial":
                                    token_obj.token.serial
                                })
                                break

    return response
Example #23
0
def autoassign(request, response):
    """
    This decorator decorates the function /validate/check.
    Depending on ACTION.AUTOASSIGN it checks if the user has no token and if
    the given OTP-value matches a token in the users realm, that is not yet
    assigned to any user.

    If a token can be found, it assigns the token to the user also taking
    into account ACTION.MAXTOKENUSER and ACTION.MAXTOKENREALM.
    :return:
    """
    content = response.json
    # check, if the authentication was successful, then we need to do nothing
    if content.get("result").get("value") is False:
        user_obj = request.User
        #user_obj = get_user_from_param(request.all_data)
        password = request.all_data.get("pass", "")
        if user_obj.login and user_obj.realm:
            # If there is no user in the request (because it is a serial
            # authentication request) we immediately bail out
            # check if the policy is defined
            autoassign_values = Match.user(g, scope=SCOPE.ENROLL, action=ACTION.AUTOASSIGN,
                                           user_object=user_obj).action_values(unique=True, write_to_audit_log=False)
            # check if the user has no token
            if autoassign_values and get_tokens(user=user_obj, count=True) == 0:
                # Check if the token would match
                # get all unassigned tokens in the realm and look for
                # a matching OTP:
                realm_tokens = get_tokens(realm=user_obj.realm,
                                          assigned=False)

                for token_obj in realm_tokens:
                    (res, pin, otp) = token_obj.split_pin_pass(password)
                    if res:
                        pin_check = True
                        if list(autoassign_values)[0] == \
                                AUTOASSIGNVALUE.USERSTORE:
                            # If the autoassign policy is set to userstore,
                            # we need to check against the userstore.
                            pin_check = user_obj.check_password(pin)
                        if pin_check:
                            otp_check = token_obj.check_otp(otp)
                            if otp_check >= 0:
                                # we found a matching token
                                #    check MAXTOKENUSER and MAXTOKENREALM
                                check_max_token_user(request=request)
                                check_max_token_realm(request=request)
                                #    Assign token
                                assign_token(serial=token_obj.token.serial,
                                             user=user_obj, pin=pin)
                                # Set the response to true
                                content.get("result")["value"] = True
                                # Set the serial number
                                detail = content.setdefault("detail", {})
                                detail["serial"] = token_obj.token.serial
                                detail["otplen"] = token_obj.token.otplen
                                detail["type"] = token_obj.type
                                detail["message"] = "Token assigned to user via Autoassignment"
                                response.set_data(json.dumps(content))

                                g.audit_object.log(
                                    {"success": True,
                                     "info":
                                         "Token assigned via auto assignment",
                                     "serial": token_obj.token.serial})
                                # The token was assigned by autoassign. We save the first policy name
                                g.audit_object.add_policy(next(iter(autoassign_values.values())))
                                break

    return response
Example #24
0
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)
Example #26
0
def assign_user(resolver, realm, username, email, givenname, surname, serial,
                pin, validity, hard_or_soft):
    app = create_app(config_name="production",
                     config_file="/etc/privacyidea/pi.cfg",
                     silent=True)

    with app.app_context():
        # User operations
        try:
            print("+ Processing user {0!s} in {1!s}/{2!s}.".format(
                username, resolver, realm))
            user_obj = User(username, realm, resolver=resolver)
        except UserError as err:
            sys.stderr.write(" +-- Failed finding user: {0!s}.\n".format(err))
            return

        if not user_obj.exist():
            # Create new user
            print(" +- Creating user {0!s} in {1!s}/{2!s}.".format(
                username, resolver, realm))
            try:
                create_user(resolver, {
                    "username": username,
                    "email": email,
                    "givenname": givenname,
                    "surname": surname
                },
                            password="")
                user_obj = User(username, realm, resolver=resolver)
            except UserError as err:
                sys.stderr.write(
                    "+-- Failed to create user: {0!s}.\n".format(err))
                return
            except Exception as err:
                sys.stderr.write(
                    "+-- Failed to create user: {0!s}.\n".format(err))
                return
        else:
            # Update existing user
            print(" +- Updating user {0!s} in {1!s}/{2!s}.".format(
                username, resolver, realm))
            user_obj.update_user_info({
                "email": email,
                "givenname": givenname,
                "surname": surname
            })

        # Token operations

        ## Assign token or create registration code
        if hard_or_soft.strip().upper() == HARDWARE:
            if serial:
                # Assign an existing token
                try:
                    print(" +- Processing token {0!s}".format(serial))
                    t = assign_token(serial, user_obj, pin)
                    print(
                        " +-- Assigned token to user {0!s}.".format(user_obj))
                except TokenAdminError as err:
                    sys.stderr.write(
                        " +-- Failed assigning token {0!s}: {1!s}.\n".format(
                            serial, err))
                except ResourceNotFoundError as err:
                    sys.stderr.write(
                        " +-- Failed assigning token {0!s}: {1!s}.\n".format(
                            serial, err))
            else:
                sys.stderr.write(
                    "+-- User {0!s} is supposed to get a hardware token, but no serial defined!"
                    .format(user_obj))
        elif hard_or_soft.strip().upper() == SOFTWARE:
            # Create a registration code, since no serial number is given
            print(" +- Creating token of type {0!s}.".format(TOKEN_TYPE))
            params = {
                "type": TOKEN_TYPE,
                "genkey": 1,
                "user": user_obj.login,
                "realm": user_obj.realm
            }
            r = requests.post('https://localhost/token/init',
                              verify=False,
                              data=params,
                              headers={"Authorization": get_auth_tok()})
            if not r.json().get("result").get("status"):
                sys.stderr.write(
                    " +-- Failed to create token for user {0!s}.".format(
                        user_obj))
        else:
            sys.stderr.write(
                "+-- Unknown Hard/Soft specifier for user {0!s}: {1!s}".format(
                    user_obj, hard_or_soft))

        # Create RADIUS token with validity period
        print(" +- Creating RADIUS token for user {0!s}.".format(user_obj))
        tok = init_token(
            {
                "type": "radius",
                "radius.identifier": RADIUS_IDENTIFIER,
                "radius.user": user_obj.login
            },
            user=user_obj)
        for k, v in TOKENINFO.items():
            tok.add_tokeninfo(k, v)
        validity_end = datetime.datetime.now() + datetime.timedelta(
            int(validity))
        tok.set_validity_period_end(
            validity_end.strftime("%Y-%m-%d %H:%M:00 CET"))
Example #27
0
def autoassign(request, response):
    """
    This decorator decorates the function /validate/check.
    Depending on ACTION.AUTOASSIGN it checks if the user has no token and if
    the given OTP-value matches a token in the users realm, that is not yet
    assigned to any user.

    If a token can be found, it assigns the token to the user also taking
    into account ACTION.MAXTOKENUSER and ACTION.MAXTOKENREALM.
    :return:
    """
    content = json.loads(response.data)
    # check, if the authentication was successful, then we need to do nothing
    if content.get("result").get("value") is False:
        user_obj = get_user_from_param(request.all_data)
        password = request.all_data.get("pass", "")
        if user_obj.login and user_obj.realm:
            # If there is no user in the request (because it is a serial
            # authentication request) we immediately bail out
            # check if the policy is defined
            policy_object = g.policy_object

            autoassign_values = policy_object.\
                get_action_values(action=ACTION.AUTOASSIGN,
                                  scope=SCOPE.ENROLL,
                                  user=user_obj.login,
                                  realm=user_obj.realm,
                                  client=g.client_ip)

            if len(autoassign_values) > 1:
                raise PolicyError("Contradicting Autoassign policies.")
            # check if the user has no token
            if autoassign_values and get_tokens(user=user_obj, count=True) == 0:
                # Check is the token would match
                # get all unassigned tokens in the realm and look for
                # a matching OTP:
                realm_tokens = get_tokens(realm=user_obj.realm,
                                          assigned=False)

                for token_obj in realm_tokens:
                    (res, pin, otp) = token_obj.split_pin_pass(password)
                    if res:
                        pin_check = True
                        if autoassign_values[0] == \
                                AUTOASSIGNVALUE.USERSTORE:
                            # If the autoassign policy is set to userstore,
                            # we need to check against the userstore.
                            pin_check = user_obj.check_password(pin)
                        if pin_check:
                            otp_check = token_obj.check_otp(otp)
                            if otp_check >= 0:
                                # we found a matching token
                                #    check MAXTOKENUSER and MAXTOKENREALM
                                check_max_token_user(request=request)
                                check_max_token_realm(request=request)
                                #    Assign token
                                assign_token(serial=token_obj.token.serial,
                                             user=user_obj, pin=pin)
                                # Set the response to true
                                content.get("result")["value"] = True
                                # Set the serial number
                                if not content.get("detail"):
                                    content["detail"] = {}
                                content.get("detail")["serial"] = \
                                    token_obj.token.serial
                                content.get("detail")["otplen"] = \
                                    token_obj.token.otplen
                                content.get("detail")["type"] = token_obj.type
                                content.get("detail")["message"] = "Token " \
                                                                   "assigned to " \
                                                                   "user via " \
                                                                   "Autoassignment"
                                response.data = json.dumps(content)

                                g.audit_object.log(
                                    {"success": True,
                                     "action_info":
                                         "Token assigned via auto assignment",
                                     "serial": token_obj.token.serial})
                                break

    return response
Example #28
0
def migrate(config_obj):

    from_app = create_app(config_name="production",
                          config_file=config_obj.PRIVACYIDEA_FROM,
                          silent=True)

    to_app = create_app(config_name="production",
                        config_file=config_obj.PRIVACYIDEA_TO,
                        silent=True)

    new_users = []
    new_tokens = []

    with from_app.app_context():
        # find all the users
        userlist = get_user_list(param=config_obj.MIGRATE_USER_FIND)
        for user in userlist:
            if re.match(config_obj.MIGRATE_USER_PATTERN, user.get("username")):
                new_username = re.sub(config_obj.MIGRATE_USER_PATTERN,
                                      config_obj.MIGRATE_USER_REPLACE,
                                      user.get("username"))
                new_user = {"username": new_username, "tokenlist": []}
                for attr in config_obj.MIGRATE_ATTRIBUTES:
                    new_user[attr] = user.get(attr)

                tokens = get_tokens(
                    user=User(user.get("username"),
                              realm=config_obj.MIGRATE_USER_FIND.get("realm")))
                for token in tokens:
                    new_tokens.append(token_to_dict(token.token))
                    new_user["tokenlist"].append(token.token.serial)
                new_users.append(new_user)

    with to_app.app_context():
        # create the new tokens
        for tok in new_tokens:
            if config_obj.MIGRATE_SERIAL_PATTERN:
                tok["serial"] = re.sub(config_obj.MIGRATE_SERIAL_PATTERN,
                                       config_obj.MIGRATE_SERIAL_REPLACE,
                                       tok["serial"])
            info_list = tok.get("info_list")
            del (tok["info_list"])
            toks = get_tokens(serial=tok.get("serial"))
            if len(toks) > 0:
                print("New token {0!s} aleady exists.".format(
                    tok.get("serial")))
            else:
                create_token_from_dict(tok, info_list)

        # create the new users
        for user in new_users:
            tokenlist = user.get("tokenlist")
            del (user["tokenlist"])

            ul = get_user_list({
                "username": user.get("username"),
                "realm": config_obj.TO_REALM,
                "resolver": config_obj.TO_RESOLVER
            })
            if not ul:
                uid = create_user(config_obj.TO_RESOLVER, user)
                print("Created user {0!s}".format(uid))
            else:
                print("User already exists!")
            user_obj = User(login=user.get("username"),
                            realm=config_obj.TO_REALM,
                            resolver=config_obj.TO_RESOLVER)

            # Assign token
            for serial in tokenlist:
                serial = re.sub(config_obj.MIGRATE_SERIAL_PATTERN,
                                config_obj.MIGRATE_SERIAL_REPLACE, serial)
                print("Assigning token {0!s} to user {1!s}".format(
                    serial, user_obj))
                try:
                    assign_token(serial, user_obj)
                except Exception:
                    print(
                        "Error assigning token - probably the token is already assigned."
                    )
Example #29
0
    def test_02_validate(self):
        # assign token to user
        r = assign_token(self.serial, User("cornelius", self.realm1),
                         pin="u2f")
        self.assertEqual(r, True)

        # Issue challenge
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={"user":
                                                    "******"+self.realm1,
                                                 "pass": "******"}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = json.loads(res.data).get("result")
            detail = json.loads(res.data).get("detail")
            self.assertEqual(result.get("value"), False)
            transaction_id = detail.get("transaction_id")
            self.assertEqual(len(transaction_id), len('01350277175811850842'))
            self.assertTrue("Please confirm with your U2F token" in
                            detail.get("message"), detail.get("message"))
            attributes = detail.get("attributes")
            u2f_sign_request = attributes.get("u2fSignRequest")
            self.assertTrue("appId" in u2f_sign_request)
            app_id = u2f_sign_request.get("appId")
            self.assertTrue("challenge" in u2f_sign_request)
            challenge = u2f_sign_request.get("challenge")
            self.assertTrue("keyHandle" in u2f_sign_request)
            key_handle = u2f_sign_request.get("keyHandle")
            self.assertEqual(u2f_sign_request.get("version"), "U2F_V2")

        # private key from the registration example
        privkey = "9a9684b127c5e3a706d618c86401c7cf6fd827fd0bc18d24b0eb842e36d16df1"
        counter = 1
        client_data = '{"typ":"navigator.id.getAssertion",' \
                      '"challenge":"%s","cid_pubkey":{"kty":"EC",' \
                      '"crv":"P-256",' \
                      '"x":"HzQwlfXX7Q4S5MtCCnZUNBw3RMzPO9tOyWjBqRl4tJ8",' \
                      '"y":"XVguGFLIZx1fXg3wNqfdbn75hi4-_7-BxhMljw42Ht4"},' \
                      '"origin":"%s"}' % (challenge, app_id)
        signature_hex = sign_challenge(privkey, app_id, client_data, counter)
        signature_data_hex = "0100000001" + signature_hex
        signature_data_url = url_encode(binascii.unhexlify(signature_data_hex))
        client_data_url = url_encode(client_data)
        # Send the response. Unfortunately it does not fit to the
        # registration, so we create a BadSignatureError
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={"user": "******",
                                                 "realm": self.realm1,
                                                 "pass": "",
                                                 "transaction_id":
                                                     transaction_id,
                                                 "clientdata": client_data_url,
                                                 "signaturedata":
                                                     signature_data_url}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = json.loads(res.data).get("result")
            detail = json.loads(res.data).get("detail")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), False)
Example #30
0
    def test_02_validate(self):
        # assign token to user
        r = assign_token(self.serial,
                         User("cornelius", self.realm1),
                         pin="u2f")
        self.assertEqual(r, True)

        # Issue challenge
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "user":
                                               "******" + self.realm1,
                                               "pass": "******"
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = json.loads(res.data).get("result")
            detail = json.loads(res.data).get("detail")
            self.assertEqual(result.get("value"), False)
            transaction_id = detail.get("transaction_id")
            self.assertEqual(len(transaction_id), len('01350277175811850842'))
            self.assertTrue(
                "Please confirm with your U2F token" in detail.get("message"),
                detail.get("message"))
            attributes = detail.get("attributes")
            u2f_sign_request = attributes.get("u2fSignRequest")
            self.assertTrue("appId" in u2f_sign_request)
            app_id = u2f_sign_request.get("appId")
            self.assertTrue("challenge" in u2f_sign_request)
            challenge = u2f_sign_request.get("challenge")
            self.assertTrue("keyHandle" in u2f_sign_request)
            key_handle = u2f_sign_request.get("keyHandle")
            self.assertEqual(u2f_sign_request.get("version"), "U2F_V2")

        # private key from the registration example
        privkey = "9a9684b127c5e3a706d618c86401c7cf6fd827fd0bc18d24b0eb842e36d16df1"
        counter = 1
        client_data = '{"typ":"navigator.id.getAssertion",' \
                      '"challenge":"%s","cid_pubkey":{"kty":"EC",' \
                      '"crv":"P-256",' \
                      '"x":"HzQwlfXX7Q4S5MtCCnZUNBw3RMzPO9tOyWjBqRl4tJ8",' \
                      '"y":"XVguGFLIZx1fXg3wNqfdbn75hi4-_7-BxhMljw42Ht4"},' \
                      '"origin":"%s"}' % (challenge, app_id)
        signature_hex = sign_challenge(privkey, app_id, client_data, counter)
        signature_data_hex = "0100000001" + signature_hex
        signature_data_url = url_encode(binascii.unhexlify(signature_data_hex))
        client_data_url = url_encode(client_data)
        # Send the response. Unfortunately it does not fit to the
        # registration, so we create a BadSignatureError
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "user": "******",
                                               "realm": self.realm1,
                                               "pass": "",
                                               "transaction_id":
                                               transaction_id,
                                               "clientdata": client_data_url,
                                               "signaturedata":
                                               signature_data_url
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = json.loads(res.data).get("result")
            detail = json.loads(res.data).get("detail")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), False)