Example #1
0
    def test_17_auth_timelimit_success(self):
        user = User("timelimituser", realm=self.realm2)
        pin = "spass"
        # create a token
        token = init_token({"type": "spass",
                            "pin": pin}, user=user)

        # set policy for timelimit
        set_policy(name="pol_time1",
                   scope=SCOPE.AUTHZ,
                   action="%s=2/20s" % ACTION.AUTHMAXSUCCESS)

        for i in [1, 2]:
            with self.app.test_request_context('/validate/check',
                                               method='POST',
                                               data={"user": "******",
                                                     "realm": self.realm2,
                                                     "pass": pin}):
                res = self.app.full_dispatch_request()
                self.assertTrue(res.status_code == 200, res)
                result = json.loads(res.data).get("result")
                self.assertEqual(result.get("value"), True)

        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={"user": "******",
                                                 "realm": self.realm2,
                                                 "pass": pin}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertEqual(result.get("value"), False)

        delete_policy("pol_time1")
        remove_token(token.token.serial)
Example #2
0
    def test_18_auth_timelimit_fail(self):
        user = User("timelimituser", realm=self.realm2)
        pin = "spass"
        # create a token
        token = init_token({"type": "spass", "pin": pin}, user=user)

        # set policy for timelimit
        set_policy(name="pol_time1", scope=SCOPE.AUTHZ, action="%s=2/20s" % ACTION.AUTHMAXFAIL)

        for i in [1, 2]:
            with self.app.test_request_context(
                "/validate/check",
                method="POST",
                data={"user": "******", "realm": self.realm2, "pass": "******"},
            ):
                res = self.app.full_dispatch_request()
                self.assertTrue(res.status_code == 200, res)
                result = json.loads(res.data).get("result")
                self.assertEqual(result.get("value"), False)

        # Now we do the correct authentication, but
        # as already two authentications failed, this will fail, too
        with self.app.test_request_context(
            "/validate/check", method="POST", data={"user": "******", "realm": self.realm2, "pass": pin}
        ):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertEqual(result.get("value"), False)
            details = json.loads(res.data).get("detail")
            self.assertEqual(details.get("message"), "Only 2 failed authentications per 0:00:20")

        delete_policy("pol_time1")
        remove_token(token.token.serial)
    def test_16_init_token_defaults(self):
        g.logged_in_user = {"username": "******",
                            "role": "user"}
        builder = EnvironBuilder(method='POST',
                                 data={'type': "totp",
                                       "genkey": "1"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        g.client_ip = env["REMOTE_ADDR"]
        req = Request(env)

        # Set a policy that defines the default totp settings
        set_policy(name="pol1",
                   scope=SCOPE.USER,
                   action="totp_otplen=8,totp_hashlib=sha256,totp_timestep=60")
        g.policy_object = PolicyClass()

        # request, that matches the policy
        req.all_data = {
            "type": "totp",
            "genkey": "1"}
        init_token_defaults(req)

        # Check, if the token defaults were added
        self.assertEqual(req.all_data.get("totp.hashlib"), "sha256")
        self.assertEqual(req.all_data.get("otplen"), "8")
        self.assertEqual(req.all_data.get("timeStep"), "60")
        # finally delete policy
        delete_policy("pol1")
Example #4
0
    def test_14_required_email(self):
        g.logged_in_user = {"username": "******",
                            "role": "admin"}
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "OATH123456"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)
        # Set a mangle policy to change the username
        # and only use the last 4 characters of the username
        set_policy(name="email1",
                   scope=SCOPE.REGISTER,
                   action="%s=/.*@mydomain\..*" % ACTION.REQUIREDEMAIL)
        g.policy_object = PolicyClass()
        # request, that matches the policy
        req.all_data = {"email": "*****@*****.**"}
        # This emails is allowed
        r = required_email(req)
        self.assertTrue(r)

        # This email is not allowed
        req.all_data = {"email": "*****@*****.**"}
        # This emails is allowed
        self.assertRaises(RegistrationError, required_email, req)

        delete_policy("email1")
        g.policy_object = PolicyClass()
        # Without a policy, this email can register
        req.all_data = {"email": "*****@*****.**"}
        # This emails is allowed
        r = required_email(req)
        self.assertTrue(r)
    def test_01_otppin(self):
        my_user = User("cornelius", realm="r1")
        set_policy(name="pol1", scope=SCOPE.AUTH, action="%s=%s" % (ACTION.OTPPIN, ACTIONVALUE.NONE))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        options = {"g": g}

        # NONE with empty PIN -> success
        r = auth_otppin(self.fake_check_otp, None, "", options=options, user=my_user)
        self.assertTrue(r)
        # NONE with empty PIN -> success, even if the authentication is done
        # for a serial and not a user, since the policy holds for all realms
        token = init_token({"type": "HOTP", "otpkey": "1234"})
        r = auth_otppin(self.fake_check_otp, token, "", options=options, user=None)
        self.assertTrue(r)

        # NONE with some pin -> fail
        r = auth_otppin(self.fake_check_otp, None, "some pin", options=options, user=my_user)
        self.assertFalse(r)

        delete_policy("pol1")
        set_policy(name="pol1", scope=SCOPE.AUTH, action="%s=%s" % (ACTION.OTPPIN, ACTIONVALUE.TOKENPIN))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        options = {"g": g}

        r = auth_otppin(self.fake_check_otp, None, "FAKE", options=options, user=my_user)
        self.assertTrue(r)
        r = auth_otppin(self.fake_check_otp, None, "Wrong Pin", options=options, user=my_user)
        self.assertFalse(r)
        delete_policy("pol1")
    def test_05_user_has_no_tokens(self):
        user = User("cornelius", realm="r1")
        passw = "test"
        options = {}
        # A user with no tokens will fail to authenticate
        rv = auth_user_has_no_token(check_user_pass, user, passw, options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"),
                         "The user has no tokens assigned")

        # Now we set a policy, that a non existing user will authenticate
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action=ACTION.PASSNOTOKEN)
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}
        rv = auth_user_has_no_token(check_user_pass, user, passw,
                                      options=options)
        self.assertTrue(rv[0])
        self.assertEqual(rv[1].get("message"),
                         u"user has no token, accepted due to "
                         u"'pol1'")
        delete_policy("pol1")
Example #7
0
    def test_07_client_policies(self):
        delete_policy(name="pol2a")
        set_policy(name="pol1", scope="s", client="172.16.0.3, 172.16.0.4/24")
        set_policy(name="pol2", scope="s", client="192.168.0.0/16, "
                                                  "-192.168.1.1")
        set_policy(name="pol3", scope="s", client="10.0.0.1, 10.0.0.2, "
                                                  "10.0.0.3")
        set_policy(name="pol4", scope="s")

        # One policy with matching client, one without any clients
        P = PolicyClass()
        p = P.get_policies(client="10.0.0.1")
        self.assertTrue(_check_policy_name("pol3", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)
        self.assertTrue(len(p) == 2, p)

        # client matches pol4 and pol2
        p = P.get_policies(client="192.168.2.3")
        self.assertTrue(_check_policy_name("pol2", p), p)
        self.assertTrue(_check_policy_name("pol4", p), p)
        self.assertTrue(len(p) == 2, p)

        # client only matches pol4, since it is excluded in pol2
        p = P.get_policies(client="192.168.1.1")
        self.assertTrue(_check_policy_name("pol4", p), p)
        self.assertTrue(len(p) == 1, p)
    def test_04a_user_does_not_exist_without_resolver(self):
        user = User("MisterX", realm=self.realm1)
        passw = "somePW"

        # Now we set a policy, that a non existing user will authenticate
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0}, {1}, {2}, {3}=none".format(
                       ACTION.RESETALLTOKENS,
                       ACTION.PASSNOUSER,
                       ACTION.PASSNOTOKEN,
                       ACTION.OTPPIN
                   ),
                   realm=self.realm1)
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}
        rv = auth_user_does_not_exist(check_user_pass, user, passw,
                                      options=options)
        self.assertTrue(rv[0])
        self.assertEqual(rv[1].get("message"),
                         u"user does not exist, accepted due "
                         u"to 'pol1'")
        delete_policy("pol1")
Example #9
0
    def test_08_encrypt_pin(self):
        g.logged_in_user = {"username": "******",
                            "role": "admin"}
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "OATH123456"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)

        # Set a policy that defines the PIN to be encrypted
        set_policy(name="pol1",
                   scope=SCOPE.ENROLL,
                   action=ACTION.ENCRYPTPIN)
        g.policy_object = PolicyClass()

        # request, that matches the policy
        req.all_data = {
                        "user": "******",
                        "realm": "home"}
        encrypt_pin(req)

        # Check, if the tokenlabel was added
        self.assertEqual(req.all_data.get("encryptpin"), "True")
        # finally delete policy
        delete_policy("pol1")
Example #10
0
    def test_13_remote_user(self):
        g.logged_in_user = {"username": "******",
                            "role": "admin"}
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "OATH123456"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        env["REMOTE_USER"] = "******"
        req = Request(env)

        # A user, for whom the login via REMOTE_USER is allowed.
        set_policy(name="ruser",
                   scope=SCOPE.WEBUI,
                   action="%s=%s" % (ACTION.REMOTE_USER, REMOTE_USER.ACTIVE))
        g.policy_object = PolicyClass()

        r = is_remote_user_allowed(req)
        self.assertEqual(r, [REMOTE_USER.ACTIVE])

        # Login for the REMOTE_USER is not allowed.
        # Only allowed for user "super", but REMOTE_USER=admin
        set_policy(name="ruser",
                   scope=SCOPE.WEBUI,
                   action="%s=%s" % (ACTION.REMOTE_USER, REMOTE_USER.ACTIVE),
                   user="******")
        g.policy_object = PolicyClass()

        r = is_remote_user_allowed(req)
        self.assertEqual(r, [])

        delete_policy("ruser")
    def test_03_otppin_for_serial(self):
        # now create a policy with userstore PW
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="%s=%s" % (ACTION.OTPPIN, ACTIONVALUE.USERSTORE))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        options = {"g": g,
                   "serial": "T001"}

        # create a token and assign to user cornelius
        token = init_token({"serial": "T001", "type": "hotp", "genkey": 1},
                           user=User("cornelius", realm="r1"))
        self.assertTrue(token)

        # Wrong password
        # Not identified by the user but by the token owner
        r = auth_otppin(self.fake_check_otp, token,
                          "WrongPW", options=options,
                          user=None)
        self.assertFalse(r)

        # Correct password from userstore: "test"
        # Not identified by the user but by the token owner
        r = auth_otppin(self.fake_check_otp, token,
                          "test", options=options,
                          user=None)
        self.assertTrue(r)
        delete_policy("pol1")
        remove_token("T001")
    def test_02_userstore_password(self):
        # create a realm, where cornelius has a password test
        rid = save_resolver({"resolver": "myreso",
                             "type": "passwdresolver",
                             "fileName": PWFILE2})
        self.assertTrue(rid > 0, rid)

        (added, failed) = set_realm("r1", ["myreso"])
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 1)

        # now create a policy with userstore PW
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="%s=%s" % (ACTION.OTPPIN, ACTIONVALUE.USERSTORE))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        options = {"g": g}

        # Wrong password
        r = auth_otppin(self.fake_check_otp, None,
                          "WrongPW", options=options,
                          user=User("cornelius", realm="r1"))
        self.assertFalse(r)

        # Correct password from userstore: "test"
        r = auth_otppin(self.fake_check_otp, None,
                          "test", options=options,
                          user=User("cornelius", realm="r1"))
        self.assertTrue(r)
        delete_policy("pol1")
    def test_09_challenge_response_allowed(self):
        user = User("cornelius", realm="r1")
        pin = "test"

        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        options = {"g": g}
        token = init_token({"type": "hotp",
                            "otpkey": "1234",
                            "pin": pin}, user=user)
        # With no policy, it will be no chal resp
        rv = token.is_challenge_request(pin, user=user, options=options)
        self.assertEqual(rv, False)

        # Now we set a policy with several tokentypes
        set_policy(name="pol_chal_resp_1",
                   scope=SCOPE.AUTH,
                   action="%s=hotp tiqr totp" % ACTION.CHALLENGERESPONSE)
        set_policy(name="pol_chal_resp_2",
                   scope=SCOPE.AUTH,
                   action="%s=hotp motp" % ACTION.CHALLENGERESPONSE)
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        options = {"g": g}
        rv = token.is_challenge_request(pin, user=user, options=options)
        self.assertEqual(rv, True)
        delete_policy("pol_chal_resp_1")
Example #14
0
    def test_01a_admin_realms(self):
        admin1 = {"username": "******",
                  "role": "admin",
                  "realm": "realm1"}

        admin2 = {"username": "******",
                  "role": "admin",
                  "realm": "realm2"}

        set_policy(name="pol",
                   scope=SCOPE.ADMIN,
                   action="*", adminrealm="realm1")
        g.policy_object = PolicyClass()
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "OATH123456"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)
        req.all_data = {}

        # admin1 is allowed to do everything
        g.logged_in_user = admin1
        r = check_base_action(req, action="delete")
        self.assertTrue(r)

        # admin2 is not allowed.
        g.logged_in_user = admin2
        self.assertRaises(PolicyError, check_base_action, req, action="delete")
        delete_policy("pol")
    def test_19_validate_passthru(self):
        # user passthru, realm: self.realm2, passwd: pthru
        set_policy(name="pthru", scope=SCOPE.AUTH, action=ACTION.PASSTHRU)

        # Passthru with GET request
        with self.app.test_request_context(
                '/validate/check',
                method='GET',
                query_string=urlencode({"user": "******",
                                        "realm": self.realm2,
                                        "pass": "******"})):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertEqual(result.get("value"), True)

        # Passthru with POST Request
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={"user": "******",
                                                 "realm": self.realm2,
                                                 "pass": "******"}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertEqual(result.get("value"), True)

        delete_policy("pthru")
Example #16
0
    def test_06_set_tokenlabel(self):
        g.logged_in_user = {"username": "******",
                            "role": "admin"}
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "OATH123456"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)

        # Set a policy that defines the tokenlabel
        set_policy(name="pol1",
                   scope=SCOPE.ENROLL,
                   action="%s=%s" % (ACTION.TOKENLABEL, "<u>@<r>"))
        set_policy(name="pol2",
                   scope=SCOPE.ENROLL,
                   action="%s=%s" % (ACTION.TOKENISSUER, "myPI"))
        g.policy_object = PolicyClass()

        # request, that matches the policy
        req.all_data = {
                        "user": "******",
                        "realm": "home"}
        init_tokenlabel(req)

        # Check, if the tokenlabel was added
        self.assertEqual(req.all_data.get("tokenlabel"), "<u>@<r>")
        # Check, if the tokenissuer was added
        self.assertEqual(req.all_data.get("tokenissuer"), "myPI")
        # finally delete policy
        delete_policy("pol1")
        delete_policy("pol2")
Example #17
0
    def test_03_check_token_upload(self):
        g.logged_in_user = {"username": "******",
                            "role": "admin"}
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "OATH123456"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)
        req.all_data = {"filename": "token.xml"}

        # Set a policy, that does allow the action
        set_policy(name="pol1",
                   scope=SCOPE.ADMIN,
                   action="enrollTOTP, enrollHOTP, %s" % ACTION.IMPORT,
                   client="10.0.0.0/8")
        g.policy_object = PolicyClass()

        # Try to import tokens
        r = check_token_upload(req)
        self.assertTrue(r)

        # The admin can not upload from another IP address
        # An exception is raised
        env["REMOTE_ADDR"] = "192.168.0.1"
        req = Request(env)
        req.all_data = {"filename": "token.xml"}
        self.assertRaises(PolicyError,
                          check_token_upload, req)
        # finally delete policy
        delete_policy("pol1")
