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")
def do(self, action, options=None): """ This method executes the defined action in the given event. :param action: :param options: Contains the flask parameters g, request, response and the handler_def configuration :type options: dict :return: """ ret = True g = options.get("g") request = options.get("request") response = options.get("response") content = json.loads(response.data) handler_def = options.get("handler_def") handler_options = handler_def.get("options", {}) serial = request.all_data.get("serial") or \ content.get("detail", {}).get("serial") or \ g.audit_object.audit_data.get("serial") if action.lower() in [ACTION_TYPE.SET_TOKENREALM, ACTION_TYPE.DELETE, ACTION_TYPE.DISABLE, ACTION_TYPE.ENABLE, ACTION_TYPE.UNASSIGN]: if serial: if action.lower() == ACTION_TYPE.SET_TOKENREALM: realm = handler_options.get("realm") only_realm = handler_options.get("only_realm") # Set the realm.. log.info("Setting realm of token {0!s} to {1!s}".format( serial, realm)) # Add the token realm set_realms(serial, [realm], add=True) elif action.lower() == ACTION_TYPE.DELETE: log.info("Delete token {0!s}".format(serial)) remove_token(serial=serial) elif action.lower() == ACTION_TYPE.DISABLE: log.info("Disable token {0!s}".format(serial)) enable_token(serial, enable=False) elif action.lower() == ACTION_TYPE.ENABLE: log.info("Enable token {0!s}".format(serial)) enable_token(serial, enable=True) elif action.lower() == ACTION_TYPE.UNASSIGN: log.info("Unassign token {0!s}".format(serial)) unassign_token(serial) else: log.info("Action {0!s} requires serial number. But no serial " "number could be found in request.") if action.lower() == ACTION_TYPE.INIT: log.info("Initializing new token") t = init_token({"type": handler_options.get("tokentype"), "genkey": 1, "realm": handler_options.get("realm", "")}) log.info("New token {0!s} enrolled.".format(t.token.serial)) return ret
def test_03_otppin_for_serial(self): # now create a policy with userstore PW set_policy(name="pol1", scope=SCOPE.AUTH, action="{0!s}={1!s}".format(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_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_03_challenge_text_position_count(self): # test challenge text and position count my_secret = "mysimplesecret" set_policy("pol1", scope=SCOPE.AUTH, action="indexedsecret_{0!s}=5".format(PIIXACTION.COUNT)) set_policy("pol2", scope=SCOPE.AUTH, action="indexedsecret_challenge_text=Hier sind die Positionen: {0!s}") t = init_token({"type": "indexedsecret", "otpkey": my_secret, "serial": "PIIX1234"}) g = FakeFlaskG() g.audit_object = FakeAudit g.policy_object = PolicyClass() # Create a challenge r, message, transaction_id, reply_dict = t.create_challenge(options={"g": g}) attribute = reply_dict.get("attributes") # The challenge text from the policy is used. self.assertIn("Hier sind die Positionen:", message) password_list = [my_secret[x - 1] for x in attribute.get("random_positions")] password = "".join(password_list) # The password has length 5, due to the pol2 self.assertEqual(5, len(password)) # Successful auth r = t.check_challenge_response(passw=password, options={"transaction_id": transaction_id}) self.assertEqual(1, r) delete_policy("pol1") delete_policy("pol2") remove_token("PIIX1234")
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_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")
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)
def test_18_assign_token(self): serial = "ASSTOKEN" user = User("cornelius", resolver=self.resolvername1, realm=self.realm1) tokenobject = init_token({"serial": serial, "otpkey": "1234567890123456"}) r = assign_token(serial, user, pin="1234") self.assertTrue(r) self.assertTrue(tokenobject.token.user_id == "1000", tokenobject.token.user_id) # token already assigned... self.assertRaises(TokenAdminError, assign_token, serial, User("shadow", realm=self.realm1)) # unassign token r = unassign_token(serial) self.assertTrue(r) self.assertTrue(tokenobject.token.user_id == "", tokenobject.token.user_id) remove_token(serial) # assign or unassign a token, that does not exist self.assertRaises(TokenAdminError, assign_token, serial, user) self.assertRaises(TokenAdminError, unassign_token, serial)
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_02a_fail_request_with_attestation(self): cwd = os.getcwd() # setup ca connector r = save_caconnector({ "cakey": CAKEY, "cacert": CACERT, "type": "local", "caconnector": "localCA", "openssl.cnf": OPENSSLCNF, "CSRDir": "", "CertificateDir": "", "WorkingDir": cwd + "/" + WORKINGDIR }) db_token = Token(self.serial2, tokentype="certificate") db_token.save() token = CertificateTokenClass(db_token) # A cert request will fail, since the attestation certificate does not match self.assertRaises(privacyIDEAError, token.update, { "ca": "localCA", "attestation": BOGUS_ATTESTATION, "request": REQUEST }) remove_token(self.serial2)
def test_02_failcounter_max_totp(self): # Check if we can not authenticate with a token that has the maximum # failcounter user = User(login="******", realm=self.realm1) pin = "testTOTP" token = init_token({"serial": pin, "pin": pin, "type": "totp", "otpkey": OTPKEY}, user=user) """ 47251644 942826 47251645 063321 47251646 306773 47251647 722053 47251648 032819 47251649 705493 47251650 589836 """ res, reply = check_user_pass(user, pin + "942826", options={"initTime": 47251644 * 30}) self.assertTrue(res) # Set the failcounter to maximum failcount token.set_failcount(10) # Authentication must fail, since the failcounter is reached res, reply = check_user_pass(user, pin + "032819", options={"initTime": 47251648 * 30}) self.assertFalse(res) self.assertEqual(reply.get("message"), "matching 1 tokens, " "Failcounter exceeded") remove_token(pin)
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" 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="%s=%s" % (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_26_set_sync_window(self): serial = "t1" tokenobject = init_token({"serial": serial, "genkey": 1}) r = set_sync_window(serial, 23) self.assertTrue(r == 1, r) self.assertTrue(tokenobject.token.sync_window == 23, tokenobject.token.sync_window) remove_token(serial)
def test_28_set_description(self): serial = "t1" tokenobject = init_token({"serial": serial, "genkey": 1}) r = set_description(serial, "new description") self.assertTrue(r == 1, r) self.assertTrue(tokenobject.token.description == "new description", tokenobject.token.description) remove_token(serial)
def test_30_set_max_failcount(self): serial = "t1" tokenobject = init_token({"serial": serial, "genkey": 1}) r = set_max_failcount(serial, 112) self.assertTrue(r == 1, r) self.assertTrue(tokenobject.token.maxfail == 112, "%s" % tokenobject.token.maxfail) remove_token(serial)
def test_27_set_count_window(self): serial = "t1" tokenobject = init_token({"serial": serial, "genkey": 1}) r = set_count_window(serial, 45) self.assertTrue(r == 1, r) self.assertTrue(tokenobject.token.count_window == 45, tokenobject.token.count_window) remove_token(serial)
def test_25_add_tokeninfo(self): serial = "t1" tokenobject = init_token({"serial": serial, "genkey": 1}) r = add_tokeninfo(serial, "something", "new") self.assertTrue(r == 1, r) tinfo = tokenobject.token.get_info() self.assertTrue(tinfo.get("something") == "new", tinfo) remove_token(serial)
def test_11_challenge_response_hotp(self): # set a chalresp policy for HOTP with self.app.test_request_context('/policy/pol_chal_resp', data={'action': "challenge_response=hotp", 'scope': "authentication", 'realm': '', 'active': True}, method='POST', 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["status"] is True, result) self.assertTrue('"setPolicy pol_chal_resp": 1' in res.data, res.data) serial = "CHALRESP1" pin = "chalresp1" # create a token and assign to the user db_token = Token(serial, tokentype="hotp") db_token.update_otpkey(self.otpkey) db_token.save() token = HotpTokenClass(db_token) token.set_user(User("cornelius", self.realm1)) token.set_pin(pin) # Set the failcounter token.set_failcount(5) # create the challenge by authenticating with the OTP PIN with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "pass": pin}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") detail = json.loads(res.data).get("detail") self.assertFalse(result.get("value")) self.assertEqual(detail.get("message"), "please enter otp: ") transaction_id = detail.get("transaction_id") self.assertEqual(token.get_failcount(), 5) # send the OTP value with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "transaction_id": transaction_id, "pass": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") detail = json.loads(res.data).get("detail") self.assertTrue(result.get("value")) self.assertEqual(token.get_failcount(), 0) # delete the token remove_token(serial=serial)
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_23_set_otplen(self): serial = "otplen" tokenobject = init_token({"serial": serial, "otpkey": "1234567890123456"}) r = set_otplen(serial=serial, otplen=8) self.assertTrue(r == 1) self.assertTrue(tokenobject.token.otplen == 8) remove_token(serial)
def test_14_check_validity_period(self): serial = "VP001" password = serial init_token({ "serial": serial, "type": "spass", "pin": password }, user=User("cornelius", self.realm1)) with self.app.test_request_context('/validate/check', method='POST', data={ "user": "******", "pass": password }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue(result.get("value")) # Set validity period token_obj = get_tokens(serial=serial)[0] token_obj.set_validity_period_end("01/01/15 10:00") with self.app.test_request_context('/validate/check', method='POST', data={ "user": "******", "pass": password }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertFalse(result.get("value")) details = json.loads(res.data).get("detail") self.assertTrue( "Outside validity period" in details.get("message")) token_obj.set_validity_period_end("01/01/99 10:00") token_obj.set_validity_period_start("01/01/98 10:00") with self.app.test_request_context('/validate/check', method='POST', data={ "user": "******", "pass": password }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertFalse(result.get("value")) details = json.loads(res.data).get("detail") self.assertTrue( "Outside validity period" in details.get("message")) # delete the token remove_token(serial="VP001")
def test_17_set_defaults(self): serial = "SETTOKEN" tokenobject = init_token({"serial": serial, "otpkey": "1234567890123456", "otplen": 8}) self.assertTrue(tokenobject.token.otplen == 8) set_defaults(serial) self.assertTrue(tokenobject.token.otplen == 6) remove_token(serial)
def test_12_challenge_response_sms(self): # set a chalresp policy for SMS with self.app.test_request_context('/policy/pol_chal_resp', data={'action': "challenge_response=sms", 'scope': "authentication", 'realm': '', 'active': True}, method='POST', 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["status"] is True, result) self.assertTrue('"setPolicy pol_chal_resp": 1' in res.data, res.data) serial = "CHALRESP2" pin = "chalresp2" # create a token and assign to the user init_token({"serial": serial, "type": "sms", "otpkey": self.otpkey, "phone": "123456", "pin": pin}, user=User("cornelius", self.realm1)) # create the challenge by authenticating with the OTP PIN with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "pass": pin}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") detail = json.loads(res.data).get("detail") self.assertFalse(result.get("value")) self.assertTrue("The PIN was correct, " "but the SMS could not be sent" in detail.get("message")) transaction_id = detail.get("transaction_id") # disable the token. The detail->message should be empty r = enable_token(serial=serial, enable=False) self.assertEqual(r, True) with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "pass": pin}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") detail = json.loads(res.data).get("detail") self.assertFalse(result.get("value")) self.assertEqual(detail.get("message"), "Token is disabled") # delete the token remove_token(serial=serial)
def test_13_challenge_response_email(self): smtpmock.setdata(response={}) # set a chalresp policy for Email with self.app.test_request_context('/policy/pol_chal_resp', data={'action': "challenge_response=email", 'scope': "authentication", 'realm': '', 'active': True}, method='POST', 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["status"] is True, result) self.assertTrue('"setPolicy pol_chal_resp": 1' in res.data, res.data) serial = "CHALRESP3" pin = "chalresp3" # create a token and assign to the user init_token({"serial": serial, "type": "email", "otpkey": self.otpkey, "email": "*****@*****.**", "pin": pin}, user=User("cornelius", self.realm1)) # create the challenge by authenticating with the OTP PIN with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "pass": pin}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") detail = json.loads(res.data).get("detail") self.assertFalse(result.get("value")) self.assertEqual(detail.get("message"), "Enter the OTP from the " "Email:") transaction_id = detail.get("transaction_id") # send the OTP value # Test with parameter state. with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "state": transaction_id, "pass": "******"}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") detail = json.loads(res.data).get("detail") self.assertTrue(result.get("value")) # delete the token remove_token(serial=serial)
def test_02_init_token(self): # Create the tokenclass via init_token my_secret = "mysimplesecret" t = init_token({"type": "indexedsecret", "otpkey": my_secret, "serial": "PIIX1234"}) self.assertEqual(t.token.tokentype, "indexedsecret") self.assertEqual(t.token.serial, "PIIX1234") remove_token("PIIX1234")
def test_22_set_hashlib(self): serial = "hashlib" tokenobject = init_token({"serial": serial, "otpkey": "1234567890123456"}) r = set_hashlib(serial=serial, hashlib="sha256") self.assertTrue(r == 1) hashlib = tokenobject.token.get_info() self.assertTrue(hashlib.get("hashlib") == "sha256", hashlib) remove_token(serial)
def test_02_create_token_from_request(self): cwd = os.getcwd() # setup ca connector r = save_caconnector({ "cakey": CAKEY, "cacert": CACERT, "type": "local", "caconnector": "localCA", "openssl.cnf": OPENSSLCNF, "CSRDir": "", "CertificateDir": "", "WorkingDir": cwd + "/" + WORKINGDIR }) db_token = Token(self.serial2, tokentype="certificate") db_token.save() token = CertificateTokenClass(db_token) # just upload a ready certificate token.update({"ca": "localCA", "request": REQUEST}) self.assertTrue(token.token.serial == self.serial2, token) self.assertTrue(token.token.tokentype == "certificate", token.token.tokentype) self.assertTrue(token.type == "certificate", token) class_prefix = token.get_class_prefix() self.assertTrue(class_prefix == "CRT", class_prefix) self.assertTrue(token.get_class_type() == "certificate", token) detail = token.get_init_detail() certificate = detail.get("certificate") # At each testrun, the certificate might get another serial number! x509obj = crypto.load_certificate(crypto.FILETYPE_PEM, certificate) self.assertEqual( "{0!r}".format(x509obj.get_issuer()), "<X509Name object '/C=DE/ST=Hessen" "/O=privacyidea/CN=CA001'>") self.assertEqual( "{0!r}".format(x509obj.get_subject()), "<X509Name object '/C=DE/ST=Hessen" "/O=privacyidea/CN=requester.localdomain'>") # Test, if the certificate is also completely stored in the tokeninfo # and if we can retrieve it from the tokeninfo token = get_tokens(serial=self.serial2)[0] certificate = token.get_tokeninfo("certificate") x509obj = crypto.load_certificate(crypto.FILETYPE_PEM, certificate) self.assertEqual( "{0!r}".format(x509obj.get_issuer()), "<X509Name object '/C=DE/ST=Hessen" "/O=privacyidea/CN=CA001'>") self.assertEqual( "{0!r}".format(x509obj.get_subject()), "<X509Name object '/C=DE/ST=Hessen" "/O=privacyidea/CN=requester.localdomain'>") remove_token(self.serial2)
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_17_set_defaults(self): serial = "SETTOKEN" tokenobject = init_token({ "serial": serial, "otpkey": "1234567890123456", "otplen": 8 }) self.assertTrue(tokenobject.token.otplen == 8) set_defaults(serial) self.assertTrue(tokenobject.token.otplen == 6) remove_token(serial)
def test_23_set_otplen(self): serial = "otplen" tokenobject = init_token({ "serial": serial, "otpkey": "1234567890123456" }) r = set_otplen(serial=serial, otplen=8) self.assertTrue(r == 1) self.assertTrue(tokenobject.token.otplen == 8) remove_token(serial)
def test_05_check_max_token_realm(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 = {"realm": self.realm1} # Set a policy, that allows two tokens per realm set_policy(name="pol1", scope=SCOPE.ENROLL, action="max_token_per_realm=2", realm=self.realm1) g.policy_object = PolicyClass() self.setUp_user_realms() # Add the first token into the realm tokenobject = init_token({ "serial": "NEW001", "type": "hotp", "otpkey": "1234567890123456" }) set_realms("NEW001", [self.realm1]) # check the realm, only one token is in it the policy condition will # pass tokenobject_list = get_tokens(realm=self.realm1) self.assertTrue(len(tokenobject_list) == 1) self.assertTrue(check_max_token_realm(req)) # add a second token to the realm tokenobject = init_token({ "serial": "NEW002", "type": "hotp", "otpkey": "1234567890123456" }) set_realms("NEW002", [self.realm1]) tokenobject_list = get_tokens(realm=self.realm1) self.assertTrue(len(tokenobject_list) == 2) # request with a user object, not with a realm req.all_data = {"user": "******".format(self.realm1)} # Now a new policy check will fail, since there are already two # tokens in the realm self.assertRaises(PolicyError, check_max_token_realm, req) # finally delete policy delete_policy("pol1") remove_token("NEW001") remove_token("NEW002")
def test_22_set_hashlib(self): serial = "hashlib" tokenobject = init_token({ "serial": serial, "otpkey": "1234567890123456" }) r = set_hashlib(serial=serial, hashlib="sha256") self.assertTrue(r == 1) hashlib = tokenobject.token.get_info() self.assertTrue(hashlib.get("hashlib") == "sha256", hashlib) remove_token(serial)
def test_16_set_realms(self): serial = "NEWREALM01" tokenobject = init_token({"serial": serial, "otpkey": "1234567890123456"}) realms = get_realms_of_token(serial) self.assertTrue(realms == [], "%s" % realms) rnum = set_realms(serial, [self.realm1]) self.assertTrue(rnum == 1, rnum) realms = get_realms_of_token(serial) self.assertTrue(realms == [self.realm1], "%s" % realms) remove_token(serial=serial) realms = get_realms_of_token(serial) self.assertTrue(realms == [], "%s" % realms)
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") # 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" # 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 = res.json.get("result") detail = res.json.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 = res.json.get("result") 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_12_challenge_response_sms(self): # set a chalresp policy for SMS with self.app.test_request_context('/policy/pol_chal_resp', data={ 'action': "challenge_response=sms", 'scope': "authentication", 'realm': '', 'active': True }, method='POST', 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["status"] is True, result) self.assertTrue('"setPolicy pol_chal_resp": 1' in res.data, res.data) serial = "CHALRESP2" pin = "chalresp2" # create a token and assign to the user init_token( { "serial": serial, "type": "sms", "otpkey": self.otpkey, "phone": "123456", "pin": pin }, user=User("cornelius", self.realm1)) # create the challenge by authenticating with the OTP PIN with self.app.test_request_context('/validate/check', method='POST', data={ "user": "******", "pass": pin }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") detail = json.loads(res.data).get("detail") self.assertFalse(result.get("value")) self.assertTrue( "The PIN was correct, " "but the SMS could not be sent" in detail.get("message")) transaction_id = detail.get("transaction_id") # delete the token remove_token(serial=serial)
def test_06_export_pskc(self): # create three tokens t1 = init_token({"serial": "t1", "type": "hotp", "otpkey": "123456", "description": u"söme ünicøde"}) t2 = init_token({"serial": "t2", "type": "totp", "otpkey": "123456", "description": "something <with> xml!"}) t3 = init_token({"serial": "t3", "type": "spass", "otpkey": "123456"}) t4 = init_token({"serial": "t4", "type": "pw", "otpkey": "lässig", "description": "password token"}) tlist = [t1, t2, t3, t4] # export the tokens psk, token_num, soup = export_pskc(tlist) # Only 3 tokens exported, the spass token does not get exported! self.assertEqual(token_num, 3) self.assertEqual(len(psk), 32) export = "{0!s}".format(soup) # remote the tokens remove_token("t1") remove_token("t2") remove_token("t3") remove_token("t4") # import the tokens again tokens, _ = parsePSKCdata(export, preshared_key_hex=psk) self.assertEqual(len(tokens), 3) self.assertEqual(tokens.get("t1").get("type"), "hotp") self.assertEqual(tokens.get("t1").get("otpkey"), "123456") # unicode gets replaced self.assertEqual(tokens.get("t1").get("description"), "s?me ?nic?de") self.assertEqual(tokens.get("t2").get("type"), "totp") self.assertEqual(tokens.get("t2").get("timeStep"), "30") self.assertEqual(tokens.get("t2").get("description"), "something <with> xml!") # password token self.assertEqual(tokens.get("t4").get("otpkey"), u"lässig")
def test_05_check_max_token_realm(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 = {"realm": self.realm1} # Set a policy, that allows two tokens per realm set_policy(name="pol1", scope=SCOPE.ENROLL, action="max_token_per_realm=2", realm=self.realm1) g.policy_object = PolicyClass() self.setUp_user_realms() # Add the first token into the realm tokenobject = init_token({"serial": "NEW001", "type": "hotp", "otpkey": "1234567890123456"}) set_realms("NEW001", [self.realm1]) # check the realm, only one token is in it the policy condition will # pass tokenobject_list = get_tokens(realm=self.realm1) self.assertTrue(len(tokenobject_list) == 1) self.assertTrue(check_max_token_realm(req)) # add a second token to the realm tokenobject = init_token({"serial": "NEW002", "type": "hotp", "otpkey": "1234567890123456"}) set_realms("NEW002", [self.realm1]) tokenobject_list = get_tokens(realm=self.realm1) self.assertTrue(len(tokenobject_list) == 2) # request with a user object, not with a realm req.all_data = {"user": "******".format(self.realm1)} # Now a new policy check will fail, since there are already two # tokens in the realm self.assertRaises(PolicyError, check_max_token_realm, req) # finally delete policy delete_policy("pol1") remove_token("NEW001") remove_token("NEW002")
def test_16_set_realms(self): serial = "NEWREALM01" tokenobject = init_token({ "serial": serial, "otpkey": "1234567890123456" }) realms = get_realms_of_token(serial) self.assertTrue(realms == [], "%s" % realms) rnum = set_realms(serial, [self.realm1]) self.assertTrue(rnum == 1, rnum) realms = get_realms_of_token(serial) self.assertTrue(realms == [self.realm1], "%s" % realms) remove_token(serial=serial) realms = get_realms_of_token(serial) self.assertTrue(realms == [], "%s" % realms)
def test_01_register_u2f(self): # step 1 with self.app.test_request_context('/token/init', method='POST', data={ "type": "u2f", "serial": self.serial }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) response = res.json result = response.get("result") details = response.get("detail") self.assertEqual(result.get("value"), True) serial = details.get("serial") self.assertEqual(serial[:3], "U2F") self.assertEqual( details.get("u2fRegisterRequest").get("version"), "U2F_V2") challenge = details.get("u2fRegisterRequest").get("challenge") self.assertTrue(len(challenge) > 20) # step 2 # We need to send back regData and clientData. # from the registration example reg_data = "BQRFnd8XtfZzsTK68VPK64Bcjiog_ZzyYNuzjaaGwpPnSpifxaqQV4_4IMxVlGS3CLoQmNAR41MSMxZHG0dENLRmQGnk4OqRxGRHmUOOLmDkGgdIJycQe79JCERV1gqGnWAOFBg_bH4WFSxZwnX-IMRcl3zW_X442QNrrdFySvXrba4wggIcMIIBBqADAgECAgQ4Zt91MAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKzEpMCcGA1UEAwwgWXViaWNvIFUyRiBFRSBTZXJpYWwgMTM4MzExNjc4NjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ3jfx0DHOblHJO09Ujubh2gQZWwT3ob6-uzzjZD1XiyAob_gsw3FOzXefQRblty48r-U-o4LkDFjx_btwuSHtxoxIwEDAOBgorBgEEAYLECgEBBAAwCwYJKoZIhvcNAQELA4IBAQIaR2TKAInPkq24f6hIU45yzD79uzR5KUMEe4IWqTm69METVio0W2FHWXlpeUe85nGqanwGeW7U67G4_WAnGbcd6zz2QumNsdlmb_AebbdPRa95Z8BG1ub_S04JoxQYNLaa8WRlzN7POgqAnAqkmnsZQ_W9Tj2uO9zP3mpxOkkmnqz7P5zt4Lp5xrv7p15hGOIPD5V-ph7tUmiCJsq0LfeRA36X7aXi32Ap0rt_wyfnRef59YYr7SmwaMuXKjbIZSLesscZZTMzXd-uuLb6DbUCasqEVBkGGqTRfAcOmPov1nHUrNDCkOR0obR4PsJG4PiamIfApNeoXGYpGbok6nucMEYCIQC_yerJqB3mnuAJGfbdKuOIx-Flxr-VSQ2nAkUUE_50dQIhAJE2NL1Xs2oVEG4bFzEM86TfS7nkHxad89aYmUrII49V" client_data = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6ImdXbndtYnFSMl9YOE91RFhId0dyQWNmUTBUajN4YTVfZ2RJMjBYcVlsdTg9Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiY2lkX3B1YmtleSI6IiJ9" with self.app.test_request_context('/token/init', method='POST', data={ "serial": serial, "type": "u2f", "regdata": reg_data, "clientdata": client_data }, headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) response = res.json result = response.get("result") self.assertEqual(result.get("value"), True) # In this case we get the automatic description self.assertEqual( get_tokens(serial=serial)[0].token.description, "Yubico U2F EE Serial 13831167861") remove_token(self.serial)
def test_16_remove_token(self): self.assertRaises(ParameterError, remove_token) count1 = get_tokens(count=True) tokenobject = init_token({"type": "hotp", "otpkey": "1234567890123456", "realm": self.realm1}) count2 = get_tokens(count=True) self.assertTrue(count2 == count1 + 1, count2) # check for the token association token_id = tokenobject.token.id realm_assoc = TokenRealm.query.filter(TokenRealm.token_id == \ token_id).count() self.assertTrue(realm_assoc == 1, realm_assoc) # Add a challenge for this token challenge = Challenge(tokenobject.get_serial(), transaction_id="918273") challenge.save() chall_count = Challenge.query.filter(Challenge.serial == tokenobject.get_serial()).count() self.assertTrue(chall_count == 1, chall_count) # remove the token count_remove = remove_token(serial=tokenobject.get_serial()) self.assertTrue(count_remove == 1, count_remove) self.assertTrue(get_tokens(count=True) == count1) # check for the realm association realm_assoc = TokenRealm.query.filter(TokenRealm.token_id == \ token_id).count() self.assertTrue(realm_assoc == 0, realm_assoc) # check if the challenge is removed chall_count = Challenge.query.filter(Challenge.serial == tokenobject.get_serial()).count() self.assertTrue(chall_count == 0, chall_count)
def test_01_set_tokenrealm(self): # setup realms self.setUp_user_realms() self.setUp_user_realm2() init_token({"serial": "SPASS01", "type": "spass"}) g = FakeFlaskG() audit_object = FakeAudit() audit_object.audit_data["serial"] = "SPASS01" g.logged_in_user = {"user": "******", "role": "admin", "realm": ""} g.audit_object = audit_object builder = EnvironBuilder(method='POST', data={'serial': "SPASS01"}, 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 = {"serial": "SPASS01", "type": "spass"} resp = Response() resp.data = """{"result": {"value": true}}""" # Now the initiailized token will be set in realm2 options = { "g": g, "request": req, "response": resp, "handler_def": { "options": { "realm": "realm2" } } } t_handler = TokenEventHandler() res = t_handler.do(ACTION_TYPE.SET_TOKENREALM, options=options) self.assertTrue(res) # Check if the token is contained in realm2 realms = get_realms_of_token("SPASS01") self.assertTrue("realm2" in realms) remove_token("SPASS01")
def test_37_challenge(self): # We create a challenge by first sending the PIN of the HOTP token # then we answer the challenge by sending the OTP. num1 = Challenge.query.filter(Challenge.serial == "hotptoken").count() # The correct PIN will create a challenge r, reply = check_serial_pass("hotptoken", "hotppin") self.assertTrue(r is False, r) num2 = Challenge.query.filter(Challenge.serial == "hotptoken").count() # check that the challenge is created self.assertTrue(num1 + 1 == num2, (num1, num2)) self.assertTrue(type(reply) == dict, reply) transaction_id = reply.get("transaction_id", "") self.assertTrue(len(transaction_id) > 10, reply) # Challenge Response, with the transaction id r, reply = check_serial_pass("hotptoken", "436521", {"transaction_id": transaction_id}) self.assertTrue(r) self.assertTrue( reply.get("message") == "Found matching challenge", reply) # create two tokens with the same OTP Key and the same PIN, so # this token will create the same challenge # creating a challenge will not work! tokenobject = init_token({ "serial": "CHALL001", "type": "hotp", "otpkey": self.otpkey }) tokenobject = init_token({ "serial": "CHALL002", "type": "hotp", "otpkey": self.otpkey }) user = User("cornelius", realm=self.realm1) assign_token("CHALL001", user) assign_token("CHALL002", user) set_pin("CHALL001", "challpin") set_pin("CHALL002", "challpin") r, reply = check_user_pass(user, "challpin") self.assertFalse(r) self.assertTrue( "Multiple tokens to create a challenge found" in reply.get("message"), reply) remove_token("CHALL001") remove_token("CHALL002")
def test_31_copy_token_pin(self): serial1 = "tcopy1" tobject1 = init_token({"serial": serial1, "genkey": 1}) r = set_pin(serial1, "secret") self.assertTrue(r) serial2 = "tcopy2" tobject2 = init_token({"serial": serial2, "genkey": 1}) r = copy_token_pin(serial1, serial2) self.assertTrue(r) # Now compare the pinhash self.assertTrue(tobject1.token.pin_hash == tobject2.token.pin_hash, "%s <> %s" % (tobject1.token.pin_hash, tobject2.token.pin_hash)) remove_token(serial1) remove_token(serial2)
def test_15_reset_all_failcounters(self): self.setUp_user_realms() set_policy("reset_all", scope=SCOPE.AUTH, action=ACTION.RESETALLTOKENS) user = User(login="******", realm=self.realm1) pin1 = "pin1" pin2 = "pin2" token1 = init_token({ "serial": pin1, "pin": pin1, "type": "spass" }, user=user) token2 = init_token({ "serial": pin2, "pin": pin2, "type": "spass" }, user=user) token1.inc_failcount() token2.inc_failcount() token2.inc_failcount() self.assertEqual(token1.token.failcount, 1) self.assertEqual(token2.token.failcount, 2) g.policy_object = PolicyClass() g.audit_object = FakeAudit() g.client_ip = None options = {"g": g} r = reset_all_user_tokens(self.fake_check_token_list, [token1, token2], "pw", None, options=options, allow_reset_all_tokens=True, result=True) self.assertTrue(r) self.assertEqual(token1.token.failcount, 0) self.assertEqual(token2.token.failcount, 0) # Clean up remove_token(pin1) remove_token(pin2)
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") # 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" # 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) 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.decode('utf8')).get("result") 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_31_copy_token_pin(self): serial1 = "tcopy1" tobject1 = init_token({"serial": serial1, "genkey": 1}) r = set_pin(serial1, "secret") self.assertTrue(r) serial2 = "tcopy2" tobject2 = init_token({"serial": serial2, "genkey": 1}) r = copy_token_pin(serial1, serial2) self.assertTrue(r) # Now compare the pinhash self.assertTrue( tobject1.token.pin_hash == tobject2.token.pin_hash, "%s <> %s" % (tobject1.token.pin_hash, tobject2.token.pin_hash)) remove_token(serial1) remove_token(serial2)
def test_14_check_validity_period(self): serial = "VP001" password = serial init_token({"serial": serial, "type": "spass", "pin": password}, user=User("cornelius", self.realm1)) with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "pass": password}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertTrue(result.get("value")) # Set validity period token_obj = get_tokens(serial=serial)[0] token_obj.set_validity_period_end("01/01/15 10:00") with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "pass": password}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertFalse(result.get("value")) details = json.loads(res.data).get("detail") self.assertTrue("Outside validity period" in details.get("message")) token_obj.set_validity_period_end("01/01/99 10:00") token_obj.set_validity_period_start("01/01/98 10:00") with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "pass": password}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") self.assertFalse(result.get("value")) details = json.loads(res.data).get("detail") self.assertTrue("Outside validity period" in details.get("message")) # delete the token remove_token(serial="VP001")
def test_20_pin_token_so_user(self): serial = "pins" tokenobject = init_token({"serial": serial, "otpkey": "1234567890123456"}) # user parameter is wrong self.assertRaises(ParameterError, set_pin, serial, None, "1234") # user and serial is missing self.assertRaises(ParameterError, set_pin) # now set the pin self.assertTrue(set_pin(serial, "1234") == 1) self.assertTrue(tokenobject.token.check_pin("1234")) self.assertTrue(tokenobject.token.user_pin == "") self.assertTrue(set_pin_user(serial, "1234") == 1) self.assertTrue(tokenobject.token.user_pin != "") self.assertTrue(tokenobject.token.so_pin == "") self.assertTrue(set_pin_so(serial, "1234") == 1) self.assertTrue(tokenobject.token.so_pin != "") remove_token(serial)
def test_04_unassign(self): # setup realms self.setUp_user_realms() init_token({ "serial": "SPASS01", "type": "spass" }, User("cornelius", self.realm1)) t = get_tokens(serial="SPASS01") uid = t[0].get_user_id() self.assertEqual(uid, "1000") g = FakeFlaskG() audit_object = FakeAudit() audit_object.audit_data["serial"] = "SPASS01" g.logged_in_user = {"user": "******", "role": "admin", "realm": ""} g.audit_object = audit_object builder = EnvironBuilder(method='POST', data={'serial': "SPASS01"}, 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 = {"serial": "SPASS01", "type": "spass"} resp = Response() resp.data = """{"result": {"value": true}}""" # Now the initiailized token will be set in realm2 options = {"g": g, "request": req, "response": resp, "handler_def": {}} t_handler = TokenEventHandler() res = t_handler.do(ACTION_TYPE.UNASSIGN, options=options) self.assertTrue(res) # Check if the token was unassigned t = get_tokens(serial="SPASS01") uid = t[0].get_user_id() self.assertEqual(uid, "") remove_token("SPASS01")
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_19_reset_resync(self): serial = "reset" tokenobject = init_token({"serial": serial, "otpkey": "1234567890123456"}) otps = tokenobject.get_multi_otp(count=100) self.assertTrue(tokenobject.token.count == 0) # 20: '122407', 21: '505117', 22: '870960', 23: '139843', 24: '631376' self.assertTrue(otps[2].get("otp").get(20) == "122407", otps[2]) self.assertTrue(tokenobject.token.count == 0) r = resync_token(serial, "122407", "505117") self.assertTrue(r) self.assertTrue(tokenobject.token.count == 22, tokenobject.token.count) tokenobject.token.failcount = 20 r = reset_token(serial) self.assertTrue(r) self.assertTrue(tokenobject.token.failcount == 0) remove_token(serial) self.assertRaises(ParameterError, reset_token)
def test_10_auth_items_ssh_ecdsa(self): # create an SSH token token_obj = init_token({ "serial": self.serial2, "type": "sshkey", "sshkey": SSHKEY_ecdsa }) 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("ecdsa-sha2-nistp256"), 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("ecdsa-sha2-nistp256"), sshkey) detach_token(self.serial2, application="ssh", hostname="gandalf") remove_token(self.serial2)
def test_21_enable_disable(self): serial = "enable" tokenobject = init_token({"serial": serial, "otpkey": "1234567890123456"}) # an active token does not need to be enabled r = enable_token(serial) self.assertTrue(r == 0, r) r = enable_token(serial, enable=False) self.assertTrue(r == 1, r) self.assertTrue(tokenobject.token.active == False, tokenobject.token.active) self.assertFalse(is_token_active(serial)) r = enable_token(serial) self.assertTrue(r == 1, r) self.assertTrue(is_token_active(serial)) remove_token(serial) self.assertTrue(is_token_active(serial) is None) self.assertRaises(ParameterError, enable_token)
def test_37_challenge(self): # We create a challenge by first sending the PIN of the HOTP token # then we answer the challenge by sending the OTP. num1 = Challenge.query.filter(Challenge.serial == "hotptoken").count() # The correct PIN will create a challenge r, reply = check_serial_pass("hotptoken", "hotppin") self.assertTrue(r is False, r) num2 = Challenge.query.filter(Challenge.serial == "hotptoken").count() # check that the challenge is created self.assertTrue(num1 + 1 == num2, (num1, num2)) self.assertTrue(type(reply) == dict, reply) transaction_id = reply.get("transaction_id","") self.assertTrue(len(transaction_id) > 10, reply) # Challenge Response, with the transaction id r, reply = check_serial_pass("hotptoken", "436521", {"transaction_id": transaction_id}) self.assertTrue(r) self.assertTrue(reply.get("message") == "Found matching challenge", reply) # create two tokens with the same OTP Key and the same PIN, so # this token will create the same challenge # creating a challenge will not work! tokenobject = init_token({"serial": "CHALL001", "type": "hotp", "otpkey": self.otpkey}) tokenobject = init_token({"serial": "CHALL002", "type": "hotp", "otpkey": self.otpkey}) user = User("cornelius", realm=self.realm1) assign_token("CHALL001", user) assign_token("CHALL002", user) set_pin("CHALL001", "challpin") set_pin("CHALL002", "challpin") r, reply = check_user_pass(user, "challpin") self.assertFalse(r) self.assertTrue("Multiple tokens to create a challenge found" in reply.get("message"), reply) remove_token("CHALL001") remove_token("CHALL002")