def test_03_check_subscription(self): # A valid subscription r = save_subscription(SUBSCRIPTION1) self.assertTrue(r) s = check_subscription("demo_application") self.assertTrue(s) # A subscription, that has expired r = save_subscription(SUBSCRIPTION3) self.assertTrue(r) # The subscription, which has expired 100 days ago raises an exception self.assertRaises(SubscriptionError, check_subscription, "demo_application") self.setUp_user_realms() init_token({"type": "spass"}, user=User("cornelius", self.realm1)) init_token({"type": "spass"}, user=User("cornelius", self.realm1)) init_token({"type": "spass"}, user=User("cornelius", self.realm1)) save_subscription(SUBSCRIPTION4) # We have only one user with tokens, so having a subscription of 3 is fine! s = check_subscription("demo_application") self.assertTrue(s) init_token({"type": "spass"}, user=User("shadow", self.realm1)) init_token({"type": "spass"}, user=User("nopw", self.realm1)) # Now we have three users with tokens, subscription will fail self.assertRaises(SubscriptionError, check_subscription, "demo_application")
def test_08_config_lost_token_policy(self): def func1(serial, validity=10, contents="Ccns", pw_len=16, options=None): self.assertEqual(validity, 10) self.assertEqual(contents, "Ccns") self.assertEqual(pw_len, 16) def func2(serial, validity=10, contents="Ccns", pw_len=16, options=None): self.assertEqual(validity, 5) self.assertEqual(contents, "C") self.assertEqual(pw_len, 3) init_token({"serial": "LOST001", "type": "hotp", "genkey": 1}, user=User("cornelius", realm="r1")) g = FakeFlaskG() P = PolicyClass() g.policy_object = P options = {"g": g} # No policy, the function is called with default values config_lost_token(func1, "LOST001", options=options) set_policy( name="lost_pol2", scope=SCOPE.ENROLL, action="%s=%s, %s=%s," "%s=%s" % (ACTION.LOSTTOKENPWCONTENTS, "C", ACTION.LOSTTOKENVALID, 5, ACTION.LOSTTOKENPWLEN, 3), ) g = FakeFlaskG() P = PolicyClass() g.policy_object = P options = {"g": g} # Policy is set, the function is called with check_otp=True config_lost_token(func2, "LOST001", options=options)
def test_02_get_auth_item(self): serial = "OATH1" # create realm self.setUp_user_realms() user = User("cornelius", realm=self.realm1) # create ssh token init_token({"serial": serial, "type": "hotp", "otpkey": OTPKEY}, user=user) # authenticate online initially tok = get_tokens(serial=serial)[0] res = tok.check_otp("359152") # count = 2 self.assertEqual(res, 2) # check intermediate counter value self.assertEqual(tok.token.count, 3) auth_item = OfflineApplication.get_authentication_item("hotp", serial) self.assertTrue(passlib.hash.\ pbkdf2_sha512.verify("969429", # count = 3 auth_item.get("response").get(0))) self.assertTrue(passlib.hash.\ pbkdf2_sha512.verify("399871", # count = 8 auth_item.get("response").get(5))) # After calling auth_item the token counter should be increased # 3, because we used the otp value with count = 2 initially # 100, because we obtained 100 offline OTPs self.assertEqual(tok.token.count, 3 + 100) # Assert that we cannot authenticate with the last offline OTP we got self.assertEqual(len(auth_item.get("response")), 100) self.assertTrue(passlib.hash.\ pbkdf2_sha512.verify("629694", # count = 102 auth_item.get("response").get(99))) res = tok.check_otp("629694") # count = 102 self.assertEqual(res, -1) res = tok.check_otp("378717") # count = 103 self.assertEqual(res, 103)
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 setUp(self): self.setUp_user_realms() self.user = User(login='******', resolver=self.resolvername1, realm=self.realm1) set_privacyidea_config("u2f.appId", self.app_id) # init step 1 self.token1 = init_token({'type': 'u2f'}) self.serial1 = self.token1.token.serial # finish init step 1 res = self.token1.get_init_detail() # init step 2 self.token1 = init_token( { "type": "u2f", "serial": self.serial1, "regdata": self.reg_data1, "clientdata": self.client_data1 }, user=self.user) # Token 2 # init step 1 self.token2 = init_token({'type': 'u2f'}) self.serial2 = self.token2.token.serial # finish init step 1 res = self.token2.get_init_detail() # init step 2 self.token2 = init_token( { "type": "u2f", "serial": self.serial2, "regdata": self.reg_data2, "clientdata": self.client_data2 }, user=self.user)
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"}) tlist = [t1, t2, t3] # export the tokens psk, token_num, soup = export_pskc(tlist) # Only 2 tokens exported, the spass token does not get exported! self.assertEqual(token_num, 2) self.assertEqual(len(psk), 32) export = "{0!s}".format(soup) # remote the tokens remove_token("t1") remove_token("t2") remove_token("t3") # import the tokens again tokens = parsePSKCdata(export, preshared_key_hex=psk) self.assertEqual(len(tokens), 2) self.assertEqual(tokens.get("t1").get("type"), "hotp") self.assertEqual(tokens.get("t1").get("otpkey"), "123456") # unicode does not get exported self.assertEqual(tokens.get("t1").get("description"), "deleted during export") 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!")
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_09_pin_policies(self): g.logged_in_user = {"username": "******", "role": "user"} 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) # Set a policy that defines PIN policy set_policy(name="pol1", scope=SCOPE.USER, action="{0!s}={1!s},{2!s}={3!s},{4!s}={5!s}".format( ACTION.OTPPINMAXLEN, "10", ACTION.OTPPINMINLEN, "4", ACTION.OTPPINCONTENTS, "cn")) g.policy_object = PolicyClass() req.all_data = {"user": "******", "realm": "home"} # The minimum OTP length is 4 self.assertRaises(PolicyError, check_otp_pin, req) req.all_data = { "user": "******", "realm": "home", "pin": "12345566890012" } # Fail maximum OTP length self.assertRaises(PolicyError, check_otp_pin, req) req.all_data = {"user": "******", "realm": "home", "pin": "123456"} # Good OTP length, but missing character A-Z self.assertRaises(PolicyError, check_otp_pin, req) req.all_data = {"user": "******", "realm": "home", "pin": "abc123"} # Good length and good contents self.assertTrue(check_otp_pin(req)) # A token that does not use pins is ignored. init_token({"type": "certificate", "serial": "certificate"}) req.all_data = { "serial": "certificate", "realm": "somerealm", "user": "******", "pin": "" } self.assertTrue(check_otp_pin(req)) init_token({"type": "sshkey", "serial": "sshkey", "sshkey": SSHKEY}) req.all_data = { "serial": "sshkey", "realm": "somerealm", "user": "******", "pin": "" } self.assertTrue(check_otp_pin(req)) # finally delete policy delete_policy("pol1")
def test_43_encryptpin(self): serial = "ENC01" # encrypt pin on init init_token({ "serial": serial, "genkey": 1, "pin": "Hallo", "encryptpin": True }) tokenobj = get_tokens(serial=serial)[0] self.assertEqual(tokenobj.token.pin_hash[0:2], "@@") # set a hashed pin set_pin(serial, "test", encrypt_pin=False) tokenobj = get_tokens(serial=serial)[0] self.assertTrue(tokenobj.token.pin_hash[0:2] != "@@") # set an encrypted PIN set_pin(serial, "test", encrypt_pin=True) tokenobj = get_tokens(serial=serial)[0] self.assertEqual(tokenobj.token.pin_hash[0:2], "@@") # assign the token with a PIN assign_token(serial, User(login="******", realm=self.realm1), pin="WellWell", encrypt_pin=True) # check if pinhash starts with "@@" to indicate the encryption tokenobj = get_tokens(serial=serial)[0] self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")
def test_43_encryptpin(self): serial = "ENC01" # encrypt pin on init init_token({"serial": serial, "genkey": 1, "pin": "Hallo", "encryptpin": True}) tokenobj = get_tokens(serial=serial)[0] self.assertEqual(tokenobj.token.pin_hash[0:2], "@@") # set a hashed pin set_pin(serial, "test", encrypt_pin=False) tokenobj = get_tokens(serial=serial)[0] self.assertTrue(tokenobj.token.pin_hash[0:2] != "@@") # set an encrypted PIN set_pin(serial, "test", encrypt_pin=True) tokenobj = get_tokens(serial=serial)[0] self.assertEqual(tokenobj.token.pin_hash[0:2], "@@") # assign the token with a PIN assign_token(serial, User(login="******", realm=self.realm1), pin="WellWell", encrypt_pin=True) # check if pinhash starts with "@@" to indicate the encryption tokenobj = get_tokens(serial=serial)[0] self.assertEqual(tokenobj.token.pin_hash[0:2], "@@")
def test_03_inc_failcounter_of_all_tokens(self): # If a user has more than one token and authenticates with wrong OTP # PIN, the failcounter on all tokens should be increased user = User(login="******", realm=self.realm1) pin1 = "pin1" pin2 = "pin2" token1 = init_token({"serial": pin1, "pin": pin1, "type": "hotp", "genkey": 1}, user=user) token2 = init_token({"serial": pin2, "pin": pin2, "type": "hotp", "genkey": 1}, user=user) # Authenticate with pin1 will increase first failcounter res, reply = check_user_pass(user, pin1 + "000000") self.assertEqual(res, False) self.assertEqual(reply.get("message"), "wrong otp value") self.assertEqual(token1.token.failcount, 1) self.assertEqual(token2.token.failcount, 0) # Authenticate with a wrong PIN will increase all failcounters res, reply = check_user_pass(user, "XXX" + "000000") self.assertEqual(res, False) self.assertEqual(reply.get("message"), "wrong otp pin") self.assertEqual(token1.token.failcount, 2) self.assertEqual(token2.token.failcount, 1)
def test_02_attach_token(self): serial = "S1" # create token init_token({"serial": serial, "type": "spass"}) with self.app.test_request_context('/machine/token', method='POST', data={ "hostname": "gandalf", "serial": serial, "application": "luks", "slot": "1" }, 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) self.assertTrue(result["value"] >= 1) # check if the options were set. token_obj = get_tokens(serial=serial)[0] self.assertEqual(token_obj.token.machine_list[0].application, "luks") self.assertEqual(token_obj.token.machine_list[0].option_list[0].mt_key, "slot")
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 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 setUp(self): self.setUp_user_realms() set_policy(name="WebAuthn", scope=SCOPE.ENROLL, action='{0!s}={1!s},{2!s}={3!s}'.format(WEBAUTHNACTION.RELYING_PARTY_NAME, self.rp_name, WEBAUTHNACTION.RELYING_PARTY_ID, self.rp_id)) set_privacyidea_config(WEBAUTHNCONFIG.APP_ID, self.app_id) self.user = User(login='******', realm=self.realm1, resolver=self.resolvername1) # TODO: extract token enrollment into a local function # init token step 1 self.token1 = init_token({'type': 'webauthn', 'serial': self.serial1}, user=self.user) # TODO: use mocking to set nonce with patch('privacyidea.lib.tokens.webauthntoken.WebAuthnTokenClass._get_nonce') as mock_nonce: mock_nonce.return_value = webauthn_b64_decode(self.nonce1) res = self.token1.get_init_detail(self.init_params, self.user) self.assertEqual(self.serial1, res['serial'], res) self.assertEqual(self.nonce1, res['webAuthnRegisterRequest']['nonce'], res) # init token step 2 self.token1.update({ 'type': 'webauthn', 'serial': self.serial1, 'regdata': self.reg_data1, 'clientdata': self.client_data1, WEBAUTHNACTION.RELYING_PARTY_ID: self.rp_id, WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_LEVEL: ATTESTATION_LEVEL.NONE, 'HTTP_ORIGIN': self.app_id }) res = self.token1.get_init_detail() self.assertEqual('Yubico U2F EE Serial 61730834', res['webAuthnRegisterResponse']['subject'], res) # enroll the second webauthn token # init token step 1 self.token2 = init_token({'type': 'webauthn', 'serial': self.serial2}, user=self.user) with patch('privacyidea.lib.tokens.webauthntoken.WebAuthnTokenClass._get_nonce') as mock_nonce: mock_nonce.return_value = webauthn_b64_decode(self.nonce2) res = self.token2.get_init_detail(self.init_params, self.user) self.assertEqual(self.serial2, res['serial'], res) self.assertEqual(self.nonce2, res['webAuthnRegisterRequest']['nonce'], res) # init token step 2 self.token2.update({ 'type': 'webauthn', 'serial': self.serial2, 'regdata': self.reg_data2, 'clientdata': self.client_data2, WEBAUTHNACTION.RELYING_PARTY_ID: self.rp_id, WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_LEVEL: ATTESTATION_LEVEL.NONE, 'HTTP_ORIGIN': self.app_id }) res = self.token2.get_init_detail() self.assertEqual('Yubico U2F EE Serial 23925734103241087', res['webAuthnRegisterResponse']['subject'], res)
def test_14_get_serial_by_otp(self): self._create_temp_token("T1") self._create_temp_token("T2") self._create_temp_token("T3") init_token({"serial": "GETSERIAL", "otpkey": OTPKEY}) # multiple tokens are matching! with self.app.test_request_context('/token/getserial/162583', method="GET", headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 400, res) init_token({"serial": "GETSERIAL2", "otpkey": OTPKEY2}) with self.app.test_request_context('/token/getserial/316522', method="GET", headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") value = result.get("value") self.assertEqual(value.get("serial"), "GETSERIAL2") # If one OTP values was found, it can not be used again with self.app.test_request_context('/token/getserial/316522', method="GET", headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") value = result.get("value") self.assertEqual(value.get("serial"), None) # Will not find an assigned token with self.app.test_request_context('/token/getserial/413789' '?assigned=1', method="GET", headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") value = result.get("value") self.assertNotEqual(value.get("serial"), "GETSERIAL2") # Will find a substr with self.app.test_request_context('/token/getserial/413789' '?unassigned=1&string=SERIAL', method="GET", headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") value = result.get("value") self.assertEqual(value.get("serial"), "GETSERIAL2")
def test_04_list_tokens_for_machine(self): serial = "serial2" init_token({"type": "spass", "serial": serial}) mt = attach_token(serial, "luks", hostname="gandalf") tokenlist = list_machine_tokens(hostname="gandalf") self.assertEqual(len(tokenlist), 2)
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_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_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_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_41_get_tokens_paginate(self): # create some tokens for serial in ["S1", "S2", "S3", "A8", "B", "X"]: init_token({ "serial": serial, "type": "hotp", "otpkey": self.otpkey, "realm": self.realm1 }) token_count = 15 # return pagination tokens = get_tokens_paginate(sortby=Token.serial, page=1, psize=5) self.assertTrue( len(tokens.get("tokens")) == 5, len(tokens.get("tokens"))) self.assertEqual(tokens.get("count"), token_count) self.assertTrue(tokens.get("next") == 2, tokens.get("next")) self.assertTrue(tokens.get("prev") is None, tokens.get("prev")) tokens = get_tokens_paginate(sortby=Token.serial, page=2, psize=5) self.assertEqual(len(tokens.get("tokens")), 5) self.assertEqual(tokens.get("count"), token_count) self.assertEqual(tokens.get("next"), 3) self.assertEqual(tokens.get("prev"), 1) tokens = get_tokens_paginate(sortby=Token.serial, page=3, psize=5) self.assertEqual(len(tokens.get("tokens")), 4) self.assertEqual(tokens.get("count"), token_count) self.assertEqual(tokens.get("next"), None) self.assertEqual(tokens.get("prev"), 2) # Test filtering and sorting tokens = get_tokens_paginate(assigned=True, page=1) self.assertTrue( len(tokens.get("tokens")) == 2, len(tokens.get("tokens"))) self.assertTrue(tokens.get("count") == 2, tokens.get("count")) self.assertTrue(tokens.get("next") is None, tokens.get("next")) self.assertTrue(tokens.get("prev") is None, tokens.get("prev")) tokens = get_tokens_paginate(sortby=Token.serial, page=1, sortdir="desc") self.assertTrue(len(tokens.get("tokens")), token_count - 1) self.assertEqual(tokens.get("count"), token_count) self.assertTrue(tokens.get("next") is None, tokens.get("next")) self.assertTrue(tokens.get("prev") is None, tokens.get("prev")) # Test to retrieve tokens of user cornelius tokens = get_tokens_paginate(user=User("cornelius", "realm1")) self.assertTrue( len(tokens.get("tokens")) == 2, len(tokens.get("tokens"))) # test to retrieve tokens with not strict serial matching tokens = get_tokens_paginate(serial="hotp*") self.assertTrue( len(tokens.get("tokens")) == 1, len(tokens.get("tokens")))
def test_15_validate_at_sign(self): self.setUp_user_realm2() serial1 = "Split001" serial2 = "Split002" init_token({"serial": serial1, "type": "spass", "pin": serial1}, user=User("cornelius", self.realm1)) init_token({"serial": serial2, "type": "spass", "pin": serial2}, user=User("cornelius", self.realm2)) with self.app.test_request_context('/validate/check', method='POST', data={"user": "******", "pass": serial1}): 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_privacyidea_config("splitAtSign", "0") with self.app.test_request_context('/validate/check', method='POST', data={"user": "******"+self.realm2, "pass": serial2}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 400, res) set_privacyidea_config("splitAtSign", "1") with self.app.test_request_context('/validate/check', method='POST', data={"user": "******"+self.realm2, "pass": serial2}): 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")) # The default behaviour - if the config entry does not exist, # is to split the @Sign delete_privacyidea_config("splitAtSign") with self.app.test_request_context('/validate/check', method='POST', data={"user": "******"+self.realm2, "pass": serial2}): 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"))
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")
def test_41_get_tokens_paginate(self): for serial in ["S1", "S2", "S3", "A8", "B", "X"]: init_token({"serial": "AUTO003", "type": "hotp", "otpkey":self.otpkey, "realm": self.realm1}) # return pagination tokens = get_tokens_paginate(sortby=Token.serial, page=1, psize=5) self.assertTrue(len(tokens.get("tokens")) == 5, len(tokens.get("tokens"))) self.assertTrue(tokens.get("count") == 13, tokens.get("count")) self.assertTrue(tokens.get("next") == 2, tokens.get("next")) self.assertTrue(tokens.get("prev") is None, tokens.get("prev")) tokens = get_tokens_paginate(sortby=Token.serial, page=2, psize=5) self.assertTrue(len(tokens.get("tokens")) == 5, len(tokens.get("tokens"))) self.assertTrue(tokens.get("count") == 13, tokens.get("count")) self.assertTrue(tokens.get("next") == 3, tokens.get("next")) self.assertTrue(tokens.get("prev") == 1, tokens.get("prev")) tokens = get_tokens_paginate(sortby=Token.serial, page=3, psize=5) self.assertTrue(len(tokens.get("tokens")) == 2, len(tokens.get("tokens"))) self.assertTrue(tokens.get("count") == 13, tokens.get("count")) self.assertTrue(tokens.get("next") is None, tokens.get("next")) self.assertTrue(tokens.get("prev") == 2, tokens.get("prev")) # Test filtering and sorting tokens = get_tokens_paginate(assigned=True, page=1) self.assertTrue(len(tokens.get("tokens")) == 2, len(tokens.get("tokens"))) self.assertTrue(tokens.get("count") == 2, tokens.get("count")) self.assertTrue(tokens.get("next") is None, tokens.get("next")) self.assertTrue(tokens.get("prev") is None, tokens.get("prev")) tokens = get_tokens_paginate(sortby=Token.serial, page=1, sortdir="desc") self.assertTrue(len(tokens.get("tokens")) == 12, len(tokens.get("tokens"))) self.assertTrue(tokens.get("count") == 13, tokens.get("count")) self.assertTrue(tokens.get("next") is None, tokens.get("next")) self.assertTrue(tokens.get("prev") is None, tokens.get("prev")) # Test to retrieve tokens of user cornelius tokens = get_tokens_paginate(user=User("cornelius", "realm1")) self.assertTrue(len(tokens.get("tokens")) == 2, len(tokens.get("tokens"))) # test to retrieve tokens with not strict serial matching tokens = get_tokens_paginate(serial="hotp*") self.assertTrue(len(tokens.get("tokens")) == 1, len(tokens.get("tokens")))
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_00_setup(self): token1 = init_token({"type": "spass", "serial": self.serial}) resolver1 = save_resolver({ "name": self.resolvername, "type": "hosts", "filename": HOSTSFILE }) init_token({ "type": "hotp", "serial": self.serialHotp, "otpkey": "313233" })
def test_05_check_serial_with_no_user(self): # Check a token per serial when the token has no user assigned. init_token({"serial": "nouser", "otpkey": self.otpkey, "pin": "pin"}) with self.app.test_request_context( "/validate/check", method="POST", data={"serial": "nouser", "pass": "******"} ): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") details = json.loads(res.data).get("detail") self.assertEqual(result.get("status"), True) self.assertEqual(result.get("value"), True)
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(response=radiusmock.AccessAccept) 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")
def test_02_get_auth_item(self): serial = "ssh1" # create realm self.setUp_user_realms() user = User("cornelius", realm=self.realm1) # create ssh token init_token({"serial": serial, "type": "sshkey", "sshkey": SSHKEY}, user=user) auth_item = SSHApplication.get_authentication_item("sshkey", serial) self.assertEqual(auth_item.get("sshkey"), SSHKEY) self.assertEqual(auth_item.get("username"), "cornelius")
def test_47_use_yubikey_and_hotp(self): # fix problem https://github.com/privacyidea/privacyidea/issues/279 user = User("cornelius", self.realm1) token = init_token({"type": "hotp", "otpkey": self.otpkey, "pin": "pin47"}, user) token = init_token({"type": "yubikey", "otpkey": self.otpkey, "pin": "pin47"}, user) r = check_user_pass(user, "pin47888888") self.assertEqual(r[0], False) self.assertEqual(r[1].get('message'), "wrong otp value")
def test_01b_create_token_with_policy(self): token = init_token({"type": "registration", "registration.length": "15", "registration.contents": "-sc"}) init_detail = token.get_init_detail() registrationcode = init_detail.get("registrationcode") # the registrationcode should only contain 15 digits self.assertEqual(15, len(registrationcode)) self.assertTrue(int(registrationcode)) token = init_token({"type": "registration"}) init_detail = token.get_init_detail() registrationcode = init_detail.get("registrationcode") self.assertEqual(DEFAULT_LENGTH, len(registrationcode))
def test_03_authenticate(self): init_token({"type": "pw", "otpkey": "password1", "pin": "pin1"}, user=User("cornelius", self.realm1)) init_token({"type": "pw", "otpkey": "password2", "pin": "pin2"}, user=User("cornelius", self.realm1)) init_token({"type": "pw", "otpkey": "password3", "pin": "pin3"}, user=User("cornelius", self.realm1)) init_token({"serial": "eye1", "type": "4eyes", "4eyes": "{0!s}:2".format(self.realm1), "separator": " "}) r = check_serial_pass("eye1", "pin1password1 pin2password2") self.assertEqual(r[0], True) r = check_serial_pass("eye1", "pin1password1") self.assertEqual(r[0], False) self.assertEqual(r[1].get("foureyes"), "Only found 1 tokens in realm " "realm1")
def test_01_tiqr(self): init_token({"serial": "TIQR1", "type": "tiqr"}, User("cornelius", self.realm1)) with self.app.test_request_context('/ttype/tiqr', method='POST', data={"action": "metadata", "serial": "TIQR1", "session": "12345"}): res = self.app.full_dispatch_request() data = json.loads(res.data.decode('utf8')) identity = data.get("identity") service = data.get("service") self.assertEqual(identity.get("displayName"), "Cornelius ") self.assertEqual(service.get("displayName"), "privacyIDEA")
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_44_validity_period(self): serial = "VAL01" init_token({"serial": serial, "genkey": 1, "pin": "Hallo"}) tokenobj = get_tokens(serial=serial)[0] r = set_validity_period_start(serial, None, "22/05/15 20:21") self.assertEqual(r, 1) r = set_validity_period_end(serial, None, "28/05/15 20:22") self.assertEqual(r, 1) vp = tokenobj.get_validity_period_start() self.assertEqual(vp, "22/05/15 20:21") vp = tokenobj.get_validity_period_end() self.assertEqual(vp, "28/05/15 20:22")
def test_03_authenticate(self): init_token({"type": "pw", "otpkey": "password1", "pin": "pin1"}, user=User("cornelius", self.realm1)) init_token({"type": "pw", "otpkey": "password2", "pin": "pin2"}, user=User("cornelius", self.realm1)) init_token({"type": "pw", "otpkey": "password3", "pin": "pin3"}, user=User("cornelius", self.realm1)) init_token({"serial": "eye1", "type": "4eyes", "4eyes": "%s:2" % self.realm1, "separator": " "}) r = check_serial_pass("eye1", "pin1password1 pin2password2") self.assertEqual(r[0], True) r = check_serial_pass("eye1", "pin1password1") self.assertEqual(r[0], False) self.assertEqual(r[1].get("foureyes"), "Only found 1 tokens in realm " "realm1")
def test_08_config_lost_token_policy(self): def func1(serial, validity=10, contents="Ccns", pw_len=16, options=None): self.assertEqual(validity, 10) self.assertEqual(contents, "Ccns") self.assertEqual(pw_len, 16) def func2(serial, validity=10, contents="Ccns", pw_len=16, options=None): self.assertEqual(validity, 5) self.assertEqual(contents, "C") self.assertEqual(pw_len, 3) init_token({ "serial": "LOST001", "type": "hotp", "genkey": 1 }, user=User("cornelius", realm="r1")) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} # No policy, the function is called with default values config_lost_token(func1, "LOST001", options=options) set_policy(name="lost_pol2", scope=SCOPE.ENROLL, action="%s=%s, %s=%s," "%s=%s" % (ACTION.LOSTTOKENPWCONTENTS, "C", ACTION.LOSTTOKENVALID, 5, ACTION.LOSTTOKENPWLEN, 3)) 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 config_lost_token(func2, "LOST001", options=options)
def test_02_get_auth_item(self): serial = "OATH1" # create realm self.setUp_user_realms() user = User("cornelius", realm=self.realm1) # create ssh token init_token({ "serial": serial, "type": "hotp", "otpkey": OTPKEY }, user=user) # authenticate online initially tok = get_tokens(serial=serial)[0] res = tok.check_otp("359152") # count = 2 self.assertEqual(res, 2) # check intermediate counter value self.assertEqual(tok.token.count, 3) auth_item = OfflineApplication.get_authentication_item("hotp", serial) refilltoken = auth_item.get("refilltoken") self.assertEqual(len(refilltoken), REFILLTOKEN_LENGTH * 2) self.assertTrue(passlib.hash.\ pbkdf2_sha512.verify("969429", # count = 3 auth_item.get("response").get(3))) self.assertTrue(passlib.hash.\ pbkdf2_sha512.verify("399871", # count = 8 auth_item.get("response").get(8))) # The token now contains the refill token information: self.assertEqual(refilltoken, tok.get_tokeninfo("refilltoken")) # After calling auth_item the token counter should be increased # 3, because we used the otp value with count = 2 initially # 100, because we obtained 100 offline OTPs self.assertEqual(tok.token.count, 3 + 100) # Assert that we cannot authenticate with the last offline OTP we got self.assertEqual(len(auth_item.get("response")), 100) self.assertTrue(passlib.hash.\ pbkdf2_sha512.verify("629694", # count = 102 auth_item.get("response").get(102))) res = tok.check_otp("629694") # count = 102 self.assertEqual(res, -1) res = tok.check_otp("378717") # count = 103 self.assertEqual(res, 103) # check illegal API usage self.assertRaises(ParameterError, OfflineApplication.get_offline_otps, tok, 'foo', -1) self.assertEqual(OfflineApplication.get_offline_otps(tok, 'foo', 0), {})
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_05_check_serial_with_no_user(self): # Check a token per serial when the token has no user assigned. init_token({"serial": "nouser", "otpkey": self.otpkey, "pin": "pin"}) with self.app.test_request_context('/validate/check', method='POST', data={ "serial": "nouser", "pass": "******" }): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") details = json.loads(res.data).get("detail") self.assertEqual(result.get("status"), True) self.assertEqual(result.get("value"), True)
def test_03_check_subscription(self): # A valid subscription r = save_subscription(SUBSCRIPTION1) self.assertTrue(r) s = check_subscription("demo_application") self.assertTrue(s) # A subscription, that has expired r = save_subscription(SUBSCRIPTION3) self.assertTrue(r) # The subscription, which has expired 100 days ago raises an exception self.assertRaises(SubscriptionError, check_subscription, "demo_application") self.setUp_user_realms() init_token({"type": "spass"}, user=User("cornelius", self.realm1)) init_token({"type": "spass"}, user=User("cornelius", self.realm1)) init_token({"type": "spass"}, user=User("cornelius", self.realm1)) save_subscription(SUBSCRIPTION4) # We have only one user with tokens, so having a subscription of 3 is fine! s = check_subscription("demo_application") self.assertTrue(s) init_token({"type": "spass"}, user=User("shadow", self.realm1)) init_token({"type": "spass"}, user=User("nopw", self.realm1)) # Now we have three users with tokens, subscription will fail self.assertRaises(SubscriptionError, check_subscription, "demo_application") # try to save some broken subscriptions sub1 = SUBSCRIPTION1.copy() sub1['date_from'] = '1234' with self.assertRaises(ValueError): save_subscription(sub1) sub1 = SUBSCRIPTION1.copy() sub1['by_name'] = 'unknown vendor' with self.assertRaisesRegexp(SubscriptionError, 'Verifying the signature ' 'of your subscription'): save_subscription(sub1) sub1 = SUBSCRIPTION1.copy() sub1['signature'] = str(int(sub1['signature']) + 1) with self.assertRaisesRegexp(SubscriptionError, 'Signature of your ' 'subscription does not'): save_subscription(sub1)
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_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_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="{0!s}=hotp tiqr totp".format(ACTION.CHALLENGERESPONSE)) set_policy(name="pol_chal_resp_2", scope=SCOPE.AUTH, action="{0!s}=hotp motp".format(ACTION.CHALLENGERESPONSE)) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} rv = token.is_challenge_request(pin, user=user, options=options) self.assertEqual(rv, True) delete_policy("pol_chal_resp_1")
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_01_tiqr(self): init_token({"serial": "TIQR1", "type": "tiqr", "user": "******", "realm": self.realm1}) with self.app.test_request_context('/ttype/tiqr', method='POST', data={"action": "metadata", "serial": "TIQR1", "session": "12345"}): res = self.app.full_dispatch_request() data = json.loads(res.data) identity = data.get("identity") service = data.get("service") self.assertEqual(identity.get("displayName"), "Cornelius ") self.assertEqual(service.get("displayName"), "privacyIDEA")
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")
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 g.audit_object = FakeAudit() 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_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_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_10_api_endpoint(self): fixed = "ebedeeefegeheiej" otpkey = "cc17a4d77eaed96e9d14b5c87a02e718" uid = "000000000000" otps = ["ebedeeefegeheiejtjtrutblehenfjljrirgdihrfuetljtt", "ebedeeefegeheiejlekvlrlkrcluvctenlnnjfknrhgtjned", "ebedeeefegeheiejktudedbktcnbuntrhdueikggtrugckij", "ebedeeefegeheiejjvjncbnffdrvjcvrbgdfufjgndfetieu", "ebedeeefegeheiejdruibhvlvktcgfjiruhltketifnitbuk" ] token = init_token({"type": "yubikey", "otpkey": otpkey, "otplen": len(otps[0]), "yubikey.prefix": fixed, "serial": "UBAM12345678_1"}) builder = EnvironBuilder(method='GET', 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) nonce = "random nonce" apiid = "hallo" apikey = "1YMEbMZijD3DzL21UfKGnOOI13c=" set_privacyidea_config("yubikey.apiid.{0!s}".format(apiid), apikey) req.all_data = {'id': apiid, "otp": otps[0], "nonce": nonce} text_type, result = YubikeyTokenClass.api_endpoint(req, g) self.assertEqual(text_type, "plain") self.assertTrue("status=OK" in result, result) self.assertTrue("nonce={0!s}".format(nonce) in result, result)
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" 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_12_auth_items_offline(self): #create HOTP token for offline usage self.setUp_user_realms() token_obj = init_token({"serial": self.serial4, "type": "hotp", "otpkey": OTPKEY, "pin": "test"}, User("cornelius", self.realm1)) self.assertEqual(token_obj.type, "hotp") self.assertEqual(token_obj.token.count, 0) # Attach the token to the machine "gandalf" with the application offline r = attach_token(hostname="gandalf", serial=self.serial4, application="offline", options={"user": "******", "count": 17}) self.assertEqual(r.machine_id, "192.168.0.1") # fetch the auth_items on machine gandalf for application "offline" with self.app.test_request_context( '/machine/authitem/offline?hostname=gandalf', method='GET', headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data).get("result") offline_auth_item = result["value"].get("offline")[0] username = offline_auth_item.get("user") self.assertEqual(username, "cornelius") # check, if we got 17 otp values response = offline_auth_item.get("response") self.assertEqual(len(response), 17) self.assertEqual(token_obj.token.count, 17) self.assertTrue(passlib.hash.\ pbkdf2_sha512.verify("755224", response.get('0'))) self.assertEqual(token_obj.check_otp('187581'), -1) # count = 16 with self.app.test_request_context( '/validate/check?user=cornelius&pass=test447589', # count = 17 environ_base={'REMOTE_ADDR': '192.168.0.1'}, method='GET'): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 200, res) result = json.loads(res.data) self.assertTrue(result['result']['status']) self.assertTrue(result['result']['value']) offline_auth_item = result["auth_items"]["offline"][0] username = offline_auth_item.get("user") self.assertEqual(username, "cornelius") # check, if we got 17 otp values response = offline_auth_item.get("response") self.assertEqual(len(response), 17) self.assertEqual(token_obj.token.count, 35) # 17 + 17 + 1, because we consumed 447589 self.assertTrue(passlib.hash. \ pbkdf2_sha512.verify("test903435", # count = 18 response.get('18'))) self.assertTrue(passlib.hash. \ pbkdf2_sha512.verify("test749439", # count = 34 response.get('34'))) self.assertEqual(token_obj.check_otp('747439'), -1) # count = 34 self.assertEqual(token_obj.check_otp('037211'), 35) # count = 35
def test_13_privacyidea_challenge_response(self): # This tests the challenge response with the privacyIDEA PIN. # First an authentication request with only the local PIN of the # radius token is sent. r = add_radius(identifier="myserver", server="1.2.3.4", secret="testing123", dictionary=DICT_FILE) self.assertTrue(r > 0) token = init_token({"type": "radius", "pin": "local", "radius.identifier": "myserver", "radius.local_checkpin": True, "radius.user": u"nönäscii"}) r = token.is_challenge_request("local") self.assertTrue(r) # create challenge of privacyidea r, message, transaction_id, _attr = token.create_challenge() self.assertTrue(r) self.assertEqual("Enter your RADIUS tokencode:", message) # check, if there is a challenge in the DB chals = get_challenges(token.token.serial) self.assertEqual(len(chals), 1) self.assertEqual(chals[0].transaction_id, transaction_id) # check if this is a response to a previously sent challenge r = token.is_challenge_response("radiuscode", options={"transaction_id": transaction_id}) self.assertTrue(r) # Now check, if the answer for the challenge is correct radiusmock.setdata(response=radiusmock.AccessAccept) r = token.check_challenge_response(passw="radiuscode", options={"transaction_id": transaction_id}) self.assertTrue(r)