Example #18
0
    def test_22_validate_locked(self):
        # test a user with two tokens
        # One token is locked/revoked.
        #  But the user must be able to login with the 2nd token
        # user lockeduser, realm: self.realm2
        # enroll two tokens
        user = "******"
        set_policy(name="locked",
                   scope=SCOPE.AUTH,
                   action="{0!s}={1!s}".format(ACTION.OTPPIN, "tokenpin"))
        r = init_token({"type": "spass", "serial": "spass1l",
                        "pin": "locked"},
                       user=User(user, self.realm2))
        r = init_token({"type": "spass", "serial": "spass2l",
                        "pin": "locked"},
                       user=User(user, self.realm2))
        # disable first token
        r = revoke_token("spass1l")
        self.assertEqual(r, True)
        # Check that the user still can authenticate with the 2nd token
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={"user": user,
                                                 "realm": self.realm2,
                                                 "pass": "******"}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertEqual(result.get("value"), True)

        remove_token("spass1l")
        remove_token("spass2l")
        delete_policy("locked")
Example #19
0
    def test_07_set_random_pin(self):
        g.logged_in_user = {"username": "******",
                            "role": "admin"}
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "OATH123456"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)

        # Set a policy that defines the tokenlabel
        set_policy(name="pol1",
                   scope=SCOPE.ENROLL,
                   action="%s=%s" % (ACTION.OTPPINRANDOM, "12"))
        set_policy(name="pinhandling",
                   scope=SCOPE.ENROLL,
                   action="%s=privacyidea.lib.pinhandling.base.PinHandler" %
                          ACTION.PINHANDLING)
        g.policy_object = PolicyClass()

        # request, that matches the policy
        req.all_data = {
                        "user": "******",
                        "realm": "home"}
        init_random_pin(req)

        # Check, if the tokenlabel was added
        self.assertEqual(len(req.all_data.get("pin")), 12)
        # finally delete policy
        delete_policy("pol1")
        delete_policy("pinhandling")
    def test_06_passthru(self):
        user = User("cornelius", realm="r1")
        passw = "test"
        options = {}
        # A user with no tokens will fail to authenticate
        self.assertEqual(get_tokens(user=user, count=True), 0)
        rv = auth_user_passthru(check_user_pass, user, passw, options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"), "The user has no tokens assigned")

        # Now we set a PASSTHRU policy, so that the user may authenticate
        # against his userstore
        set_policy(name="pol1", scope=SCOPE.AUTH, action=ACTION.PASSTHRU)
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        options = {"g": g}
        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertEqual(
            rv[1].get("message"), u"The user authenticated against his userstore " u"according to policy 'pol1'."
        )

        # Now assign a token to the user. If the user has a token and the
        # passthru policy is set, the user must not be able to authenticate
        # with his userstore password.
        init_token({"serial": "PTHRU", "type": "spass", "pin": "Hallo"}, user=user)
        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"), "wrong otp pin")

        remove_token("PTHRU")
        delete_policy("pol1")
Example #21
0
    def test_03_no_detail_on_success(self):
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "HOTP123435"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)
        # The response contains the token type SPASS
        res = {"jsonrpc": "2.0",
               "result": {"status": True,
                          "value": True},
               "version": "privacyIDEA test",
               "id": 1,
               "detail": {"message": "matching 1 tokens",
                          "serial": "HOTP123456",
                          "type": "hotp"}}
        resp = Response(json.dumps(res))

        # Set a policy, that does not allow the detail on success
        set_policy(name="pol2",
                   scope=SCOPE.AUTHZ,
                   action="no_detail_on_success", client="10.0.0.0/8")
        g.policy_object = PolicyClass()

        new_response = no_detail_on_success(req, resp)
        jresult = json.loads(new_response.data)
        self.assertTrue("detail" not in jresult, jresult)
        delete_policy("pol2")
    def test_01_challenge(self):

        set_policy("chalresp", scope=SCOPE.AUTHZ,
                   action="{0!s}=hotp".format(ACTION.CHALLENGERESPONSE))
        token = init_token({"genkey": 1, "serial": "CHAL1", "pin": "pin"})
        from privacyidea.lib.token import check_serial_pass
        r = check_serial_pass(token.token.serial, "pin")
        # The OTP PIN is correct
        self.assertEqual(r[0], False)
        self.assertEqual(r[1].get("message"), "please enter otp: ")
        transaction_id = r[1].get("transaction_id")
        chals = get_challenges()
        self.assertEqual(len(chals), 1)
        self.assertEqual(chals[0].transaction_id, transaction_id)

        # get challenge for this serial
        chals = get_challenges(serial="CHAL1")
        self.assertEqual(len(chals), 1)
        self.assertEqual(chals[0].transaction_id, transaction_id)

        # get challenge for another seial
        chals = get_challenges(serial="CHAL2")
        self.assertEqual(len(chals), 0)

        delete_policy("chalresp")
    def test_04_check_max_token_user(self):
        g.logged_in_user = {"username": "******",
                            "role": "admin"}
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "OATH123456"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        g.client_ip = env["REMOTE_ADDR"]
        req = Request(env)
        req.all_data = {"user": "******",
                        "realm": self.realm1}

        # Set a policy, that allows two tokens per user
        set_policy(name="pol1",
                   scope=SCOPE.ENROLL,
                   action="{0!s}={1!s}".format(ACTION.MAXTOKENUSER, 2))
        g.policy_object = PolicyClass()
        # The user has one token, everything is fine.
        self.setUp_user_realms()
        tokenobject = init_token({"serial": "NEW001", "type": "hotp",
                                  "otpkey": "1234567890123456"},
                                  user=User(login="******",
                                            realm=self.realm1))
        tokenobject_list = get_tokens(user=User(login="******",
                                           realm=self.realm1))
        self.assertTrue(len(tokenobject_list) == 1)
        self.assertTrue(check_max_token_user(req))

        # Now the user gets his second token
        tokenobject = init_token({"serial": "NEW002", "type": "hotp",
                                  "otpkey": "1234567890123456"},
                                  user=User(login="******",
                                            realm=self.realm1))
        tokenobject_list = get_tokens(user=User(login="******",
                                           realm=self.realm1))
        self.assertTrue(len(tokenobject_list) == 2)

        # The user has two tokens. The check that will run in this case,
        # before the user would be assigned the 3rd token, will raise a
        # PolicyError
        self.assertRaises(PolicyError,
                          check_max_token_user, req)


        # The check for a token, that has no username in it, must not
        # succeed. I.e. in the realm new tokens must be enrollable.
        req.all_data = {}
        self.assertTrue(check_max_token_user(req))

        req.all_data = {"realm": self.realm1}
        self.assertTrue(check_max_token_user(req))

        # finally delete policy
        delete_policy("pol1")
        remove_token("NEW001")
        remove_token("NEW002")
    def test_05_autoassign_any_pin(self):
        # init a token, that does has no uwser
        self.setUp_user_realms()
        tokenobject = init_token({"serial": "UASSIGN1", "type": "hotp",
                                  "otpkey": "3132333435363738393031"
                                            "323334353637383930"},
                                 tokenrealms=[self.realm1])

        user_obj = User("autoassignuser", self.realm1)
        # unassign all tokens from the user autoassignuser
        try:
            unassign_token(None, user=user_obj)
        except Exception:
            print("no need to unassign token")

        # The request with an OTP value and a PIN of a user, who has not
        # token assigned
        builder = EnvironBuilder(method='POST',
                                 data={},
                                 headers={})
        env = builder.get_environ()
        env["REMOTE_ADDR"] = "10.0.0.1"
        g.client_ip = env["REMOTE_ADDR"]
        req = Request(env)
        req.all_data = {"user": "******", "realm": self.realm1,
                        "pass": "******"}
        # The response with a failed request
        res = {"jsonrpc": "2.0",
               "result": {"status": True,
                          "value": False},
               "version": "privacyIDEA test",
               "id": 1}
        resp = Response(json.dumps(res))

        # Set the autoassign policy
        # to "any_pin"
        set_policy(name="pol2",
                   scope=SCOPE.ENROLL,
                   action="{0!s}={1!s}".format(ACTION.AUTOASSIGN, AUTOASSIGNVALUE.NONE),
                                     client="10.0.0.0/8")
        g.policy_object = PolicyClass()

        new_response = autoassign(req, resp)
        jresult = json.loads(new_response.data)
        self.assertTrue(jresult.get("result").get("value"), jresult)
        self.assertEqual(jresult.get("detail").get("serial"), "UASSIGN1")

        # test the token with test287082 will fail
        res, dict = check_user_pass(User("autoassignuser", self.realm1),
                                    "test287082")
        self.assertFalse(res)

        # test the token with test359152 will succeed
        res, dict = check_user_pass(User("autoassignuser", self.realm1),
                                    "test359152")
        self.assertTrue(res)

        delete_policy("pol2")
    def test_14_otppin_priority(self):
        my_user = User("cornelius", realm="r1")
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}={1!s}".format(ACTION.OTPPIN, ACTIONVALUE.NONE),
                   priority=2)
        set_policy(name="pol2",
                   scope=SCOPE.AUTH,
                   action="{0!s}={1!s}".format(ACTION.OTPPIN, ACTIONVALUE.TOKENPIN),
                   priority=2)
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # error because of conflicting policies
        with self.assertRaises(PolicyError):
            auth_otppin(self.fake_check_otp, None,
                        "", options=options, user=my_user)

        # lower pol2 priority
        set_policy(name="pol2",
                   priority=3)
        g.policy_object.reload_from_db()

        # NONE with empty PIN -> success
        r = auth_otppin(self.fake_check_otp, None,
                        "", options=options, user=my_user)
        self.assertTrue(r)
        # NONE with empty PIN -> success, even if the authentication is done
        # for a serial and not a user, since the policy holds for all realms
        token = init_token({"type": "HOTP", "otpkey": "1234"})
        r = auth_otppin(self.fake_check_otp, token,
                        "", options=options, user=None)
        self.assertTrue(r)

        # NONE with some pin -> fail
        r = auth_otppin(self.fake_check_otp, None,
                        "some pin", options=options, user=my_user)
        self.assertFalse(r)

        # increase pol2 priority
        set_policy(name="pol2", priority=1)
        g.policy_object.reload_from_db()

        r = auth_otppin(self.fake_check_otp, None,
                        "FAKE", options=options,
                        user=my_user)
        self.assertTrue(r)
        r = auth_otppin(self.fake_check_otp, None,
                        "Wrong Pin", options=options,
                        user=my_user)
        self.assertFalse(r)
        delete_policy("pol1")
        delete_policy("pol2")
    def test_08_get_webui_settings(self):
        # Test that a machine definition will return offline hashes
        self.setUp_user_realms()
        serial = "offline01"
        tokenobject = init_token({"serial": serial, "type": "hotp",
                                  "otpkey": "3132333435363738393031"
                                            "323334353637383930",
                                  "pin": "offline",
                                  "user": "******"})

        # Set the Machine and MachineToken
        resolver1 = save_resolver({"name": "reso1",
                                   "type": "hosts",
                                   "filename": HOSTSFILE})

        mt = attach_token(serial, "offline", hostname="gandalf")
        self.assertEqual(mt.token.serial, serial)
        self.assertEqual(mt.token.machine_list[0].machine_id, "192.168.0.1")

        # The request with an OTP value and a PIN of a user, who has not
        # token assigned
        builder = EnvironBuilder(method='POST',
                                 data={},
                                 headers={})
        env = builder.get_environ()
        env["REMOTE_ADDR"] = "192.168.0.1"
        g.client_ip = env["REMOTE_ADDR"]
        req = Request(env)
        req.all_data = {"user": "******",
                        "pass": "******"}

        res = {"jsonrpc": "2.0",
               "result": {"status": True,
                          "value": {"role": "user",
                                    "username": "******"}},
               "version": "privacyIDEA test",
               "detail": {"serial": serial},
               "id": 1}
        resp = Response(json.dumps(res))

        new_response = get_webui_settings(req, resp)
        jresult = json.loads(new_response.data)
        self.assertEqual(jresult.get("result").get("value").get(
            "token_wizard"), False)

        # Set a policy. User has not token, so "token_wizard" will be True
        set_policy(name="pol_wizard",
                   scope=SCOPE.WEBUI,
                   action=ACTION.TOKENWIZARD)
        g.policy_object = PolicyClass()
        new_response = get_webui_settings(req, resp)
        jresult = json.loads(new_response.data)
        self.assertEqual(jresult.get("result").get("value").get(
            "token_wizard"), True)

        delete_policy("pol_wizard")
Example #27
0
    def test_16_admin_realm(self):
        P = PolicyClass()
        logged_in_user = {"username": "******",
                          "role": "admin",
                          "realm": "realm1"}
        # Without policies, the admin gets all
        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertTrue("hotp" in tt)
        self.assertTrue("totp" in tt)
        self.assertTrue("motp" in tt)
        self.assertTrue("sms" in tt)
        self.assertTrue("spass" in tt)
        self.assertTrue("sshkey" in tt)
        self.assertTrue("email" in tt)
        self.assertTrue("certificate" in tt)
        self.assertTrue("yubico" in tt)
        self.assertTrue("yubikey" in tt)
        self.assertTrue("radius" in tt)

        # An admin in realm1 may only enroll Yubikeys
        set_policy(name="tokenEnroll", scope=SCOPE.ADMIN,
                   adminrealm="realm1",
                   action="enrollYUBIKEY")
        P = PolicyClass()

        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertFalse("hotp" in tt)
        self.assertFalse("totp" in tt)
        self.assertFalse("motp" in tt)
        self.assertFalse("sms" in tt)
        self.assertFalse("spass" in tt)
        self.assertFalse("sshkey" in tt)
        self.assertFalse("email" in tt)
        self.assertFalse("certificate" in tt)
        self.assertFalse("yubico" in tt)
        self.assertTrue("yubikey" in tt)
        self.assertFalse("radius" in tt)

        # An admin in another admin realm may enroll nothing.
        logged_in_user = {"username": "******",
                          "role": "admin",
                          "realm": "OtherRealm"}
        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertFalse("hotp" in tt)
        self.assertFalse("totp" in tt)
        self.assertFalse("motp" in tt)
        self.assertFalse("sms" in tt)
        self.assertFalse("spass" in tt)
        self.assertFalse("sshkey" in tt)
        self.assertFalse("email" in tt)
        self.assertFalse("certificate" in tt)
        self.assertFalse("yubico" in tt)
        self.assertFalse("yubikey" in tt)
        self.assertFalse("radius" in tt)
        delete_policy("tokenEnroll")
Example #28
0
    def test_06_u2f_enrollment_fails_wrong_issuer(self):
        # test data taken from
        # https://fidoalliance.org/specs/fido-u2f-v1.0-ps-20141009/fido-u2f-raw-message-formats-ps-20141009.html#examples
        serial = "U2F0010BF6F"
        set_privacyidea_config("u2f.appId",
                               "https://puck.az.intern")
        pin = "test"
        # Registration data
        client_data = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6ImpIakIxaEM2VjA3dDl4ZnNNaDRfOEQ3U1JuSHRFY1BqUTdsaVl3cWxkX009Iiwib3JpZ2luIjoiaHR0cHM6Ly9wdWNrLmF6LmludGVybiIsImNpZF9wdWJrZXkiOiJ1bnVzZWQifQ"
        reg_data = "BQRHjwxEYFCkLHz3xdrmifKOHl2h17BmRJQ_S1Y9PRAhS2R186T391YE-ryqWis9HSmdp0XpRqUaKk9L8lxJTPpTQF_xFJ_LAsKkPTzKIwUlPIjGZDsLmv0en2Iya17Yz8X8OS89fuxwZOvEok-NQOKUTJP3att_RVe3dEAbq_iOtyAwggJEMIIBLqADAgECAgRVYr6gMAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTQzMjUzNDY4ODBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEszH3c9gUS5mVy-RYVRfhdYOqR2I2lcvoWsSCyAGfLJuUZ64EWw5m8TGy6jJDyR_aYC4xjz_F2NKnq65yvRQwmjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS41MBMGCysGAQQBguUcAgEBBAQDAgUgMAsGCSqGSIb3DQEBCwOCAQEArBbZs262s6m3bXWUs09Z9Pc-28n96yk162tFHKv0HSXT5xYU10cmBMpypXjjI-23YARoXwXn0bm-BdtulED6xc_JMqbK-uhSmXcu2wJ4ICA81BQdPutvaizpnjlXgDJjq6uNbsSAp98IStLLp7fW13yUw-vAsWb5YFfK9f46Yx6iakM3YqNvvs9M9EUJYl_VrxBJqnyLx2iaZlnpr13o8NcsKIJRdMUOBqt_ageQg3ttsyq_3LyoNcu7CQ7x8NmeCGm_6eVnZMQjDmwFdymwEN4OxfnM5MkcKCYhjqgIGruWkVHsFnJa8qjZXneVvKoiepuUQyDEJ2GcqvhU2YKY1zBFAiEA4ZkIXXyjEPExcMGtW6kJXqYv7UHgjxJR5h3H9w9FV7gCIFGdhxZDqwCQKplDi-LU4WJ45OyCpNK6lGa72eZqUR_k"
        # Authentication data
        transaction_id = "05871369157706202013"
        challenge = "1616515928c389ba9e028d83eb5f63782cbf351ca6abbc81aeb0dddd4895b609"
        # challenge = "FhZRWSjDibqeAo2D619jeCy_NRymq7yBrrDd3UiVtgk"
        key_handle = "X_EUn8sCwqQ9PMojBSU8iMZkOwua_R6fYjJrXtjPxfw5Lz1-7HBk68SiT41A4pRMk_dq239FV7d0QBur-I63IA"
        client_data_auth = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoiRmhaUldTakRpYnFlQW8yRDYxOWplQ3lfTlJ5bXE3eUJyckRkM1VpVnRnayIsIm9yaWdpbiI6Imh0dHBzOi8vcHVjay5hei5pbnRlcm4iLCJjaWRfcHVia2V5IjoidW51c2VkIn0"
        signature_data = "AQAAAAMwRQIgU8d6waOIRVVydg_AXxediEZGkfFioUjd6FG3OxH2wUMCIQDpxzavJyxRlMwgNmD1Kw-iw_oP2egdshU9hrpxFHTRzQ"

        # step 1
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={"type": "u2f",
                                                 "user": "******",
                                                 "realm": self.realm1,
                                                 "serial": serial},
                                           headers={'Authorization': self.at}):
            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"), True)

        set_policy(name="u2f01", scope=SCOPE.ENROLL,
                   action="{0!s}=issuer/.*Plugup.*/".format(U2FACTION.REQ))

        # Init step 2
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={"type": "u2f",
                                                 "serial": serial,
                                                 "regdata": reg_data,
                                                 "clientdata": client_data},
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 403)
            result = json.loads(res.data).get("result")
            detail = json.loads(res.data).get("detail")
            self.assertEqual(result.get("status"), False)
            self.assertEqual(result.get("error").get("message"),
                             u'The U2F device is not allowed to be registered '
                             u'due to policy restriction.')

        delete_policy("u2f01")
        remove_token(serial)
    def test_07_login_mode(self):
        # a realm: cornelius@r1: PW: test

        def check_webui_user_userstore(user_obj, password,
                                       options=None, superuser_realms=None,
                                       check_otp=False):
            self.assertEqual(check_otp, False)

        def check_webui_user_privacyidea(user_obj, password,
                                         options=None, superuser_realms=None,
                                         check_otp=False):
            self.assertEqual(check_otp, True)

        user_obj = User("cornelius", "r1")

        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # No policy, the function is called with check_otp=False
        login_mode(check_webui_user_userstore, user_obj, "",
                   options=options, superuser_realms="", check_otp=False)

        set_policy(name="pol2",
                   scope=SCOPE.WEBUI,
                   action="{0!s}={1!s}".format(ACTION.LOGINMODE, LOGINMODE.PRIVACYIDEA))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # Policy is set, the function is called with check_otp=True
        login_mode(check_webui_user_privacyidea, user_obj, "",
                   options=options, superuser_realms="", check_otp=False)

        # Set policy, so that the user is not allowed to login at all
        set_policy(name="pol2",
                   scope=SCOPE.WEBUI,
                   action="{0!s}={1!s}".format(ACTION.LOGINMODE, LOGINMODE.DISABLE))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # Policy is set. Trying to login raises a policy error
        self.assertRaises(PolicyError, login_mode,
                          check_webui_user_privacyidea, user_obj, "",
                          options=options, superuser_realms="",
                          check_otp=False)
        delete_policy("pol2")
Example #30
0
    def test_02_REMOTE_USER(self):
        # Allow remote user
        set_policy(name="remote", scope=SCOPE.WEBUI, action="%s=allowed" %
                                                            ACTION.REMOTE_USER)

        # Admin remote user
        with self.app.test_request_context('/auth', method='POST',
                                           data={"username": "******"},
                                           environ_base={"REMOTE_USER":
                                                             "******"}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertTrue("token" in result.get("value"))
            self.assertTrue("username" in result.get("value"))
            self.assertEqual(result.get("value").get("role"), "admin")
            self.assertTrue(result.get("status"), res.data)

        self.setUp_user_realms()
        # User "cornelius" from the default realm as normale user
        with self.app.test_request_context('/auth', method='POST',
                                           data={"username": "******"},
                                           environ_base={"REMOTE_USER":
                                                             "******"}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertTrue("token" in result.get("value"))
            self.assertTrue("username" in result.get("value"))
            self.assertEqual(result.get("value").get("role"), "user")
            self.assertTrue(result.get("status"), res.data)

        # Define the superuser_realm: "adminrealm"
        (added, failed) = set_realm("adminrealm",
                                    [self.resolvername1])
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 1)

        # user cornelius is a member of the superuser_realm...
        with self.app.test_request_context('/auth', method='POST',
                                           data={"username":
                                                     "******"},
                                           environ_base={"REMOTE_USER":
                                                     "******"}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertTrue("token" in result.get("value"))
            self.assertTrue("username" in result.get("value"))
            # ...and will have the role admin
            self.assertEqual(result.get("value").get("role"), "admin")
            self.assertTrue(result.get("status"), res.data)

        delete_policy("remote")
Example #31
0
    def test_03_api_enroll_push_poll_only(self):
        """Enroll a poll-only push token"""
        self.authenticate()
        # Set policy for poll only
        set_policy("push1",
                   scope=SCOPE.ENROLL,
                   action="{0!s}={1!s},{2!s}={3!s},{4!s}={5!s}".format(
                       PUSH_ACTION.FIREBASE_CONFIG, POLL_ONLY,
                       PUSH_ACTION.REGISTRATION_URL, REGISTRATION_URL,
                       PUSH_ACTION.TTL, TTL))

        # 1st step
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "push",
                                               "genkey": 1
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            detail = res.json.get("detail")
            serial = detail.get("serial")
            self.assertEqual(detail.get("rollout_state"), "clientwait")
            self.assertIn("pushurl", detail)
            # check that the new URL contains the serial number
            self.assertIn("&serial=PIPU", detail.get("pushurl").get("value"))
            # The firebase settings are NOT contained in the QR Code, since we do poll_only
            # poll_only
            self.assertNotIn("appid=", detail.get("pushurl").get("value"))
            self.assertNotIn("appidios=", detail.get("pushurl").get("value"))
            self.assertNotIn("apikeyios=", detail.get("pushurl").get("value"))
            self.assertNotIn("otpkey", detail)
            enrollment_credential = detail.get("enrollment_credential")

        # 2nd step: as performed by the smartphone. Also in POLL_ONLY the smartphone needs to send
        #           an empty "fbtoken"
        with self.app.test_request_context(
                '/ttype/push',
                method='POST',
                data={
                    "enrollment_credential": enrollment_credential,
                    "serial": serial,
                    "pubkey": self.smartphone_public_key_pem_urlsafe,
                    "fbtoken": ""
                }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            detail = res.json.get("detail")
            # still the same serial number
            self.assertEqual(serial, detail.get("serial"))
            self.assertEqual(detail.get("rollout_state"), "enrolled")
            # Now the smartphone gets a public key from the server
            augmented_pubkey = "-----BEGIN RSA PUBLIC KEY-----\n{}\n-----END RSA PUBLIC KEY-----\n".format(
                detail.get("public_key"))
            parsed_server_pubkey = serialization.load_pem_public_key(
                to_bytes(augmented_pubkey), default_backend())
            self.assertIsInstance(parsed_server_pubkey, rsa.RSAPublicKey)
            pubkey = detail.get("public_key")

            # Now check, what is in the token in the database
            toks = get_tokens(serial=serial)
            self.assertEqual(len(toks), 1)
            token_obj = toks[0]
            self.assertEqual(token_obj.token.rollout_state, u"enrolled")
            self.assertTrue(token_obj.token.active)
            tokeninfo = token_obj.get_tokeninfo()
            self.assertEqual(tokeninfo.get("public_key_smartphone"),
                             self.smartphone_public_key_pem_urlsafe)
            self.assertEqual(tokeninfo.get("firebase_token"), u"")
            self.assertEqual(
                tokeninfo.get("public_key_server").strip().strip(
                    "-BEGIN END RSA PUBLIC KEY-").strip(), pubkey)
            # The token should also contain the firebase config
            self.assertEqual(tokeninfo.get(PUSH_ACTION.FIREBASE_CONFIG),
                             POLL_ONLY)

        # remove the token
        remove_token(serial)
        # remove the policy
        delete_policy("push1")
Example #32
0
    def test_04_remote_user_auth(self):
        self.setUp_user_realms()
        # first check that without a remote_user policy the login fails
        with self.app.test_request_context(
                '/auth',
                method='POST',
                data={"username": "******"},
                environ_base={"REMOTE_USER": "******"}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 401, res)
            result = res.json.get("result")
            self.assertFalse(result.get("status"), result)
            self.assertEqual(result.get("error").get('code'), 4031, result)
            self.assertEqual(
                result.get("error").get('message'),
                'Authentication failure. Wrong credentials', result)
        aentry = self.find_most_recent_audit_entry(action='POST /auth')
        self.assertEqual(aentry['action'], 'POST /auth', aentry)
        self.assertEqual(aentry['success'], 0, aentry)

        # now check that with a disabled remote_user policy the login fails
        set_policy(name="remote",
                   scope=SCOPE.WEBUI,
                   action="{0!s}={1!s}".format(ACTION.REMOTE_USER,
                                               REMOTE_USER.DISABLE))
        with self.app.test_request_context(
                '/auth',
                method='POST',
                data={"username": "******"},
                environ_base={"REMOTE_USER": "******"}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 401, res)
            result = res.json.get("result")
            self.assertFalse(result.get("status"), result)
            self.assertEqual(result.get("error").get('code'), 4031, result)
            self.assertEqual(
                result.get("error").get('message'),
                'Authentication failure. Wrong credentials', result)
        aentry = self.find_most_recent_audit_entry(action='POST /auth')
        self.assertEqual(aentry['action'], 'POST /auth', aentry)
        self.assertEqual(aentry['success'], 0, aentry)
        self.assertEqual(aentry['policies'], 'remote', aentry)

        # And now check that with an enabled remote_user policy the login succeeds
        set_policy(name="remote",
                   scope=SCOPE.WEBUI,
                   action="{0!s}={1!s}".format(ACTION.REMOTE_USER,
                                               REMOTE_USER.ACTIVE))
        with self.app.test_request_context(
                '/auth',
                method='POST',
                data={"username": "******"},
                environ_base={"REMOTE_USER": "******"}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status"), result)
            self.assertEqual(result.get("value").get('role'), 'user', result)
        aentry = self.find_most_recent_audit_entry(action='POST /auth')
        self.assertEqual(aentry['action'], 'POST /auth', aentry)
        self.assertEqual(aentry['success'], 1, aentry)
        self.assertEqual(aentry['policies'], 'remote', aentry)

        # check that a remote user with "@" works as well
        set_policy(name="remote",
                   scope=SCOPE.WEBUI,
                   realm=self.realm1,
                   action="{0!s}={1!s}".format(ACTION.REMOTE_USER,
                                               REMOTE_USER.ACTIVE))
        with self.app.test_request_context(
                '/auth',
                method='POST',
                data={"username": "******"},
                environ_base={"REMOTE_USER": "******"}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status"), result)
            self.assertEqual(result.get("value").get('role'), 'user', result)
        aentry = self.find_most_recent_audit_entry(action='POST /auth')
        self.assertEqual(aentry['action'], 'POST /auth', aentry)
        self.assertEqual(aentry['success'], 1, aentry)
        self.assertEqual(aentry['policies'], 'remote', aentry)

        # check that the policy remote_user=force passes the necessary hidden tag to the
        # login window
        set_policy(name="remote",
                   scope=SCOPE.WEBUI,
                   realm=self.realm1,
                   action="{0!s}={1!s}".format(ACTION.REMOTE_USER,
                                               REMOTE_USER.FORCE))
        with self.app.test_request_context(
                '/',
                method='GET',
                environ_base={"REMOTE_USER": "******"}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200, res)
            # The login page contains the info about force remote_user, which will hide the
            # "login with credentials" button.
            self.assertIn(
                u'input type=hidden id=FORCE_REMOTE_USER value="True"',
                to_unicode(res.data))

        # bind the remote user policy to an unknown realm
        set_policy(name="remote",
                   scope=SCOPE.WEBUI,
                   realm='unknown',
                   action="{0!s}={1!s}".format(ACTION.REMOTE_USER,
                                               REMOTE_USER.ACTIVE))
        with self.app.test_request_context(
                '/auth',
                method='POST',
                data={"username": "******"},
                environ_base={"REMOTE_USER": "******"}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 401, res)
            result = res.json.get("result")
            self.assertFalse(result.get("status"), result)
        aentry = self.find_most_recent_audit_entry(action='POST /auth')
        self.assertEqual(aentry['action'], 'POST /auth', aentry)
        self.assertEqual(aentry['success'], 0, aentry)
        self.assertEqual(aentry['policies'], '', aentry)

        # check split@sign is working correctly
        set_policy(name="remote",
                   scope=SCOPE.WEBUI,
                   realm=self.realm1,
                   action="{0!s}={1!s}".format(ACTION.REMOTE_USER,
                                               REMOTE_USER.ACTIVE))
        set_privacyidea_config(SYSCONF.SPLITATSIGN, False)
        with self.app.test_request_context(
                '/auth',
                method='POST',
                data={"username": "******"},
                environ_base={"REMOTE_USER": "******"}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status"), result)
            self.assertEqual(result.get("value").get('role'), 'user', result)
        aentry = self.find_most_recent_audit_entry(action='POST /auth')
        self.assertEqual(aentry['action'], 'POST /auth', aentry)
        self.assertEqual(aentry['success'], 1, aentry)
        self.assertEqual(aentry['policies'], 'remote', aentry)

        delete_policy(name='remote')
        set_privacyidea_config(SYSCONF.SPLITATSIGN, True)
Example #33
0
    def test_15_ui_tokentypes(self):
        P = PolicyClass()
        logged_in_user = {
            "username": "******",
            "role": "admin",
            "realm": "realm1"
        }
        # Without policies, the admin gets all
        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertTrue("hotp" in tt)
        self.assertTrue("totp" in tt)
        self.assertTrue("motp" in tt)
        self.assertTrue("sms" in tt)
        self.assertTrue("spass" in tt)
        self.assertTrue("sshkey" in tt)
        self.assertTrue("email" in tt)
        self.assertTrue("certificate" in tt)
        self.assertTrue("yubico" in tt)
        self.assertTrue("yubikey" in tt)
        self.assertTrue("radius" in tt)

        # An admin may only enroll Yubikeys
        set_policy(name="tokenEnroll",
                   scope=SCOPE.ADMIN,
                   action="enrollYUBIKEY")
        P = PolicyClass()

        tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user)
        self.assertFalse("hotp" in tt)
        self.assertFalse("totp" in tt)
        self.assertFalse("motp" in tt)
        self.assertFalse("sms" in tt)
        self.assertFalse("spass" in tt)
        self.assertFalse("sshkey" in tt)
        self.assertFalse("email" in tt)
        self.assertFalse("certificate" in tt)
        self.assertFalse("yubico" in tt)
        self.assertTrue("yubikey" in tt)
        self.assertFalse("radius" in tt)

        # A user may enroll nothing
        set_policy(name="someUserAction", scope=SCOPE.USER, action="disable")
        P = PolicyClass()
        tt = P.ui_get_enroll_tokentypes("127.0.0.1", {
            "username": "******",
            "realm": "realm",
            "role": "user"
        })
        self.assertEqual(len(tt), 0)
        delete_policy("tokenEnroll")

        # Two admins:
        # adminA is allowed to enroll tokens in all realms
        # adminB is allowed to enroll tokens only in realmB

        set_policy(name="polAdminA",
                   scope=SCOPE.ADMIN,
                   user="******",
                   action="enrollHOTP, enrollTOTP")
        set_policy(name="polAdminB",
                   scope=SCOPE.ADMIN,
                   user="******",
                   realm="realmB",
                   action="enrollHOTP")
        P = PolicyClass()
        # realm is empty, since in case of an admin, this is the admin realm
        rights = P.ui_get_enroll_tokentypes(None, {
            "role": SCOPE.ADMIN,
            "realm": None,
            "username": "******"
        })
        self.assertTrue("hotp" in rights)
        self.assertTrue("totp" in rights)
        rights = P.ui_get_enroll_tokentypes(None, {
            "role": SCOPE.ADMIN,
            "realm": "",
            "username": "******"
        })
        self.assertTrue("totp" not in rights)
        self.assertTrue("hotp" in rights)
        rights = P.ui_get_enroll_tokentypes(None, {
            "role": SCOPE.ADMIN,
            "realm": "",
            "username": "******"
        })
        self.assertEqual(rights, {})
        delete_policy("polAdminA")
        delete_policy("polAdminB")
    def test_01_set_policy(self):
        with self.app.test_request_context('/policy/pol1',
                                           method='POST',
                                           data={
                                               "action": ACTION.NODETAILFAIL,
                                               "client": "10.1.2.3",
                                               "scope": SCOPE.AUTHZ,
                                               "check_all_resolvers": "true",
                                               "realm": "realm1",
                                               "priority": 3
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            data = res.json
            result = data.get("result")
            self.assertTrue("setPolicy pol1" in result.get("value"),
                            result.get("value"))

        # get the policies and see if check_all_resolvers and priority are set
        with self.app.test_request_context('/policy/',
                                           method='GET',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            self.assertTrue(res.json['result']['status'], res.json)
            value = res.json['result']['value']
            self.assertEqual(len(value), 1)
            pol1 = value[0]
            self.assertEqual(pol1.get("check_all_resolvers"), True)
            self.assertEqual(pol1.get("priority"), 3)

        # get active policies
        with self.app.test_request_context('/policy/?active=true',
                                           method='GET',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            self.assertTrue(res.json['result']['status'], res.json)
            self.assertEqual(len(value), 1)
            pol1 = value[0]
            self.assertEqual(pol1.get("check_all_resolvers"), True)
            self.assertEqual(pol1.get("priority"), 3)

        # Update policy to check_all_resolvers = false and priority = 5
        with self.app.test_request_context('/policy/pol1',
                                           method='POST',
                                           data={
                                               "action": ACTION.NODETAILFAIL,
                                               "client": "10.1.2.3",
                                               "scope": SCOPE.AUTHZ,
                                               "check_all_resolvers": "false",
                                               "priority": 5,
                                               "realm": "realm1"
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            data = res.json
            result = data.get("result")
            self.assertTrue("setPolicy pol1" in result.get("value"),
                            result.get("value"))

        # get the policies and see if check_all_resolvers and priority are set
        with self.app.test_request_context('/policy/',
                                           method='GET',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            self.assertTrue(res.json['result']['status'], res.json)
            value = res.json['result']['value']
            self.assertEqual(len(value), 1)
            pol1 = value[0]
            self.assertEqual(pol1.get("check_all_resolvers"), False)
            self.assertEqual(pol1.get("priority"), 5)

        delete_policy("pol1")

        with self.app.test_request_context('/policy/polpinode',
                                           method='POST',
                                           data={
                                               "action": ACTION.NODETAILFAIL,
                                               "client": "10.1.2.3",
                                               "scope": SCOPE.AUTHZ,
                                               "pinode": "Node1",
                                               "priority": 1,
                                               "realm": "realm1"
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            data = res.json
            result = data.get("result")
            self.assertTrue("setPolicy polpinode" in result.get("value"),
                            result.get("value"))

        # get the policies and see if the pinode was set
        with self.app.test_request_context('/policy/',
                                           method='GET',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            self.assertTrue(res.json['result']['status'], res.json)
            value = res.json['result']['value']
            self.assertEqual(len(value), 1)
            pol1 = value[0]
            self.assertEqual(pol1.get("pinode"), ["Node1"])

        delete_policy("polpinode")
    def test_02_check_httpenvironment_condition(self):
        self.setUp_user_realms()
        # enroll a simple pass token
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                json={
                    "type": "spass",
                    "pin": "1234",
                    "serial": "sp1",
                    "user": "******",
                    "realm": "realm1",
                    "client": "10.1.2.3"
                },
                headers={'PI-Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)

        # test an auth request
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           json={
                                               "pass": "******",
                                               "user": "******",
                                               "realm": "realm1",
                                               "client": "10.1.2.3"
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = res.json
            self.assertTrue("detail" in result)
            self.assertEqual(
                result.get("detail").get("message"), u"matching 1 tokens")

        # set a policy with conditions
        # Request with a certain request method will not see the user details
        with self.app.test_request_context(
                '/policy/cond1',
                method='POST',
                json={
                    "action":
                    ACTION.NODETAILSUCCESS,
                    "realm":
                    "realm1",
                    "client":
                    "10.1.2.3",
                    "conditions": [[
                        CONDITION_SECTION.HTTP_ENVIRONMENT, "REQUEST_METHOD",
                        "equals", "POST", True
                    ]],
                    "scope":
                    SCOPE.AUTHZ
                },
                headers={'PI-Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)

        # A GET request will contain the details!
        with self.app.test_request_context('/validate/check',
                                           method='GET',
                                           json={
                                               "pass": "******",
                                               "user": "******",
                                               "realm": "realm1",
                                               "client": "10.1.2.3"
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = res.json
            self.assertTrue("detail" in result)
            self.assertEqual(
                result.get("detail").get("message"), u"matching 1 tokens")

        # A POST request will NOT contain the details!
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           json={
                                               "pass": "******",
                                               "user": "******",
                                               "realm": "realm1",
                                               "client": "10.1.2.3"
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = res.json
            self.assertFalse("detail" in result)

        delete_policy("cond1")
        # Now we run a test with a non-existing environment key
        with self.app.test_request_context(
                '/policy/cond1',
                method='POST',
                json={
                    "action":
                    ACTION.NODETAILSUCCESS,
                    "realm":
                    "realm1",
                    "client":
                    "10.1.2.3",
                    "conditions": [[
                        CONDITION_SECTION.HTTP_ENVIRONMENT, "NON_EXISTING",
                        "equals", "POST", True
                    ]],
                    "scope":
                    SCOPE.AUTHZ
                },
                headers={'PI-Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)

        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           json={
                                               "pass": "******",
                                               "user": "******",
                                               "realm": "realm1",
                                               "client": "10.1.2.3"
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 403)
            result = res.json
            self.assertIn(
                u"Unknown HTTP environment key referenced in condition of policy",
                result["result"]["error"]["message"])
            self.assertIn(u"NON_EXISTING",
                          result["result"]["error"]["message"])

        delete_policy("cond1")
        remove_token("sp1")
    def test_08_get_webui_settings(self):
        # Test that a machine definition will return offline hashes
        self.setUp_user_realms()
        serial = "offline01"
        tokenobject = init_token({
            "serial": serial,
            "type": "hotp",
            "otpkey": "3132333435363738393031"
            "323334353637383930",
            "pin": "offline",
            "user": "******"
        })

        # Set the Machine and MachineToken
        resolver1 = save_resolver({
            "name": "reso1",
            "type": "hosts",
            "filename": HOSTSFILE
        })

        mt = attach_token(serial, "offline", hostname="gandalf")
        self.assertEqual(mt.token.serial, serial)
        self.assertEqual(mt.token.machine_list[0].machine_id, "192.168.0.1")

        # The request with an OTP value and a PIN of a user, who has not
        # token assigned
        builder = EnvironBuilder(method='POST', data={}, headers={})
        env = builder.get_environ()
        env["REMOTE_ADDR"] = "192.168.0.1"
        g.client_ip = env["REMOTE_ADDR"]
        req = Request(env)
        req.all_data = {"user": "******", "pass": "******"}

        res = {
            "jsonrpc": "2.0",
            "result": {
                "status": True,
                "value": {
                    "role": "user",
                    "username": "******"
                }
            },
            "version": "privacyIDEA test",
            "detail": {
                "serial": serial
            },
            "id": 1
        }
        resp = Response(json.dumps(res))

        new_response = get_webui_settings(req, resp)
        jresult = json.loads(new_response.data)
        self.assertEqual(
            jresult.get("result").get("value").get("token_wizard"), False)

        # Set a policy. User has not token, so "token_wizard" will be True
        set_policy(name="pol_wizard",
                   scope=SCOPE.WEBUI,
                   action=ACTION.TOKENWIZARD)
        g.policy_object = PolicyClass()
        new_response = get_webui_settings(req, resp)
        jresult = json.loads(new_response.data)
        self.assertEqual(
            jresult.get("result").get("value").get("token_wizard"), True)

        delete_policy("pol_wizard")
    def test_07_login_mode(self):
        # a realm: cornelius@r1: PW: test

        def check_webui_user_userstore(user_obj,
                                       password,
                                       options=None,
                                       superuser_realms=None,
                                       check_otp=False):
            self.assertEqual(check_otp, False)

        def check_webui_user_privacyidea(user_obj,
                                         password,
                                         options=None,
                                         superuser_realms=None,
                                         check_otp=False):
            self.assertEqual(check_otp, True)

        user_obj = User("cornelius", "r1")

        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # No policy, the function is called with check_otp=False
        login_mode(check_webui_user_userstore,
                   user_obj,
                   "",
                   options=options,
                   superuser_realms="",
                   check_otp=False)

        set_policy(name="pol2",
                   scope=SCOPE.WEBUI,
                   action="{0!s}={1!s}".format(ACTION.LOGINMODE,
                                               LOGINMODE.PRIVACYIDEA))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # Policy is set, the function is called with check_otp=True
        login_mode(check_webui_user_privacyidea,
                   user_obj,
                   "",
                   options=options,
                   superuser_realms="",
                   check_otp=False)

        # Set policy, so that the user is not allowed to login at all
        set_policy(name="pol2",
                   scope=SCOPE.WEBUI,
                   action="{0!s}={1!s}".format(ACTION.LOGINMODE,
                                               LOGINMODE.DISABLE))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # Policy is set. Trying to login raises a policy error
        self.assertRaises(PolicyError,
                          login_mode,
                          check_webui_user_privacyidea,
                          user_obj,
                          "",
                          options=options,
                          superuser_realms="",
                          check_otp=False)
        delete_policy("pol2")
    def test_06_passthru(self):
        user = User("cornelius", realm="r1")
        passw = "test"
        options = {}
        # A user with no tokens will fail to authenticate
        self.assertEqual(get_tokens(user=user, count=True), 0)
        rv = auth_user_passthru(check_user_pass, user, passw, options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"),
                         "The user has no tokens assigned")

        # Now we set a PASSTHRU policy, so that the user may authenticate
        # against his userstore (old style)
        set_policy(name="pol1", scope=SCOPE.AUTH, action=ACTION.PASSTHRU)
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}
        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertEqual(rv[1].get("message"),
                         u"against userstore due to 'pol1'")

        # Now set a PASSTHRU policy to the userstore (new style)
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}=userstore".format(ACTION.PASSTHRU))
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}
        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertEqual(rv[1].get("message"),
                         u"against userstore due to 'pol1'")

        # Now set a PASSTHRU policy to a RADIUS config (new style)
        radiusmock.setdata(success=True)
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}=radiusconfig1".format(ACTION.PASSTHRU))
        r = add_radius("radiusconfig1",
                       "1.2.3.4",
                       "testing123",
                       dictionary=DICT_FILE)
        self.assertTrue(r > 0)
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}
        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertEqual(rv[1].get("message"),
                         u"against RADIUS server radiusconfig1 due to 'pol1'")

        # Now assign a token to the user. If the user has a token and the
        # passthru policy is set, the user must not be able to authenticate
        # with his userstore password.
        init_token({
            "serial": "PTHRU",
            "type": "spass",
            "pin": "Hallo"
        },
                   user=user)
        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"), "wrong otp pin")

        remove_token("PTHRU")
        delete_policy("pol1")
Example #39
0
    def test_02_get_allowed_audit_realm(self):
        # Check that an administrator is only allowed to see log entries of
        # the defined realms.
        # fill some audit entries
        Audit(action="enroll", success=1, realm="realm1a").save()
        Audit(action="enroll", success=1, realm="realm1a").save()
        Audit(action="enroll", success=1, realm="realm2b").save()
        Audit(action="enroll", success=1, realm="realm2b").save()
        Audit(action="enroll", success=1, realm="realm2b").save()

        # check, that we see all audit entries
        with self.app.test_request_context('/audit/',
                                           method='GET',
                                           data={"realm": "realm1a"},
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            json_response = json.loads(res.data.decode('utf8'))
            self.assertTrue(json_response.get("result").get("status"), res)
            self.assertEqual(
                json_response.get("result").get("value").get("count"), 2)

        with self.app.test_request_context('/audit/',
                                           method='GET',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            json_response = json.loads(res.data.decode('utf8'))
            self.assertTrue(json_response.get("result").get("status"), res)
            self.assertEqual(
                json_response.get("result").get("value").get("count"), 8)
            audit_list = json_response.get("result").get("value").get(
                "auditdata")
            audit_actions = [
                a for a in audit_list if a.get("action") == "GET /audit/"
            ]
            self.assertEqual(len(audit_actions), 2)

        with self.app.test_request_context('/audit/',
                                           method='GET',
                                           data={"realm": "realm2b"},
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            json_response = json.loads(res.data.decode('utf8'))
            self.assertTrue(json_response.get("result").get("status"), res)
            self.assertEqual(
                json_response.get("result").get("value").get("count"), 3)

        # set policy for audit realms
        set_policy("audit01",
                   scope=SCOPE.ADMIN,
                   action=ACTION.AUDIT,
                   realm="realm1a")

        # check, that we only see allowed audit realms
        with self.app.test_request_context('/audit/',
                                           method='GET',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            json_response = json.loads(res.data.decode('utf8'))
            self.assertTrue(json_response.get("result").get("status"), res)
            # We now have 3 entries, as we added one by the search in line #43
            audit_list = json_response.get("result").get("value").get(
                "auditdata")
            audit_realms = [
                a for a in audit_list if a.get("realm") == "realm1a"
            ]
            self.assertEqual(len(audit_realms), 3)
            self.assertEqual(
                json_response.get("result").get("value").get("count"), 3)

        # delete policy
        delete_policy("audit01")
Example #40
0
    def test_03_get_allowed_audit_realm(self):
        # Check than an internal admin is allowed to see all realms
        # A helpdesk user in "adminrealm" is only allowerd to see realm1A
        Audit(action="enroll", success=1, realm="realm1a").save()
        Audit(action="enroll", success=1, realm="realm1a").save()
        Audit(action="enroll", success=1, realm="realm2b").save()
        Audit(action="enroll", success=1, realm="realm2b").save()
        Audit(action="enroll", success=1, realm="realm2b").save()

        # check, that we see all audit entries
        with self.app.test_request_context('/audit/',
                                           method='GET',
                                           data={"realm": "realm1a"},
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            json_response = json.loads(res.data.decode('utf8'))
            self.assertTrue(json_response.get("result").get("status"), res)
            self.assertEqual(
                json_response.get("result").get("value").get("count"), 5)

        with self.app.test_request_context('/audit/',
                                           method='GET',
                                           data={"realm": "realm2b"},
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            json_response = json.loads(res.data.decode('utf8'))
            self.assertTrue(json_response.get("result").get("status"), res)
            self.assertEqual(
                json_response.get("result").get("value").get("count"), 7)

        # set policy: helpdesk users in adminrealm are only allowed to
        # view "realm1A".
        set_policy("audit01",
                   scope=SCOPE.ADMIN,
                   action=ACTION.AUDIT,
                   adminrealm="adminrealm",
                   realm="realm1a")
        # Test admin is allowed to view unrestricted logs!
        set_policy("audit02",
                   scope=SCOPE.ADMIN,
                   action=ACTION.AUDIT,
                   user="******")

        rid = save_resolver({
            "resolver": self.resolvername1,
            "type": "passwdresolver",
            "fileName": PWFILE
        })
        self.assertTrue(rid > 0, rid)

        (added, failed) = set_realm("adminrealm", [self.resolvername1])
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 1)

        helpdesk_authorization = None
        with self.app.test_request_context('/auth',
                                           method='POST',
                                           data={
                                               'username':
                                               '******',
                                               'password': '******'
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            json_response = json.loads(res.data.decode('utf8'))
            value = json_response.get("result").get("value")
            # Helpdesk user is allowed to view the audit log.
            self.assertTrue("auditlog" in value.get("rights"))
            helpdesk_authorization = value.get("token")

        # check, that we only see allowed audit realms
        with self.app.test_request_context(
                '/audit/',
                method='GET',
                headers={'Authorization': helpdesk_authorization}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            json_response = json.loads(res.data.decode('utf8'))
            self.assertTrue(json_response.get("result").get("status"), res)
            # We now have 3 entries, as we added one by the search in line #43
            count = json_response.get("result").get("value").get("count")
            auditdata = json_response.get("result").get("value").get(
                "auditdata")
            self.assertEqual(count, 6)
            # All entries are in realm1A!
            for ad in auditdata:
                self.assertEqual(ad.get("realm"), "realm1a")

        # Now check, that the testadmin (self.at) sees all entries!
        with self.app.test_request_context('/audit/',
                                           method='GET',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            json_response = json.loads(res.data.decode('utf8'))
            self.assertTrue(json_response.get("result").get("status"), res)
            # We now have 3 entries, as we added one by the search in line #43
            count = json_response.get("result").get("value").get("count")
            auditdata = json_response.get("result").get("value").get(
                "auditdata")
            self.assertEqual(count, 20)

        # delete policy
        delete_policy("audit01")
        delete_policy("audit02")
Example #41
0
    def test_06_api_auth(self):
        self.setUp_user_realms()

        # get enrolled push token
        toks = get_tokens(tokentype="push")
        self.assertEqual(len(toks), 1)
        tokenobj = toks[0]

        # set PIN
        tokenobj.set_pin("pushpin")
        tokenobj.add_user(User("cornelius", self.realm1))

        # Set a loginmode policy
        set_policy("webui", scope=SCOPE.WEBUI,
                   action="{}={}".format(ACTION.LOGINMODE, LOGINMODE.PRIVACYIDEA))
        # Set a PUSH_WAIT action which will be ignored by privacyIDEA
        set_policy("push1", scope=SCOPE.AUTH, action="{0!s}=20".format(PUSH_ACTION.WAIT))
        with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.ServiceAccountCredentials') as mySA:
            # alternative: side_effect instead of return_value
            mySA.from_json_keyfile_name.return_value = myCredentials(myAccessTokenInfo("my_bearer_token"))

            # add responses, to simulate the communication to firebase
            responses.add(responses.POST, 'https://fcm.googleapis.com/v1/projects/test-123456/messages:send',
                          body="""{}""",
                          content_type="application/json")

            with self.app.test_request_context('/auth',
                                               method='POST',
                                               data={"username": "******",
                                                     "realm": self.realm1,
                                                     # this will be overwritted by pushtoken_disable_wait
                                                     PUSH_ACTION.WAIT: "10",
                                                     "password": "******"}):
                res = self.app.full_dispatch_request()
                self.assertEqual(res.status_code, 401)
                jsonresp = res.json
                self.assertFalse(jsonresp.get("result").get("value"))
                self.assertFalse(jsonresp.get("result").get("status"))
                self.assertEqual(jsonresp.get("detail").get("serial"), tokenobj.token.serial)
                self.assertIn("transaction_id", jsonresp.get("detail"))
                transaction_id = jsonresp.get("detail").get("transaction_id")
                self.assertEqual(jsonresp.get("detail").get("message"), DEFAULT_CHALLENGE_TEXT)

        # Get the challenge from the database
        challengeobject_list = get_challenges(serial=tokenobj.token.serial,
                                              transaction_id=transaction_id)
        challenge = challengeobject_list[0].challenge
        # This is what the smartphone answers.
        # create the signature:
        sign_data = "{0!s}|{1!s}".format(challenge, tokenobj.token.serial)
        signature = b32encode_and_unicode(
            self.smartphone_private_key.sign(sign_data.encode("utf-8"),
                                             padding.PKCS1v15(),
                                             hashes.SHA256()))

        # We still cannot log in
        with self.app.test_request_context('/auth',
                                           method='POST',
                                           data={"username": "******",
                                                 "realm": self.realm1,
                                                 "pass": "",
                                                 "transaction_id": transaction_id}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 401)
            self.assertFalse(res.json['result']['status'])

        # Answer the challenge
        with self.app.test_request_context('/ttype/push',
                                           method='POST',
                                           data={"serial": tokenobj.token.serial,
                                                 "nonce": challenge,
                                                 "signature": signature}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            self.assertTrue(res.json['result']['status'])
            self.assertTrue(res.json['result']['value'])

        # We can now log in
        with self.app.test_request_context('/auth',
                                           method='POST',
                                           data={"username": "******",
                                                 "realm": self.realm1,
                                                 "pass": "",
                                                 "transaction_id": transaction_id}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            self.assertTrue(res.json['result']['status'])

        delete_policy("push1")
        delete_policy("webui")
Example #42
0
 def test_04_delete_policy(self):
     delete_policy(name="pol4")
     P = PolicyClass()
     pol4 = P.get_policies(name="pol4")
     self.assertTrue(pol4 == [], pol4)
Example #43
0
    def test_10_auth_items_ssh(self):
        # create an SSH token
        token_obj = init_token({"serial": self.serial2, "type": "sshkey",
                                "sshkey": SSHKEY})
        self.assertEqual(token_obj.type, "sshkey")

        # Attach the token to the machine "gandalf" with the application SSH
        r = attach_token(hostname="gandalf", serial=self.serial2,
                         application="ssh", options={"user": "******"})

        self.assertEqual(r.machine_id, "192.168.0.1")

        # fetch the auth_items for application SSH on machine gandalf
        with self.app.test_request_context(
                '/machine/authitem/ssh?hostname=gandalf',
                method='GET',
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertEqual(result["status"], True)
            sshkey = result["value"].get("ssh")[0].get("sshkey")
            self.assertTrue(sshkey.startswith("ssh-rsa"), sshkey)

        # fetch the auth_items for user testuser
        with self.app.test_request_context(
                '/machine/authitem/ssh?hostname=gandalf&user=testuser',
                method='GET',
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertEqual(result["status"], True)
            sshkey = result["value"].get("ssh")[0].get("sshkey")
            self.assertTrue(sshkey.startswith("ssh-rsa"), sshkey)

        # fetch auth_items for testuser, but with mangle policy
        # Remove everything that sounds like "SOMETHING\" in front of
        # the username
        set_policy(name="mangle1", scope=SCOPE.AUTH,
                   action="{0!s}=user/.*\\\\(.*)/\\1/".format(ACTION.MANGLE))
        with self.app.test_request_context(
                '/machine/authitem/ssh?hostname=gandalf&user=DOMAIN\\testuser',
                method='GET',
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertEqual(result["status"], True)
            sshkey = result["value"].get("ssh")[0].get("sshkey")
            self.assertTrue(sshkey.startswith("ssh-rsa"), sshkey)
        delete_policy("mangle1")

        # Now that the policy is deleted, we will not get the auth_items
        # anymore, since the username is not mangled.
        with self.app.test_request_context(
                '/machine/authitem/ssh?hostname=gandalf&user=DOMAIN\\testuser',
                method='GET',
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            self.assertEqual(result["status"], True)
            sshkeys = result["value"].get("ssh")
            # No user DOMAIN\\testuser and no SSH keys
            self.assertFalse(sshkeys)

        # fetch the auth_items on machine gandalf for all applications
        with self.app.test_request_context(
                '/machine/authitem?hostname=gandalf',
                method='GET',
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = res.json.get("result")
            sshkey = result["value"].get("ssh")[0].get("sshkey")
            self.assertTrue(sshkey.startswith("ssh-rsa"), sshkey)
Example #44
0
    def test_05_autoassign_userstore(self):
        # init a token, that does has no user
        self.setUp_user_realms()
        tokenobject = init_token(
            {
                "serial": "UASSIGN2",
                "type": "hotp",
                "otpkey": "3132333435363738393031"
                "323334353637383930"
            },
            tokenrealms=[self.realm1])
        user_obj = User("autoassignuser", self.realm1)
        # unassign all tokens from the user autoassignuser
        try:
            unassign_token(None, user=user_obj)
        except Exception:
            print("no need to unassign token")

        # The request with an OTP value and a PIN of a user, who has not
        # token assigned
        builder = EnvironBuilder(method='POST', data={}, headers={})
        env = builder.get_environ()
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)
        req.all_data = {
            "user": "******",
            "realm": self.realm1,
            "pass": "******"
        }
        # The response with a failed request
        res = {
            "jsonrpc": "2.0",
            "result": {
                "status": True,
                "value": False
            },
            "version": "privacyIDEA test",
            "id": 1
        }
        resp = Response(json.dumps(res))

        # Set the autoassign policy
        # to "userstore"
        set_policy(name="pol2",
                   scope=SCOPE.ENROLL,
                   action="%s=%s" %
                   (ACTION.AUTOASSIGN, AUTOASSIGNVALUE.USERSTORE),
                   client="10.0.0.0/8")
        g.policy_object = PolicyClass()

        new_response = autoassign(req, resp)
        jresult = json.loads(new_response.data)
        self.assertEqual(jresult.get("result").get("value"), True)
        self.assertEqual(jresult.get("detail").get("serial"), "UASSIGN2")

        # authenticate with 287082 a second time will fail
        res, dict = check_user_pass(User("autoassignuser", self.realm1),
                                    "password287082")
        self.assertFalse(res)

        # authenticate with the next OTP 359152 will succeed
        res, dict = check_user_pass(User("autoassignuser", self.realm1),
                                    "password359152")
        self.assertTrue(res)

        delete_policy("pol2")
Example #45
0
    def test_03_custom_parameters(self):
        set_policy(
            name="enrollhotp",
            action=["enrollHOTP=1", "delete", "hotp_2step=allow"],
            scope=SCOPE.ADMIN,
        )
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "hotp",
                    "genkey": "1",
                    "2stepinit": "1",
                    "2step_serversize": "5",
                    "2step_clientsize": "16",
                    "2step_difficulty": "17898",
                    "hashlib": "sha512",  # force 64-byte secret
                    "otplen": "8",
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = json.loads(res.data).get("detail")
            serial = detail.get("serial")
            otpkey_url = detail.get("otpkey", {}).get("value")
            server_component = binascii.unhexlify(otpkey_url.split("/")[2])

        client_component = "wrongsize0"  # 10 bytes
        hex_client_component = binascii.hexlify(client_component)

        # Supply a client secret of incorrect size
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "hotp",
                                               "serial": serial,
                                               "otpkey": hex_client_component,
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 400, res)
            result = json.loads(res.data).get("result")
            self.assertFalse(result.get("status"))

        client_component = "correctsizeABCDE"  # 16 bytes
        hex_client_component = binascii.hexlify(client_component)

        # Now doing the correct 2nd step
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "hotp",
                    "serial": serial,
                    "otpkey": hex_client_component,
                    "2step_serversize": "3",  # will have no effect
                    "2step_clientsize": "4",
                    "2step_difficulty": "33333"
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = json.loads(res.data).get("detail")
            otpkey_url = detail.get("otpkey", {}).get("value")
            otpkey = otpkey_url.split("/")[2]

        # Now try to authenticate
        otpkey_bin = binascii.unhexlify(otpkey)
        otp_value = HmacOtp(digits=8,
                            hashfunc=hashlib.sha512).generate(key=otpkey_bin,
                                                              counter=1)
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), True)

        # Check serversize
        self.assertEqual(len(server_component), 5)
        # Check that the OTP key is what we expected it to be
        expected_secret = pbkdf2(binascii.hexlify(server_component),
                                 client_component, 17898, 64)
        self.assertEqual(otpkey_bin, expected_secret)

        with self.app.test_request_context('/token/' + serial,
                                           method='DELETE',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)

        delete_policy("enrollhotp")
    def test_11_otppin_with_resolvers(self):
        # This tests, if the otppin policy differentiates between users in
        # the same realm but in different resolvers.
        r = save_resolver({
            "resolver": "reso001",
            "type": "passwdresolver",
            "fileName": "tests/testdata/passwords"
        })
        # user "cornelius" is in resolver reso001
        self.assertTrue(r > 0)
        r = save_resolver({
            "resolver": "reso002",
            "type": "passwdresolver",
            "fileName": "tests/testdata/pw-2nd-resolver"
        })
        # user "userresolver2" is in resolver reso002
        self.assertTrue(r > 0)
        (added, failed) = set_realm("myrealm", ["reso001", "reso002"])
        self.assertEqual(len(added), 2)
        self.assertEqual(len(failed), 0)
        my_user_1 = User("cornelius", realm="myrealm")
        my_user_2 = User("userresolver2", realm="myrealm")
        # We set a policy only for resolver reso002
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   realm="myrealm",
                   resolver="reso002",
                   action="{0!s}={1!s}".format(ACTION.OTPPIN,
                                               ACTIONVALUE.NONE))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # user in reso001 fails with empty PIN, since the policy does not
        # match for him
        r = auth_otppin(self.fake_check_otp,
                        None,
                        "",
                        options=options,
                        user=my_user_1)
        self.assertFalse(r)

        # user in reso002 succeeds with empty PIN, since policy pol1 matches
        # for him
        r = auth_otppin(self.fake_check_otp,
                        None,
                        "",
                        options=options,
                        user=my_user_2)
        self.assertTrue(r)

        # user in reso002 fails with any PIN, since policy pol1 matches
        # for him
        r = auth_otppin(self.fake_check_otp,
                        None,
                        "anyPIN",
                        options=options,
                        user=my_user_2)
        self.assertFalse(r)

        delete_policy("pol1")
        delete_realm("myrealm")
        delete_resolver("reso001")
        delete_resolver("reso002")
    def test_06_offline_auth(self):
        # Test that a machine definition will return offline hashes
        self.setUp_user_realms()
        serial = "offline01"
        tokenobject = init_token({
            "serial": serial,
            "type": "hotp",
            "otpkey": "3132333435363738393031"
            "323334353637383930",
            "pin": "offline",
            "user": "******"
        })

        # Set the Machine and MachineToken
        resolver1 = save_resolver({
            "name": "reso1",
            "type": "hosts",
            "filename": HOSTSFILE
        })

        mt = attach_token(serial, "offline", hostname="gandalf")
        self.assertEqual(mt.token.serial, serial)
        self.assertEqual(mt.token.machine_list[0].machine_id, "192.168.0.1")

        # The request with an OTP value and a PIN of a user, who has not
        # token assigned
        builder = EnvironBuilder(method='POST', data={}, headers={})
        env = builder.get_environ()
        env["REMOTE_ADDR"] = "192.168.0.1"
        g.client_ip = env["REMOTE_ADDR"]
        req = Request(env)
        req.all_data = {"user": "******", "pass": "******"}

        res = {
            "jsonrpc": "2.0",
            "result": {
                "status": True,
                "value": True
            },
            "version": "privacyIDEA test",
            "detail": {
                "serial": serial
            },
            "id": 1
        }
        resp = Response(json.dumps(res))

        new_response = offline_info(req, resp)
        jresult = json.loads(new_response.data)
        self.assertTrue(jresult.get("result").get("value"), jresult)
        self.assertEqual(jresult.get("detail").get("serial"), serial)

        # Check the hashvalues in the offline tree
        auth_items = jresult.get("auth_items")
        self.assertEqual(len(auth_items), 1)
        response = auth_items.get("offline")[0].get("response")
        self.assertEqual(len(response), 100)
        # check if the counter of the token was increased to 100
        tokenobject = get_tokens(serial=serial)[0]
        self.assertEqual(tokenobject.token.count, 101)
        delete_policy("pol2")
    def test_01_otppin(self):
        my_user = User("cornelius", realm="r1")
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}={1!s}".format(ACTION.OTPPIN,
                                               ACTIONVALUE.NONE))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # NONE with empty PIN -> success
        r = auth_otppin(self.fake_check_otp,
                        None,
                        "",
                        options=options,
                        user=my_user)
        self.assertTrue(r)
        # NONE with empty PIN -> success, even if the authentication is done
        # for a serial and not a user, since the policy holds for all realms
        token = init_token({"type": "HOTP", "otpkey": "1234"})
        r = auth_otppin(self.fake_check_otp,
                        token,
                        "",
                        options=options,
                        user=None)
        self.assertTrue(r)

        # NONE with some pin -> fail
        r = auth_otppin(self.fake_check_otp,
                        None,
                        "some pin",
                        options=options,
                        user=my_user)
        self.assertFalse(r)

        delete_policy("pol1")
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}={1!s}".format(ACTION.OTPPIN,
                                               ACTIONVALUE.TOKENPIN))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        r = auth_otppin(self.fake_check_otp,
                        None,
                        "FAKE",
                        options=options,
                        user=my_user)
        self.assertTrue(r)
        r = auth_otppin(self.fake_check_otp,
                        None,
                        "Wrong Pin",
                        options=options,
                        user=my_user)
        self.assertFalse(r)
        delete_policy("pol1")
    def test_01_check_httpheader_condition(self):
        self.setUp_user_realms()
        # enroll a simple pass token
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                json={
                    "type": "spass",
                    "pin": "1234",
                    "serial": "sp1",
                    "user": "******",
                    "realm": "realm1",
                    "client": "10.1.2.3"
                },
                headers={'PI-Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)

        # test an auth request
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           json={
                                               "pass": "******",
                                               "user": "******",
                                               "realm": "realm1",
                                               "client": "10.1.2.3"
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = res.json
            self.assertTrue("detail" in result)
            self.assertEqual(
                result.get("detail").get("message"), u"matching 1 tokens")

        # set a policy with conditions
        # Request from a certain user agent will not see the detail
        with self.app.test_request_context(
                '/policy/cond1',
                method='POST',
                json={
                    "action":
                    ACTION.NODETAILSUCCESS,
                    "client":
                    "10.1.2.3",
                    "realm":
                    "realm1",
                    "conditions": [[
                        CONDITION_SECTION.HTTP_REQUEST_HEADER, "User-Agent",
                        "equals", "SpecialApp", True
                    ]],
                    "scope":
                    SCOPE.AUTHZ
                },
                headers={'PI-Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)

        # A request with another header will display the details
        with self.app.test_request_context(
                '/validate/check',
                method='POST',
                headers={"User-Agent": "somethingelse"},
                json={
                    "pass": "******",
                    "user": "******",
                    "realm": "realm1",
                    "client": "10.1.2.3"
                }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = res.json
            self.assertTrue("detail" in result)
            self.assertEqual(
                result.get("detail").get("message"), u"matching 1 tokens")

        # A request with the dedicated header will not display the details
        with self.app.test_request_context(
                '/validate/check',
                method='POST',
                headers={'User-Agent': 'SpecialApp'},
                json={
                    "pass": "******",
                    "user": "******",
                    "realm": "realm1",
                    "client": "10.1.2.3"
                }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = res.json
            self.assertFalse("detail" in result)

        # A request without such a header
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           headers={"Another": "header"},
                                           json={
                                               "pass": "******",
                                               "user": "******",
                                               "realm": "realm1",
                                               "client": "10.1.2.3"
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 403)
            result = res.json
            self.assertIn(
                u"Unknown HTTP header key referenced in condition of policy",
                result["result"]["error"]["message"])
            self.assertIn(u"User-Agent", result["result"]["error"]["message"])

        # A request without such a specific header - always has a header
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           json={
                                               "pass": "******",
                                               "user": "******",
                                               "realm": "realm1",
                                               "client": "10.1.2.3"
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 403)
            result = res.json
            self.assertIn(
                u"Unknown HTTP header key referenced in condition of policy",
                result["result"]["error"]["message"])
            self.assertIn(u"User-Agent", result["result"]["error"]["message"])

        # Test http header policy with broken matching
        # update the policy
        with self.app.test_request_context(
                '/policy/cond1',
                method='POST',
                json={
                    "action":
                    ACTION.NODETAILSUCCESS,
                    "client":
                    "10.1.2.3",
                    "realm":
                    "realm1",
                    "conditions": [[
                        CONDITION_SECTION.HTTP_REQUEST_HEADER, "User-Agent",
                        "broken", "SpecialApp", True
                    ]],
                    "scope":
                    SCOPE.AUTHZ
                },
                headers={'PI-Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
        # now test the policy
        with self.app.test_request_context(
                '/validate/check',
                method='POST',
                headers={"User-Agent": "SpecialApp"},
                json={
                    "pass": "******",
                    "user": "******",
                    "realm": "realm1",
                    "client": "10.1.2.3"
                }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 403)
            result = res.json
            self.assertIn(
                u"Invalid comparison in the HTTP header conditions of policy",
                result["result"]["error"]["message"])

        # Also check for an unknown section
        # update the policy
        with self.app.test_request_context(
                '/policy/cond1',
                method='POST',
                json={
                    "action":
                    ACTION.NODETAILSUCCESS,
                    "client":
                    "10.1.2.3",
                    "realm":
                    "realm1",
                    "conditions":
                    [['blabla', "User-Agent", "equals", "SpecialApp", True]],
                    "scope":
                    SCOPE.AUTHZ
                },
                headers={'PI-Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
        # now test the policy
        with self.app.test_request_context(
                '/validate/check',
                method='POST',
                headers={"User-Agent": "SpecialApp"},
                json={
                    "pass": "******",
                    "user": "******",
                    "realm": "realm1",
                    "client": "10.1.2.3"
                }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 403)
            result = res.json
            # The text can be "Policy u'cond1' has condition with unknown section"
            # or "Policy 'cond1' has condition with unknown section"
            # so we only match for a substring
            self.assertIn("has condition with unknown section",
                          result["result"]["error"]["message"], result)

        delete_policy("cond1")
        remove_token("sp1")
    def test_14_otppin_priority(self):
        my_user = User("cornelius", realm="r1")
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}={1!s}".format(ACTION.OTPPIN,
                                               ACTIONVALUE.NONE),
                   priority=2)
        set_policy(name="pol2",
                   scope=SCOPE.AUTH,
                   action="{0!s}={1!s}".format(ACTION.OTPPIN,
                                               ACTIONVALUE.TOKENPIN),
                   priority=2)
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # error because of conflicting policies
        with self.assertRaises(PolicyError):
            auth_otppin(self.fake_check_otp,
                        None,
                        "",
                        options=options,
                        user=my_user)

        # lower pol2 priority
        set_policy(name="pol2", priority=3)
        g.policy_object.reload_from_db()

        # NONE with empty PIN -> success
        r = auth_otppin(self.fake_check_otp,
                        None,
                        "",
                        options=options,
                        user=my_user)
        self.assertTrue(r)
        # NONE with empty PIN -> success, even if the authentication is done
        # for a serial and not a user, since the policy holds for all realms
        token = init_token({"type": "HOTP", "otpkey": "1234"})
        r = auth_otppin(self.fake_check_otp,
                        token,
                        "",
                        options=options,
                        user=None)
        self.assertTrue(r)

        # NONE with some pin -> fail
        r = auth_otppin(self.fake_check_otp,
                        None,
                        "some pin",
                        options=options,
                        user=my_user)
        self.assertFalse(r)

        # increase pol2 priority
        set_policy(name="pol2", priority=1)
        g.policy_object.reload_from_db()

        r = auth_otppin(self.fake_check_otp,
                        None,
                        "FAKE",
                        options=options,
                        user=my_user)
        self.assertTrue(r)
        r = auth_otppin(self.fake_check_otp,
                        None,
                        "Wrong Pin",
                        options=options,
                        user=my_user)
        self.assertFalse(r)
        delete_policy("pol1")
        delete_policy("pol2")
Example #51
0
    def test_21_check_all_resolver(self):
        # check_all_resolver allows to find a policy for a secondary user
        # resolver.
        # We create one realm "realm1" with the resolvers
        # reso1 (prio 1)
        # reso2 (prio 2)
        # reso3 (prio 3)
        # A user user@realm1 will be identified as user.reso1@realm1.
        # But we will also match policies for reso2.

        # no realm and resolver
        r = get_realms()
        self.assertEqual(r, {})

        r = get_resolver_list()
        self.assertEqual(r, {})

        # create user realm
        for reso in ["reso1", "resoX", "resoA"]:
            rid = save_resolver({
                "resolver": reso,
                "type": "passwdresolver",
                "fileName": PWFILE
            })
            self.assertTrue(rid > 0, rid)

        # create a realm with reso1 being the resolver with the highest priority
        (added, failed) = set_realm("realm1", ["reso1", "resoX", "resoA"],
                                    priority={
                                        "reso1": 1,
                                        "resoX": 2,
                                        "resoA": 3
                                    })
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 3)

        user = User(login="******", realm="realm1")
        # The user, that is created, is cornelius.reso1@realm1
        user_str = "{0!s}".format(user)
        self.assertEqual(user_str, "<cornelius.reso1@realm1>")
        # But the user "cornelius" is also contained in other resolves in
        # this realm
        r = user.get_ordererd_resolvers()
        self.assertEqual(r, ["reso1", "resoX", "resoA"])
        self.assertFalse(user.is_empty())
        self.assertTrue(User().is_empty())

        # define a policy with the wrong resolver
        p = set_policy(name="checkAll",
                       scope=SCOPE.AUTHZ,
                       realm="realm1",
                       resolver="resoX",
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        p = set_policy(name="catchAll",
                       scope=SCOPE.AUTHZ,
                       realm="realm1",
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        P = PolicyClass()
        pols = P.get_policies(scope=SCOPE.AUTHZ,
                              realm=user.realm,
                              resolver=user.resolver,
                              user=user.login)
        self.assertEqual(len(pols), 1)

        # Now we change the policy, so that it uses check_all_resolver, i.e.
        p = set_policy(name="checkAll",
                       scope=SCOPE.AUTHZ,
                       realm="realm1",
                       resolver="resoX",
                       check_all_resolvers=True,
                       action="{0}=totp".format(ACTION.TOKENTYPE))
        self.assertTrue(p > 0)
        P = PolicyClass()
        pols = P.get_policies(scope=SCOPE.AUTHZ,
                              realm=user.realm,
                              resolver=user.resolver,
                              user=user.login)
        self.assertEqual(len(pols), 2)

        # delete policy
        delete_policy("checkAll")
        delete_policy("catchAll")
        # delete resolvers and realm
        delete_realm("realm1")
        for reso in ["reso1", "resoX", "resoA"]:
            rid = delete_resolver(reso)
            self.assertTrue(rid > 0, rid)
    def test_16_passthru_assign(self):
        user = User("cornelius", realm="r1")
        passw = "{0!s}test".format(self.valid_otp_values[1])
        options = {}
        # remove all tokens of cornelius
        remove_token(user=user)

        # create unassigned tokens in realm r1
        init_token({
            "type": "hotp",
            "otpkey": "00" * 20,
            "serial": "TOKFAIL"
        },
                   tokenrealms=["r1"])
        init_token(
            {
                "type": "hotp",
                "otpkey": self.otpkey,
                "serial": "TOKMATCH"
            },
            tokenrealms=["r1"])

        # A user with no tokens will fail to authenticate
        self.assertEqual(get_tokens(user=user, count=True), 0)
        rv = auth_user_passthru(check_user_pass, user, passw, options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"),
                         "The user has no tokens assigned")

        # Now add a PASSTHRU policy to a RADIUS config
        radiusmock.setdata(success=True)
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}=radiusconfig1".format(ACTION.PASSTHRU))
        r = add_radius("radiusconfig1",
                       "1.2.3.4",
                       "testing123",
                       dictionary=DICT_FILE)
        self.assertTrue(r > 0)
        set_policy(name="pol2",
                   scope=SCOPE.AUTH,
                   action="{0!s}=6:pin:1234".format(ACTION.PASSTHRU_ASSIGN))

        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}

        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertTrue(u"against RADIUS server radiusconfig1 due to 'pol1'" in
                        rv[1].get("message"))
        self.assertTrue(u"autoassigned TOKMATCH" in rv[1].get("message"))

        # Check if the token is assigned and can authenticate
        r = check_user_pass(User("cornelius", "r1"),
                            "test{0!s}".format(self.valid_otp_values[2]))
        self.assertTrue(r[0])
        self.assertEqual(r[1].get("serial"), "TOKMATCH")

        remove_token("TOKFAIL")
        remove_token("TOKMATCH")
        delete_policy("pol1")
        delete_policy("pol2")
Example #53
0
    def test_01_setup_eventhandlers(self):
        # This test create an HOTP token with C/R with a pre-event handler
        # and the user uses this HOTP token to directly login to /auth

        # Setup realm
        rid = save_resolver({
            "resolver": self.resolvername1,
            "type": "passwdresolver",
            "fileName": PWFILE
        })
        self.assertTrue(rid > 0, rid)

        (added, failed) = set_realm(self.realm1, [self.resolvername1])
        self.assertTrue(len(failed) == 0)
        self.assertTrue(len(added) == 1)

        set_default_realm(self.realm1)

        # set a policy to authenticate against privacyIDEA
        set_policy("piLogin",
                   scope=SCOPE.WEBUI,
                   action="{0!s}=privacyIDEA".format(ACTION.LOGINMODE))
        # set a policy to for otppin=userstore
        set_policy("otppin",
                   scope=SCOPE.AUTH,
                   action="{0!s}=userstore".format(ACTION.OTPPIN))
        # Set a policy to do C/R with HOTP tokens
        set_policy("crhotp",
                   scope=SCOPE.AUTH,
                   action="{0!s}=hotp".format(ACTION.CHALLENGERESPONSE))

        # Create an event handler, that creates HOTP token on /auth with default OTP key
        eid = set_event(
            "createtoken",
            event=["auth"],
            handlermodule="Token",
            action="enroll",
            position="pre",
            conditions={CONDITION.USER_TOKEN_NUMBER: 0},
            options={
                "tokentype": "hotp",
                "user": "******",
                "additional_params": {
                    'otpkey': self.otpkey,
                    # We need to set gekey=0, otherwise the Tokenhandler will
                    # generate a random otpkey
                    'genkey': 0
                }
            })
        # cleanup tokens
        remove_token(user=User("someuser", self.realm1))

        # user tries to log in with his userstore password and gets a transaction_id
        with self.app.test_request_context('/auth',
                                           method='POST',
                                           data={
                                               "username": "******",
                                               "password": "******"
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(401, res.status_code, res)
            result = res.json.get("result")
            self.assertFalse(result.get("status"), result)
            detail = res.json.get("detail")
            self.assertEqual("please enter otp: ", detail.get("message"))
            transaction_id = detail.get("transaction_id")

        # Check if the token was enrolled
        toks = get_tokens(user=User("someuser", self.realm1))
        self.assertEqual(len(toks), 1)
        self.assertEqual(toks[0].token.tokentype, "hotp")
        serial = toks[0].token.serial
        # Check if the correct otpkey was used
        hotptoken = toks[0]
        r = hotptoken.check_otp(self.valid_otp_values[1])
        self.assertTrue(r >= 0)

        # Now the user logs in with the second step of C/R with OTP value of new token
        with self.app.test_request_context('/auth',
                                           method='POST',
                                           data={
                                               "username": "******",
                                               "transaction_id":
                                               transaction_id,
                                               "password":
                                               self.valid_otp_values[2]
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(200, res.status_code, res)
            result = res.json.get("result")
            self.assertTrue(result.get("status"))
            self.assertTrue(result.get("value"))

        # Check that there is still only one token
        toks = get_tokens(user=User("someuser", self.realm1))
        self.assertEqual(len(toks), 1)
        self.assertEqual(toks[0].token.tokentype, "hotp")
        self.assertEqual(serial, toks[0].token.serial)

        # cleanup
        delete_policy("piLogin")
        delete_policy("otppin")
        delete_policy("crhotp")
        delete_event(eid)
        remove_token(hotptoken.token.serial)
    def test_12_authcache(self):
        password = "******"
        username = "******"
        realm = "myrealm"
        resolver = "reso001"

        r = save_resolver({"resolver": "reso001",
                           "type": "passwdresolver",
                           "fileName": "tests/testdata/passwords"})
        (added, failed) = set_realm("myrealm", ["reso001"])

        def fake_check_user_pass(user, passw, options=None):
            return True, {"message": "Fake Authentication"}

        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   realm=realm,
                   resolver=resolver,
                   action="{0!s}={1!s}".format(ACTION.AUTH_CACHE, "4h/5m"))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        # This successfully authenticates against the authcache
        # We have an authentication, that is within the policy timeout
        AuthCache(username, realm, resolver, _hash_password(password),
                  first_auth=datetime.datetime.utcnow() - timedelta(hours=3),
                  last_auth=datetime.datetime.utcnow() - timedelta(minutes=1)).save()
        r = auth_cache(fake_check_user_pass, User("cornelius", "myrealm"),
                        password, options=options)
        self.assertTrue(r[0])
        self.assertEqual(r[1].get("message"), "Authenticated by AuthCache." )

        # We have an authentication, that is not read from the authcache,
        # since the authcache first_auth is too old.
        delete_from_cache(username, realm, resolver, password)
        AuthCache(username, realm, resolver, _hash_password(password),
                  first_auth=datetime.datetime.utcnow() - timedelta(hours=5),
                  last_auth=datetime.datetime.utcnow() - timedelta(
                      minutes=1)).save()
        r = auth_cache(fake_check_user_pass, User("cornelius", "myrealm"),
                       password, options=options)
        self.assertTrue(r[0])
        self.assertEqual(r[1].get("message"), "Fake Authentication")

        # We have an authentication, that is not read from authcache, since
        # the last_auth is too old = 10 minutes.
        delete_from_cache(username, realm, resolver, password)
        AuthCache(username, realm, resolver, _hash_password(password),
                  first_auth=datetime.datetime.utcnow() - timedelta(hours=1),
                  last_auth=datetime.datetime.utcnow() - timedelta(
                      minutes=10)).save()
        r = auth_cache(fake_check_user_pass, User("cornelius", "myrealm"),
                       password, options=options)
        self.assertTrue(r[0])
        self.assertEqual(r[1].get("message"), "Fake Authentication")

        # We have a policy, with no special last_auth
        delete_policy("pol1")
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   realm=realm,
                   resolver=resolver,
                   action="{0!s}={1!s}".format(ACTION.AUTH_CACHE, "4h"))
        g = FakeFlaskG()
        P = PolicyClass()
        g.policy_object = P
        g.audit_object = FakeAudit()
        options = {"g": g}

        delete_from_cache(username, realm, resolver, password)
        AuthCache(username, realm, resolver, _hash_password(password),
                  first_auth=datetime.datetime.utcnow() - timedelta(hours=2),
                  last_auth=datetime.datetime.utcnow() - timedelta(
                      hours=1)).save()
        r = auth_cache(fake_check_user_pass, User("cornelius", "myrealm"),
                       password, options=options)
        self.assertTrue(r[0])
        self.assertEqual(r[1].get("message"), "Authenticated by AuthCache.")

        # Clean up
        delete_policy("pol1")
        delete_realm("myrealm")
        delete_resolver("reso001")
Example #55
0
    def test_05_u2f_auth_fails_wrong_issuer(self):
        # test data taken from
        # https://fidoalliance.org/specs/fido-u2f-v1.0-ps-20141009/fido-u2f-raw-message-formats-ps-20141009.html#examples
        serial = "U2F0010BF6F"
        set_privacyidea_config("u2f.appId", "https://puck.az.intern")
        pin = "test"
        # Registration data
        client_data = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6ImpIakIxaEM2VjA3dDl4ZnNNaDRfOEQ3U1JuSHRFY1BqUTdsaVl3cWxkX009Iiwib3JpZ2luIjoiaHR0cHM6Ly9wdWNrLmF6LmludGVybiIsImNpZF9wdWJrZXkiOiJ1bnVzZWQifQ"
        reg_data = "BQRHjwxEYFCkLHz3xdrmifKOHl2h17BmRJQ_S1Y9PRAhS2R186T391YE-ryqWis9HSmdp0XpRqUaKk9L8lxJTPpTQF_xFJ_LAsKkPTzKIwUlPIjGZDsLmv0en2Iya17Yz8X8OS89fuxwZOvEok-NQOKUTJP3att_RVe3dEAbq_iOtyAwggJEMIIBLqADAgECAgRVYr6gMAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTQzMjUzNDY4ODBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEszH3c9gUS5mVy-RYVRfhdYOqR2I2lcvoWsSCyAGfLJuUZ64EWw5m8TGy6jJDyR_aYC4xjz_F2NKnq65yvRQwmjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS41MBMGCysGAQQBguUcAgEBBAQDAgUgMAsGCSqGSIb3DQEBCwOCAQEArBbZs262s6m3bXWUs09Z9Pc-28n96yk162tFHKv0HSXT5xYU10cmBMpypXjjI-23YARoXwXn0bm-BdtulED6xc_JMqbK-uhSmXcu2wJ4ICA81BQdPutvaizpnjlXgDJjq6uNbsSAp98IStLLp7fW13yUw-vAsWb5YFfK9f46Yx6iakM3YqNvvs9M9EUJYl_VrxBJqnyLx2iaZlnpr13o8NcsKIJRdMUOBqt_ageQg3ttsyq_3LyoNcu7CQ7x8NmeCGm_6eVnZMQjDmwFdymwEN4OxfnM5MkcKCYhjqgIGruWkVHsFnJa8qjZXneVvKoiepuUQyDEJ2GcqvhU2YKY1zBFAiEA4ZkIXXyjEPExcMGtW6kJXqYv7UHgjxJR5h3H9w9FV7gCIFGdhxZDqwCQKplDi-LU4WJ45OyCpNK6lGa72eZqUR_k"
        # Authentication data
        transaction_id = "05871369157706202013"
        challenge = "1616515928c389ba9e028d83eb5f63782cbf351ca6abbc81aeb0dddd4895b609"
        # challenge = "FhZRWSjDibqeAo2D619jeCy_NRymq7yBrrDd3UiVtgk"
        key_handle = "X_EUn8sCwqQ9PMojBSU8iMZkOwua_R6fYjJrXtjPxfw5Lz1-7HBk68SiT41A4pRMk_dq239FV7d0QBur-I63IA"
        client_data_auth = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoiRmhaUldTakRpYnFlQW8yRDYxOWplQ3lfTlJ5bXE3eUJyckRkM1VpVnRnayIsIm9yaWdpbiI6Imh0dHBzOi8vcHVjay5hei5pbnRlcm4iLCJjaWRfcHVia2V5IjoidW51c2VkIn0"
        signature_data = "AQAAAAMwRQIgU8d6waOIRVVydg_AXxediEZGkfFioUjd6FG3OxH2wUMCIQDpxzavJyxRlMwgNmD1Kw-iw_oP2egdshU9hrpxFHTRzQ"

        # step 1
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "u2f",
                                               "user": "******",
                                               "realm": self.realm1,
                                               "serial": serial
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = json.loads(res.data.decode('utf8')).get("result")
            detail = json.loads(res.data.decode('utf8')).get("detail")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), True)

        # Init step 2
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "u2f",
                                               "serial": serial,
                                               "regdata": reg_data,
                                               "clientdata": client_data
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 200)
            result = json.loads(res.data.decode('utf8')).get("result")
            detail = json.loads(res.data.decode('utf8')).get("detail")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), True)

        # create a challenge in the database
        db_challenge = Challenge(serial,
                                 transaction_id=transaction_id,
                                 challenge=challenge,
                                 data=None)
        db_challenge.save()

        set_policy(name="u2f01",
                   scope=SCOPE.AUTHZ,
                   action="{0!s}=issuer/.*Plugup.*/".format(U2FACTION.REQ))

        # Successful C/R authentication
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": "",
                                               "transaction_id":
                                               transaction_id,
                                               "clientdata": client_data_auth,
                                               "signaturedata": signature_data
                                           }):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 403)
            result = json.loads(res.data.decode('utf8')).get("result")
            self.assertEqual(result.get("status"), False)
            self.assertEqual(result.get("error").get("code"), ERROR.POLICY)
            self.assertEqual(
                result.get("error").get("message"),
                u'The U2F device is not allowed to authenticate due to policy restriction.'
            )

        delete_policy("u2f01")
        remove_token(serial)
    def test_13_passthru_priorities(self):
        user = User("cornelius", realm="r1")
        passw = "test"
        options = {}
        # remove all tokens of cornelius
        remove_token(user=user)

        # A user with no tokens will fail to authenticate
        self.assertEqual(get_tokens(user=user, count=True), 0)
        rv = auth_user_passthru(check_user_pass, user, passw, options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"),
                         "The user has no tokens assigned")

        # Now set a PASSTHRU policy to the userstore
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}=userstore".format(ACTION.PASSTHRU))
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}
        rv = auth_user_passthru(check_user_pass, user, passw,
                                options=options)
        self.assertTrue(rv[0])
        self.assertEqual(rv[1].get("message"),
                         u"against userstore due to 'pol1'")

        # Now add a PASSTHRU policy to a RADIUS config
        radiusmock.setdata(response=radiusmock.AccessAccept)
        set_policy(name="pol2",
                   scope=SCOPE.AUTH,
                   action="{0!s}=radiusconfig1".format(ACTION.PASSTHRU))
        r = add_radius("radiusconfig1", "1.2.3.4", "testing123",
                       dictionary=DICT_FILE)
        self.assertTrue(r > 0)
        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}

        # They will conflict, because they use the same priority
        with self.assertRaises(PolicyError):
            auth_user_passthru(check_user_pass, user, passw, options=options)

        # Lower pol1 priority
        set_policy(name="pol1", priority=2)

        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertEqual(rv[1].get("message"),
                         u"against RADIUS server radiusconfig1 due to 'pol2'")

        # Lower pol2 priority
        set_policy(name="pol2", priority=3)

        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertEqual(rv[1].get("message"),
                         u"against userstore due to 'pol1'")

        # Add old style priority
        set_policy(name="pol3",
                   scope=SCOPE.AUTH,
                   action=ACTION.PASSTHRU)

        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertEqual(rv[1].get("message"),
                         u"against userstore due to 'pol3'")
        set_policy(name="pol3", priority=2)

        # They will conflict, because they use the same priority
        with self.assertRaises(PolicyError):
            auth_user_passthru(check_user_pass, user, passw, options=options)

        delete_policy("pol3")

        # Now assign a token to the user. If the user has a token and the
        # passthru policy is set, the user must not be able to authenticate
        # with his userstore password.
        init_token({"serial": "PTHRU",
                    "type": "spass", "pin": "Hallo"},
                   user=user)
        rv = auth_user_passthru(check_user_pass, user, passw,
                                options=options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"), "wrong otp pin")

        remove_token("PTHRU")
        delete_policy("pol1")
        delete_policy("pol2")
Example #57
0
    def test_06_force_totp_parameters(self):
        set_policy(
            name="force_2step",
            action=["totp_2step=force", "enrollTOTP=1", "delete"],
            scope=SCOPE.ADMIN,
        )
        set_policy(
            name="2step_params",
            action=[
                "totp_2step_difficulty=12345", "totp_2step_serversize=33",
                "totp_2step_clientsize=11"
            ],
            scope=SCOPE.ENROLL,
        )
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "totp",
                    "genkey": "1",
                    "2stepinit": "0",  # will be forced nevertheless
                    "2step_serversize": "3",
                    "2step_clientsize": "4",
                    "2step_difficulty": "33333",
                    "timeStep": "60",
                    "hashlib": "sha512",
                    "otplen": "8",
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = json.loads(res.data).get("detail")
            serial = detail.get("serial")
            otpkey_url = detail.get("otpkey", {}).get("value")
            server_component = binascii.unhexlify(otpkey_url.split("/")[2])
            google_url = detail["googleurl"]["value"]
            self.assertIn('2step_difficulty=12345', google_url)
            self.assertIn('2step_salt=11', google_url)
            self.assertIn('2step_output=64', google_url)
        # Authentication does not work yet!
        wrong_otp_value = HmacOtp(digits=8, hashfunc=hashlib.sha512).generate(
            key=server_component, counter=int(time.time() / 60))
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": wrong_otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data)
            self.assertTrue(result.get("result").get("status"))
            self.assertFalse(result.get("result").get("value"))
            self.assertEqual(
                result.get("detail").get("message"),
                u'matching 1 tokens, Token is disabled')

        client_component = "wrongsize"  # 9 bytes
        hex_client_component = binascii.hexlify(client_component)

        # Supply a client secret of incorrect size
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "totp",
                                               "serial": serial,
                                               "otpkey": hex_client_component,
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 400, res)
            result = json.loads(res.data).get("result")
            self.assertFalse(result.get("status"))

        client_component = "correctsize"  # 11 bytes
        hex_client_component = binascii.hexlify(client_component)

        # Now doing the correct 2nd step
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "totp",
                    "serial": serial,
                    "otpkey": hex_client_component,
                    "2step_serversize": "3",  # will have no effect
                    "2step_clientsize": "4",
                    "2step_difficulty": "33333"
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = json.loads(res.data).get("detail")
            otpkey_url = detail.get("otpkey", {}).get("value")
            otpkey = otpkey_url.split("/")[2]

        # Now try to authenticate
        otpkey_bin = binascii.unhexlify(otpkey)
        otp_value = HmacOtp(digits=8, hashfunc=hashlib.sha512).generate(
            key=otpkey_bin, counter=int(time.time() / 60))
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), True)

        # Check serversize
        self.assertEqual(len(server_component), 33)
        # Check that the OTP key is what we expected it to be
        expected_secret = pbkdf2(binascii.hexlify(server_component),
                                 client_component, 12345, 64)
        self.assertEqual(otpkey_bin, expected_secret)

        with self.app.test_request_context('/token/' + serial,
                                           method='DELETE',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)

        delete_policy("force_2step")
        delete_policy("2step_params")
Example #58
0
    def test_05_init_totp_token(self):
        set_policy(
            name="allow_2step",
            action=["totp_2step=allow", "enrollTOTP=1", "delete"],
            scope=SCOPE.ADMIN,
        )
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "totp",
                                               "genkey": "1",
                                               "2stepinit": "1"
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = json.loads(res.data).get("detail")
            serial = detail.get("serial")
            otpkey_url = detail.get("otpkey", {}).get("value")
            server_component = binascii.unhexlify(otpkey_url.split("/")[2])
            google_url = detail["googleurl"]["value"]
            self.assertIn('2step_difficulty=10000', google_url)
            self.assertIn('2step_salt=8', google_url)
            self.assertIn('2step_output=20', google_url)
            self.assertEqual(detail['2step_difficulty'], 10000)
            self.assertEqual(detail['2step_salt'], 8)
            self.assertEqual(detail['2step_output'], 20)

        client_component = "VRYSECRT"
        checksum = hashlib.sha1(client_component).digest()[:4]
        base32check_client_component = base64.b32encode(
            checksum + client_component).strip("=")

        # Try to do a 2stepinit on a second step will raise an error
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "totp",
                                               "2stepinit": "1",
                                               "serial": serial,
                                               "otpkey":
                                               base32check_client_component,
                                               "otpkeyformat": "base32check"
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 400)
            result = json.loads(res.data).get("result")
            self.assertIn(
                '2stepinit is only to be used in the first initialization step',
                result.get("error").get("message"))

        # Invalid base32check will raise an error
        with self.app.test_request_context(
                '/token/init',
                method='POST',
                data={
                    "type": "totp",
                    "2stepinit": "1",
                    "serial": serial,
                    "otpkey": "A" + base32check_client_component[1:],
                    "otpkeyformat": "base32check"
                },
                headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertEqual(res.status_code, 400)
            result = json.loads(res.data).get("result")
            self.assertIn('Malformed base32check data: Incorrect checksum',
                          result.get("error").get("message"))

        # Authentication does not work yet!
        wrong_otp_value = HmacOtp().generate(key=server_component,
                                             counter=int(time.time() / 30))
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": wrong_otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data)
            self.assertTrue(result.get("result").get("status"))
            self.assertFalse(result.get("result").get("value"))
            self.assertEqual(
                result.get("detail").get("message"),
                u'matching 1 tokens, Token is disabled')

        # Now doing the correct 2nd step
        with self.app.test_request_context('/token/init',
                                           method='POST',
                                           data={
                                               "type": "totp",
                                               "serial": serial,
                                               "otpkey":
                                               base32check_client_component,
                                               "otpkeyformat": "base32check"
                                           },
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertTrue(result.get("status") is True, result)
            self.assertTrue(result.get("value") is True, result)
            detail = json.loads(res.data).get("detail")
            otpkey_url = detail.get("otpkey", {}).get("value")
            otpkey = otpkey_url.split("/")[2]
            self.assertNotIn('2step', detail)

        # Now try to authenticate
        otpkey_bin = binascii.unhexlify(otpkey)
        otp_value = HmacOtp().generate(key=otpkey_bin,
                                       counter=int(time.time() / 30))
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={
                                               "serial": serial,
                                               "pass": otp_value
                                           }):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            result = json.loads(res.data).get("result")
            self.assertEqual(result.get("status"), True)
            self.assertEqual(result.get("value"), True)

        # Check that the OTP key is what we expected it to be
        expected_secret = pbkdf2(binascii.hexlify(server_component),
                                 client_component, 10000, 20)
        self.assertEqual(otpkey_bin, expected_secret)

        with self.app.test_request_context('/token/' + serial,
                                           method='DELETE',
                                           headers={'Authorization': self.at}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
        delete_policy("allow_2step")
Example #59
0
    def test_03b_api_authenticate_client(self):
        # Test the /validate/check endpoints without the smartphone endpoint /ttype/push
        self.setUp_user_realms()

        # get enrolled push token
        toks = get_tokens(tokentype="push")
        self.assertEqual(len(toks), 1)
        tokenobj = toks[0]

        # set PIN
        tokenobj.set_pin("pushpin")
        tokenobj.add_user(User("cornelius", self.realm1))

        # We mock the ServiceAccountCredentials, since we can not directly contact the Google API
        with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.ServiceAccountCredentials') as mySA:
            # alternative: side_effect instead of return_value
            mySA.from_json_keyfile_name.return_value = myCredentials(myAccessTokenInfo("my_bearer_token"))

            # add responses, to simulate the communication to firebase
            responses.add(responses.POST, 'https://fcm.googleapis.com/v1/projects/test-123456/messages:send',
                          body="""{}""",
                          content_type="application/json")

            # Send the first authentication request to trigger the challenge
            with self.app.test_request_context('/validate/check',
                                               method='POST',
                                               data={"user": "******",
                                                     "realm": self.realm1,
                                                     "pass": "******"}):
                res = self.app.full_dispatch_request()
                self.assertTrue(res.status_code == 200, res)
                jsonresp = res.json
                self.assertFalse(jsonresp.get("result").get("value"))
                self.assertTrue(jsonresp.get("result").get("status"))
                self.assertEqual(jsonresp.get("detail").get("serial"), tokenobj.token.serial)
                self.assertTrue("transaction_id" in jsonresp.get("detail"))
                transaction_id = jsonresp.get("detail").get("transaction_id")
                self.assertEqual(jsonresp.get("detail").get("message"), DEFAULT_CHALLENGE_TEXT)

            # Our ServiceAccountCredentials mock has not been called because we use a cached token
            self.assertEqual(len(mySA.from_json_keyfile_name.mock_calls), 0)
            self.assertIn(FIREBASE_FILE, get_app_local_store()["firebase_token"])

        # The mobile device has not communicated with the backend, yet.
        # The user is not authenticated!
        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={"user": "******",
                                                 "realm": self.realm1,
                                                 "pass": "",
                                                 "transaction_id": transaction_id}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            jsonresp = res.json
            # Result-Value is false, the user has not answered the challenge, yet
            self.assertFalse(jsonresp.get("result").get("value"))

        # Now the smartphone communicates with the backend and the challenge in the database table
        # is marked as answered successfully.
        challengeobject_list = get_challenges(serial=tokenobj.token.serial,
                                              transaction_id=transaction_id)
        challengeobject_list[0].set_otp_status(True)

        with self.app.test_request_context('/validate/check',
                                           method='POST',
                                           data={"user": "******",
                                                 "realm": self.realm1,
                                                 "pass": "",
                                                 "state": transaction_id}):
            res = self.app.full_dispatch_request()
            self.assertTrue(res.status_code == 200, res)
            jsonresp = res.json
            # Result-Value is True, since the challenge is marked resolved in the DB
        self.assertTrue(jsonresp.get("result").get("value"))

        # We mock the ServiceAccountCredentials, since we can not directly contact the Google API
        # Do single shot auth with waiting
        # Also mock time.time to be 4000 seconds in the future (exceeding the validity of myAccessTokenInfo),
        # so that we fetch a new auth token
        with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.time') as mock_time:
            mock_time.time.return_value = time.time() + 4000

            with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.ServiceAccountCredentials') as mySA:
                # alternative: side_effect instead of return_value
                mySA.from_json_keyfile_name.return_value = myCredentials(myAccessTokenInfo("my_new_bearer_token"))

                # add responses, to simulate the communication to firebase
                responses.add(responses.POST, 'https://fcm.googleapis.com/v1/projects/test-123456/messages:send',
                              body="""{}""",
                              content_type="application/json")

                # In two seconds we need to run an update on the challenge table.
                Timer(2, self.mark_challenge_as_accepted).start()

                set_policy("push1", scope=SCOPE.AUTH, action="{0!s}=20".format(PUSH_ACTION.WAIT))
                # Send the first authentication request to trigger the challenge
                with self.app.test_request_context('/validate/check',
                                                   method='POST',
                                                   data={"user": "******",
                                                         "realm": self.realm1,
                                                         "pass": "******"}):
                    res = self.app.full_dispatch_request()
                    self.assertTrue(res.status_code == 200, res)
                    jsonresp = res.json
                    # We successfully authenticated! YEAH!
                    self.assertTrue(jsonresp.get("result").get("value"))
                    self.assertTrue(jsonresp.get("result").get("status"))
                    self.assertEqual(jsonresp.get("detail").get("serial"), tokenobj.token.serial)
                delete_policy("push1")

            # Our ServiceAccountCredentials mock has been called once because we fetched a new token
            self.assertEqual(len(mySA.from_json_keyfile_name.mock_calls), 1)
            self.assertIn(FIREBASE_FILE, get_app_local_store()["firebase_token"])
            self.assertEqual(get_app_local_store()["firebase_token"][FIREBASE_FILE].access_token,
                             "my_new_bearer_token")

        # Authentication fails, if the push notification is not accepted within the configured time
        with mock.patch('privacyidea.lib.smsprovider.FirebaseProvider.ServiceAccountCredentials') as mySA:
            # alternative: side_effect instead of return_value
            mySA.from_json_keyfile_name.return_value = myCredentials(myAccessTokenInfo("my_bearer_token"))

            # add responses, to simulate the communication to firebase
            responses.add(responses.POST, 'https://fcm.googleapis.com/v1/projects/test-123456/messages:send',
                          body="""{}""",
                          content_type="application/json")

            set_policy("push1", scope=SCOPE.AUTH, action="{0!s}=1".format(PUSH_ACTION.WAIT))
            # Send the first authentication request to trigger the challenge
            with self.app.test_request_context('/validate/check',
                                               method='POST',
                                               data={"user": "******",
                                                     "realm": self.realm1,
                                                     "pass": "******"}):
                res = self.app.full_dispatch_request()
                self.assertTrue(res.status_code == 200, res)
                jsonresp = res.json
                # We fail to authenticate! Oh No!
                self.assertFalse(jsonresp.get("result").get("value"))
                self.assertTrue(jsonresp.get("result").get("status"))
                self.assertEqual(jsonresp.get("detail").get("serial"), tokenobj.token.serial)
            delete_policy("push1")
Example #60
0
    def test_01_check_token_action(self):
        g.logged_in_user = {"username": "******", "role": "admin"}
        builder = EnvironBuilder(method='POST',
                                 data={'serial': "OATH123456"},
                                 headers={})
        env = builder.get_environ()
        # Set the remote address so that we can filter for it
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)
        req.all_data = {"serial": "SomeSerial"}

        # Set a policy, that does allow the action
        set_policy(name="pol1",
                   scope=SCOPE.ADMIN,
                   action="enable",
                   client="10.0.0.0/8")
        g.policy_object = PolicyClass()

        # Action enable is cool
        r = check_base_action(request=req, action="enable")
        self.assertTrue(r)

        # Another action - like "disable" - is not allowed
        # An exception is
        self.assertRaises(PolicyError, check_base_action, req, "disable")

        # Action delete is not allowed
        self.assertRaises(PolicyError, check_base_action, req, "delete")

        # check action with a token realm
        set_policy(name="pol1",
                   scope=SCOPE.ADMIN,
                   action="enable",
                   client="10.0.0.0/8",
                   realm="realm1")
        set_policy(name="pol2",
                   scope=SCOPE.ADMIN,
                   action="*",
                   client="10.0.0.0/8",
                   realm="realm2")
        g.policy_object = PolicyClass()
        # set a polrealm1 and a polrealm2
        # setup realm1
        self.setUp_user_realms()
        # setup realm2
        self.setUp_user_realm2()
        tokenobject = init_token({
            "serial": "POL001",
            "type": "hotp",
            "otpkey": "1234567890123456"
        })
        r = set_realms("POL001", [self.realm1])

        tokenobject = init_token({
            "serial": "POL002",
            "type": "hotp",
            "otpkey": "1234567890123456"
        })
        r = set_realms("POL002", [self.realm2])

        # Token in realm1 can not be deleted
        req.all_data = {"serial": "POL001"}
        self.assertRaises(PolicyError, check_base_action, req, "delete")
        # while token in realm2 can be deleted
        req.all_data = {"serial": "POL002"}
        r = check_base_action(req, action="delete")
        self.assertTrue(r)

        # A normal user can "disable", since no user policies are defined.
        g.logged_in_user = {"username": "******", "role": "user"}
        r = check_base_action(req, "disable")
        self.assertTrue(r)
        delete_policy("pol1")
        delete_policy("pol2")
        remove_token("POL001")
        remove_token("POL002")