def split_pin_otp(token, passw, user=None, options=None): ''' split the pin and the otp fron the given password :param passw: the to be splitted password :param options: currently not used, but might be forwarded to the token.splitPinPass :return: tuple of (split status, pin and otpval) ''' Policy = PolicyClass(request, config, c, get_privacyIDEA_config()) pin_policies = Policy.get_pin_policies(user) policy = 0 if 1 in pin_policies: LOG.debug("pin policy=1: checking the users password as pin") # split the passw into password and otp value (res, pin, otp) = token.splitPinPass(passw) policy = 1 elif 2 in pin_policies: # NO PIN should be entered atall LOG.debug("pin policy=2: checking no pin") (res, pin, otp) = (0, "", passw) policy = 2 else: # old stuff: We check The fixed OTP PIN LOG.debug("pin policy=0: checkin the PIN") (res, pin, otp) = token.splitPinPass(passw) if res != -1: res = policy return (res, pin, otp)
def get_config_documentation(): """ returns an restructured text document, that describes the complete configuration. """ P = PolicyClass() config = get_from_config() resolvers = get_resolver_list() realms = get_realms() policies = P.get_policies() admins = get_db_admins() context = {"system": socket.getfqdn(socket.gethostname()), "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M"), "systemconfig": config, "appconfig": current_app.config, "resolverconfig": resolvers, "realmconfig": realms, "policyconfig": policies, "admins": admins} g.audit_object.log({"success": True}) # Three or more line breaks will be changed to two. return re.sub("\n{3,}", "\n\n", render_template("documentation.rst", context=context))
def test_08_user_policies(self): set_policy(name="pol1", scope="s", user="******") set_policy(name="pol2", scope="s", user="******") set_policy(name="pol3", scope="s", user="******") set_policy(name="pol4", scope="s", user="******") # get policies for user1 P = PolicyClass() p = P.get_policies(user="******") self.assertTrue(len(p) == 3, (len(p), p)) self.assertTrue(_check_policy_name("pol1", p), p) self.assertTrue(_check_policy_name("pol2", p), p) self.assertFalse(_check_policy_name("pol3", p), p) self.assertTrue(_check_policy_name("pol4", p), p) # get policies for root p = P.get_policies(user="******") self.assertTrue(len(p) == 3, p) self.assertTrue(_check_policy_name("pol1", p), p) self.assertTrue(_check_policy_name("pol2", p), p) self.assertTrue(_check_policy_name("pol3", p), p) self.assertFalse(_check_policy_name("pol4", p), p) # get policies for admin p = P.get_policies(user="******") self.assertTrue(len(p) == 4, p) self.assertTrue(_check_policy_name("pol1", p), p) self.assertTrue(_check_policy_name("pol2", p), p) self.assertTrue(_check_policy_name("pol3", p), p) self.assertTrue(_check_policy_name("pol4", p), p)
def test_01_create_simple_policy(self): p = set_policy(name="pol1", action="read", scope="system") self.assertTrue(p > 0) p = set_policy(name="pol2", action="tokentype=HOTP", scope=SCOPE.AUTHZ) self.assertTrue(p > 0) p = set_policy(name="pol3", action="serial=OATH", scope=SCOPE.AUTHZ) self.assertTrue(p > 0) p = set_policy(name="pol4", action="enroll, init, disable , enable", scope="admin") self.assertTrue(p > 0) P = PolicyClass() policies = P.get_policies(name="pol3") # only one policy found self.assertTrue(len(policies) == 1, len(policies)) policies = P.get_policies(scope=SCOPE.AUTHZ) self.assertTrue(len(policies) == 2, len(policies)) policies = P.get_policies(scope=SCOPE.AUTHZ, action="tokentype") self.assertTrue(len(policies) == 1, len(policies)) policies = P.get_policies(scope="admin", action="disable") self.assertTrue(len(policies) == 1, len(policies)) self.assertTrue(policies[0].get("name") == "pol4")
def test_11_import_policy(self): with self.app.test_request_context('/policy/import/policy.cfg', method='POST', data=dict(file=(POLICYFILE, 'policy.cfg')), 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(result["value"] == 2, result) # check if policies are there P = PolicyClass() p1 = P.get_policies(name="importpol1") self.assertTrue(len(p1) == 1, p1) p2 = P.get_policies(name="importpol2") self.assertTrue(len(p2) == 1, p2) # import empty file with self.app.test_request_context("/policy/import/" "policy_empty_file.cfg", method='POST', data=dict(file=(POLICYEMPTY, "policy_empty_file.cfg")), headers={'Authorization': self.at}): res = self.app.full_dispatch_request() self.assertTrue(res.status_code == 400, res)
def test_09_realm_resolver_policy(self): set_policy(name="pol1", scope="s", realm="r1") set_policy(name="pol2", scope="s", realm="r1", resolver="reso1") set_policy(name="pol3", scope="s", realm="", resolver="reso2") set_policy(name="pol4", scope="s", realm="r2", active="true") P = PolicyClass() p = P.get_policies(realm="r1") self.assertTrue(len(p) == 3, p) self.assertTrue(_check_policy_name("pol1", p), p) self.assertTrue(_check_policy_name("pol2", p), p) self.assertTrue(_check_policy_name("pol3", p), p) self.assertFalse(_check_policy_name("pol4", p), p) p = P.get_policies(realm="r2") self.assertTrue(len(p) == 2, p) self.assertFalse(_check_policy_name("pol1", p), p) self.assertFalse(_check_policy_name("pol2", p), p) self.assertTrue(_check_policy_name("pol3", p), p) self.assertTrue(_check_policy_name("pol4", p), p) p = P.get_policies(resolver="reso1") self.assertTrue(len(p) == 3, p) self.assertTrue(_check_policy_name("pol1", p), p) self.assertTrue(_check_policy_name("pol2", p), p) self.assertFalse(_check_policy_name("pol3", p), p) self.assertTrue(_check_policy_name("pol4", p), p) p = P.get_policies(resolver="reso2") self.assertTrue(len(p) == 3, p) self.assertTrue(_check_policy_name("pol1", p), p) self.assertFalse(_check_policy_name("pol2", p), p) self.assertTrue(_check_policy_name("pol3", p), p) self.assertTrue(_check_policy_name("pol4", p), p)
def test_05_export_policies(self): P = PolicyClass() policies = P.get_policies() file = export_policies(policies) self.assertTrue("[pol1]" in file, file) self.assertTrue("[pol2]" in file, file) self.assertTrue("[pol3]" in file, file)
def create_google_authenticator_url(user, realm, key, type="hmac", serial=""): ''' This creates the google authenticator URL. This url may only be 119 characters long. Otherwise we qrcode.js can not create the qrcode. If the URL would be longer, we shorten the username We expect the key to be hexlified! ''' # policy depends on some lib.util if "hmac" == type.lower(): type = "hotp" key_bin = binascii.unhexlify(key) # also strip the padding =, as it will get problems with the google app. otpkey = base64.b32encode(key_bin).strip('=') #'url' : "otpauth://hotp/%s?secret=%s&counter=0" % ( user@realm, otpkey ) base_len = len("otpauth://%s/?secret=%s&counter=0" % (type, otpkey)) max_len = 119 allowed_label_len = max_len - base_len log.debug("we have got %s characters left for the token label" % str(allowed_label_len)) Policy = PolicyClass(request, config, c, get_privacyIDEA_config()) label = Policy.get_tokenlabel(user, realm, serial) label = label[0:allowed_label_len] url_label = quote(label) return "otpauth://%s/%s?secret=%s&counter=0" % (type, url_label, otpkey)
def test_07_client_policies(self): delete_policy(name="pol2a") set_policy(name="pol1", scope="s", client="172.16.0.3, 172.16.0.4/24") set_policy(name="pol2", scope="s", client="192.168.0.0/16, " "-192.168.1.1") set_policy(name="pol3", scope="s", client="10.0.0.1, 10.0.0.2, " "10.0.0.3") set_policy(name="pol4", scope="s") # One policy with matching client, one without any clients P = PolicyClass() p = P.get_policies(client="10.0.0.1") self.assertTrue(_check_policy_name("pol3", p), p) self.assertTrue(_check_policy_name("pol4", p), p) self.assertTrue(len(p) == 2, p) # client matches pol4 and pol2 p = P.get_policies(client="192.168.2.3") self.assertTrue(_check_policy_name("pol2", p), p) self.assertTrue(_check_policy_name("pol4", p), p) self.assertTrue(len(p) == 2, p) # client only matches pol4, since it is excluded in pol2 p = P.get_policies(client="192.168.1.1") self.assertTrue(_check_policy_name("pol4", p), p) self.assertTrue(len(p) == 1, p)
def test_19_ui_get_menus(self): delete_all_policies() luser = {"username": "******", "role": "admin"} # Without policies, the admin gets all P = PolicyClass() menus = P.ui_get_main_menus(luser) self.assertTrue(MAIN_MENU.USERS in menus) self.assertTrue(MAIN_MENU.TOKENS in menus) self.assertTrue(MAIN_MENU.COMPONENTS in menus) self.assertTrue(MAIN_MENU.CONFIG in menus) self.assertTrue(MAIN_MENU.MACHINES in menus) # Admin has only right to enroll HOTP! :-) set_policy("pol1", scope=SCOPE.ADMIN, user="******", action="enrollHOTP") P = PolicyClass() menus = P.ui_get_main_menus(luser) # Thus he can only see the token menu self.assertTrue(MAIN_MENU.USERS not in menus) self.assertTrue(MAIN_MENU.TOKENS in menus) self.assertTrue(MAIN_MENU.COMPONENTS not in menus) self.assertTrue(MAIN_MENU.CONFIG not in menus) self.assertTrue(MAIN_MENU.MACHINES not in menus) set_policy("pol2", scope=SCOPE.ADMIN, user="******", action=ACTION.USERLIST) P = PolicyClass() menus = P.ui_get_main_menus(luser) # Thus he can only see the token menu self.assertTrue(MAIN_MENU.USERS in menus) self.assertTrue(MAIN_MENU.TOKENS in menus) self.assertTrue(MAIN_MENU.COMPONENTS not in menus) self.assertTrue(MAIN_MENU.CONFIG not in menus) self.assertTrue(MAIN_MENU.MACHINES not in menus) set_policy("pol3", scope=SCOPE.ADMIN, user="******", action=ACTION.MACHINELIST) P = PolicyClass() menus = P.ui_get_main_menus(luser) # Thus he can only see the token menu self.assertTrue(MAIN_MENU.USERS in menus) self.assertTrue(MAIN_MENU.TOKENS in menus) self.assertTrue(MAIN_MENU.COMPONENTS not in menus) self.assertTrue(MAIN_MENU.CONFIG not in menus) self.assertTrue(MAIN_MENU.MACHINES in menus) set_policy("pol4", scope=SCOPE.ADMIN, user="******", action=ACTION.SYSTEMDELETE) P = PolicyClass() menus = P.ui_get_main_menus(luser) # Thus he can only see the token menu self.assertTrue(MAIN_MENU.USERS in menus) self.assertTrue(MAIN_MENU.TOKENS in menus) self.assertTrue(MAIN_MENU.COMPONENTS not in menus) self.assertTrue(MAIN_MENU.CONFIG in menus) self.assertTrue(MAIN_MENU.MACHINES in menus) delete_all_policies()
def test_13_get_allowed_serials(self): set_policy(name="st1", scope=SCOPE.AUTHZ, action="serial=OATH") set_policy(name="st2", scope=SCOPE.AUTHZ, action="serial=mOTP ") P = PolicyClass() ttypes = P.get_action_values("serial", scope=SCOPE.AUTHZ) self.assertTrue("OATH" in ttypes) self.assertTrue("mOTP" in ttypes) self.assertFalse("TOTP" in ttypes)
def test_12_get_allowed_tokentypes(self): set_policy(name="tt1", scope=SCOPE.AUTHZ, action="tokentype=hotp " "totp, enroll") set_policy(name="tt2", scope=SCOPE.AUTHZ, action="tokentype=motp") P = PolicyClass() ttypes = P.get_action_values("tokentype", scope=SCOPE.AUTHZ) self.assertTrue("motp" in ttypes) self.assertTrue("totp" in ttypes) self.assertTrue("hotp" in ttypes) self.assertFalse("spass" in ttypes)
def test_16_admin_realm(self): P = PolicyClass() logged_in_user = {"username": "******", "role": "admin", "realm": "realm1"} # Without policies, the admin gets all tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user) self.assertTrue("hotp" in tt) self.assertTrue("totp" in tt) self.assertTrue("motp" in tt) self.assertTrue("sms" in tt) self.assertTrue("spass" in tt) self.assertTrue("sshkey" in tt) self.assertTrue("email" in tt) self.assertTrue("certificate" in tt) self.assertTrue("yubico" in tt) self.assertTrue("yubikey" in tt) self.assertTrue("radius" in tt) # An admin in realm1 may only enroll Yubikeys set_policy(name="tokenEnroll", scope=SCOPE.ADMIN, adminrealm="realm1", action="enrollYUBIKEY") P = PolicyClass() tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user) self.assertFalse("hotp" in tt) self.assertFalse("totp" in tt) self.assertFalse("motp" in tt) self.assertFalse("sms" in tt) self.assertFalse("spass" in tt) self.assertFalse("sshkey" in tt) self.assertFalse("email" in tt) self.assertFalse("certificate" in tt) self.assertFalse("yubico" in tt) self.assertTrue("yubikey" in tt) self.assertFalse("radius" in tt) # An admin in another admin realm may enroll nothing. logged_in_user = {"username": "******", "role": "admin", "realm": "OtherRealm"} tt = P.ui_get_enroll_tokentypes("127.0.0.1", logged_in_user) self.assertFalse("hotp" in tt) self.assertFalse("totp" in tt) self.assertFalse("motp" in tt) self.assertFalse("sms" in tt) self.assertFalse("spass" in tt) self.assertFalse("sshkey" in tt) self.assertFalse("email" in tt) self.assertFalse("certificate" in tt) self.assertFalse("yubico" in tt) self.assertFalse("yubikey" in tt) self.assertFalse("radius" in tt) delete_policy("tokenEnroll")
def authenticate(self, environ, identity): username = None realm = None success = None try: if isSelfTest(): if identity.has_key('login') == False and identity.has_key('repoze.who.plugins.auth_tkt.userid') == True: u = identity.get('repoze.who.plugins.auth_tkt.userid') identity['login'] = u identity['password'] = u if getRealmBox(): username = identity['login'] realm = identity['realm'] else: log.debug("no realmbox, so we are trying to split the loginname") m = re.match("(.*)\@(.*)", identity['login']) if m: if 2 == len(m.groups()): username = m.groups()[0] realm = m.groups()[1] log.debug("found @: username: %r, realm: %r" % (username, realm)) else: username = identity['login'] realm = getDefaultRealm() log.debug("using default Realm: username: %r, realm: %r" % (username, realm)) password = identity['password'] except KeyError as e: log.error("Keyerror in identity: %r." % e) log.error("%s" % traceback.format_exc()) return None # check username/realm, password if isSelfTest(): success = "%s@%s" % (unicode(username), unicode(realm)) else: Policy = PolicyClass(request, config, c, get_privacyIDEA_config()) if Policy.is_auth_selfservice_otp(username, realm): # check the OTP success = authenticate_privacyidea_user(username, realm, password) else: # We do authentication against the user store success = check_user_password(username, realm, password) if not success and is_admin_identity("%s@%s" % (username, realm), exception=False): # user not found or authenticated in resolver. # So let's see, if this is an administrative user. success = check_admin_password(username, password, realm) if success: log.info("User %r authenticated" % success) return success
def list(): """ list the policies """ P = PolicyClass() policies = P.get_policies() print "Active \t Name \t Scope" print 40*"=" for policy in policies: print("%s \t %s \t %s" % (policy.get("active"), policy.get("name"), policy.get("scope")))
def test_22_non_ascii_user(self): set_policy(name="polnonascii", action="enroll, otppin=1", user=u'nönäscii', scope='s') P = PolicyClass() p = P.get_policies(action="enroll", user='******') self.assertEqual(len(p), 0) p = P.get_policies(action="enroll", user=u'nönäscii') self.assertEqual(len(p), 1)
def single_page_application(): instance = request.script_root if instance == "/": instance = "" # The backend URL should come from the configuration of the system. backend_url = "" # The default theme. We can change this later theme = current_app.config.get("PI_CSS", DEFAULT_THEME) # Get further customizations customization = current_app.config.get("PI_CUSTOMIZATION", "/static/customize/") customization = customization.strip('/') # TODO: we should add the CSS into PI_CUSTOMZATION/css # Enrollment-Wizard: # PI_CUSTOMIZATION/views/includes/token.enroll.pre.top.html # PI_CUSTOMIZATION/views/includes/token.enroll.pre.bottom.html # PI_CUSTOMIZATION/views/includes/token.enroll.post.top.html # PI_CUSTOMIZATION/views/includes/token.enroll.post.bottom.html browser_lang = request.accept_languages.best_match(["en", "de"]) # check if login with REMOTE_USER is allowed. remote_user = "" password_reset = False # Depending on displaying the realm dropdown, we fill realms or not. policy_object = PolicyClass() realms = "" client_ip = request.access_route[0] if request.access_route else \ request.remote_addr realm_dropdown = policy_object.get_policies(action=ACTION.REALMDROPDOWN, scope=SCOPE.WEBUI, client=client_ip) if realm_dropdown: realms = ",".join(get_realms().keys()) try: if is_remote_user_allowed(request): remote_user = request.remote_user password_reset = is_password_reset() hsm_ready = True except HSMException: hsm_ready = False return render_template("index.html", instance=instance, backendUrl=backend_url, browser_lang=browser_lang, remote_user=remote_user, theme=theme, password_reset=password_reset, hsm_ready=hsm_ready, customization=customization, realms=realms)
def authenticate(self, environ, identity): username = None realm = None success = None try: if isSelfTest(): if ('login' not in identity and 'repoze.who.plugins.auth_tkt.userid' in identity): u = identity.get('repoze.who.plugins.auth_tkt.userid') identity['login'] = u identity['password'] = u username, realm = self._get_user_from_login(identity['login'], default_realm=False) if getRealmBox() and realm == "": # The login name contained no realm realm = identity['realm'] if realm == "": # The realm is still empty realm = getDefaultRealm() password = identity['password'] except KeyError as e: log.error("Keyerror in identity: %r." % e) log.error("%s" % traceback.format_exc()) return None # check username/realm, password if isSelfTest(): success = "%s@%s" % (unicode(username), unicode(realm)) else: Policy = PolicyClass(request, config, c, get_privacyIDEA_config()) if Policy.is_auth_selfservice_otp(username, realm): # check the OTP success = authenticate_privacyidea_user(username, realm, password) else: # We do authentication against the user store success = check_user_password(username, realm, password) if not success and is_admin_identity("%s@%s" % (username, realm), exception=False): # user not found or authenticated in resolver. # So let's see, if this is an administrative user. success = check_admin_password(username, password, realm) if success: log.info("User %r authenticated" % success) return success
def __before__(self, action, **params): ''' ''' try: c.audit['success'] = False c.audit['client'] = get_client() self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), tokenrealms=request.params.get('serial'), token_type_list=get_token_type_list()) self.set_language() self.before_identity_check(action) Session.commit() return request except webob.exc.HTTPUnauthorized as acc: # the exception, when an abort() is called if forwarded log.info("%r: webob.exception %r" % (action, acc)) log.info(traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: log.error("exception %r" % (action, exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: pass
def __before__(self, action, **params): ''' Here we see, what action is to be called and check the authorization ''' try: c.audit['success'] = False c.audit['client'] = get_client() self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), token_type_list = get_token_type_list()) if action != "check_t": self.before_identity_check(action) return response except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.error("%r webob.exception %r" % (action, acc)) log.error(traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: log.error("%r exception %r" % (action, exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: pass
def autosms(self): ''' This function is used to test the autosms policy method: testing/autosms arguments: user - username / loginname realm - additional realm to match the user to a useridresolver returns: JSON response ''' log.debug('[autosms]') param = request.params try: if isSelfTest() is False: Session.rollback() return sendError(response, "The testing controller can " "only be used in SelfTest mode!", 0) _user = getUserFromParam(param, required) Policy = PolicyClass(request, config, c, get_privacyIDEA_config()) ok = Policy.get_auth_AutoSMSPolicy() Session.commit() return sendResult(response, ok, 0) except Exception as e: log.error("[autosms] validate/check failed: %r", e) log.error("[autosms] %s" % traceback.format_exc()) Session.rollback() return sendError(response, "validate/check failed:" + unicode(e), 0) finally: Session.close() log.debug('[autosms] done')
def test_10_action_policies(self): set_policy(name="pol1", action="enroll, init, disable") set_policy(name="pol2", action="enroll, otppin=1") set_policy(name="pol3", action="*, -disable") set_policy(name="pol4", action="*, -otppin=2") P = PolicyClass() p = P.get_policies(action="enroll") self.assertTrue(len(p) == 4, (len(p), p)) p = P.get_policies(action="init") self.assertTrue(len(p) == 3, (len(p), p)) p = P.get_policies(action="disable") self.assertTrue(len(p) == 2, (len(p), p)) p = P.get_policies(action="otppin") self.assertTrue(len(p) == 2, (len(p), p))
def create_motp_url(user, realm, key, serial=""): ''' This creates the motp url as described at http://huseynov.com/index.php?post=motp-vs-google-authenticator-and-a-new-otp-app The format is: motp://SecureSite:[email protected]?secret=JBSWY3DPEHPK3PXP ''' # For Token2 the OTPKEY is hexencoded, not base32! otpkey = key Policy = PolicyClass(request, config, c, get_privacyIDEA_config()) label = Policy.get_tokenlabel(user, realm, serial) allowed_label_len = 20 label = label[0:allowed_label_len] url_label = quote(label) return "motp://privacyidea:%s?secret=%s" % (url_label, otpkey)
def test_18_policy_with_time(self): set_policy(name="time1", scope=SCOPE.AUTHZ, action="tokentype=hotp totp, enroll", time="Mon-Wed: 0-23:59") tn = datetime.datetime.now() dow = tn.isoweekday() P = PolicyClass() policies = P.get_policies(name="time1", scope=SCOPE.AUTHZ, all_times=True) self.assertEqual(len(policies), 1) policies = P.get_policies(name="time1", scope=SCOPE.AUTHZ) if dow in [1, 2, 3]: self.assertEqual(len(policies), 1) else: self.assertEqual(len(policies), 0) delete_policy("time1")
def check_pin(token, passw, user=None, options=None): ''' check the provided pin w.r.t. the policy definition :param passw: the to be checked pass :param user: if otppin==1, this is the user, which resolver should be checked :param options: the optional request parameters :return: boolean, if pin matched True ''' res = False Policy = PolicyClass(request, config, c, get_privacyIDEA_config()) pin_policies = Policy.get_pin_policies(user) if 1 in pin_policies: # We check the Users Password as PIN LOG.debug("pin policy=1: checking the users" " password as pin") if (user is None): raise Exception("fail for pin policy == 1 with user = None") (uid, _resolver, resolver_class) = getUserId(user) r_obj = getResolverObject(resolver_class) if r_obj.checkPass(uid, passw): LOG.debug("Successfully authenticated user %r." % uid) res = True else: LOG.info("user %r failed to authenticate." % uid) elif 2 in pin_policies: # NO PIN should be entered atall LOG.debug("pin policy=2: checking no pin") if len(passw) == 0: res = True else: # old stuff: We check The fixed OTP PIN LOG.debug("pin policy=0: checkin the PIN") res = token.checkPin(passw, options=options) return res
def test_17_ui_get_rights(self): P = PolicyClass() # Without policies, the admin gets all rights = P.ui_get_rights(SCOPE.ADMIN, "realm1", "admin") self.assertTrue(len(rights) >= 60) # An admin may only enroll Yubikeys set_policy(name="tokenEnroll", scope=SCOPE.ADMIN, action="enrollYUBIKEY") P = PolicyClass() rights = P.ui_get_rights(SCOPE.ADMIN, "realm1", "admin") self.assertEqual(rights, ["enrollYUBIKEY"]) # A user may do something else... set_policy(name="userpol", scope=SCOPE.USER, action="enable") P = PolicyClass() rights = P.ui_get_rights(SCOPE.USER, "realm2", "user") # there was still another policy... self.assertEqual(rights, ["enable", "disable"]) delete_policy("tokenEnroll") delete_policy("userpol") # Two admins: # adminA is allowed to enroll tokens in all realms # adminB is allowed to enroll tokens only in realmB set_policy(name="polAdminA", scope=SCOPE.ADMIN, user="******", action="enrollHOTP, enrollTOTP") set_policy(name="polAdminB", scope=SCOPE.ADMIN, user="******", realm="realmB", action="enrollHOTP") P = PolicyClass() # realm is empty, since in case of an admin, this is the admin realm rights = P.ui_get_rights(SCOPE.ADMIN, realm=None, username="******") self.assertTrue("enrollTOTP" in rights) self.assertTrue("enrollHOTP" in rights) rights = P.ui_get_rights(SCOPE.ADMIN, realm=None, username="******") self.assertTrue("enrollTOTP" not in rights) self.assertTrue("enrollHOTP" in rights) rights = P.ui_get_rights(SCOPE.ADMIN, realm=None, username="******") self.assertEqual(rights, []) delete_policy("polAdminA") delete_policy("polAdminB")
def create_oathtoken_url(user, realm, otpkey, type="hmac", serial=""): #'url' : 'oathtoken:///addToken?name='+serial + # '&key='+otpkey+ # '&timeBased=false&counter=0&numDigites=6&lockdown=true', timebased = "" if "totp" == type.lower(): timebased = "&timeBased=true" Policy = PolicyClass(request, config, c, get_privacyIDEA_config()) label = Policy.get_tokenlabel(user, realm, serial) url_label = quote(label) url = "oathtoken:///addToken?name=%s&lockdown=true&key=%s%s" % ( url_label, otpkey, timebased ) return url
def __init__(self, aToken): HmacTokenClass.__init__(self, aToken) self.setType(u"sms") self.hKeyRequired = False # we support various hashlib methods, but only on create # which is effectively set in the update self.hashlibStr = getFromConfig("hotp.hashlib", "sha1") self.mode = ['challenge'] self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config())
def is_password_reset(): """ Check if password reset is allowed. We need to check, if a user policy with password_reset exists AND if an editable resolver exists. Otherwise password_reset does not make any sense. :return: True or False """ rlist = get_resolver_list(editable=True) log.debug("Number of editable resolvers: %s" % len(rlist)) Policy = PolicyClass() policy_at_all = Policy.get_policies(scope=SCOPE.USER, active=True) log.debug("Policy at all: %s" % policy_at_all) policy_reset_pw = Policy.get_policies(scope=SCOPE.USER, action=ACTION.PASSWORDRESET) log.debug("Password reset policy: %s" % policy_reset_pw) pwreset = (policy_at_all and policy_reset_pw) or not policy_at_all log.debug("Password reset allowed via policy: %s" % pwreset) return bool(rlist and pwreset)
def before_request(): """ This is executed before the request. user_required checks if there is a logged in admin or user The checks for ONLY admin are preformed in api/system.py """ # remove session from param and gather all parameters, either # from the Form data or from JSON in the request body. request.all_data = get_all_params(request.values, request.data) g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) # Already get some typical parameters to log serial = getParam(request.all_data, "serial") realm = getParam(request.all_data, "realm") # log it g.audit_object.log({ "success": False, "serial": serial, "realm": realm, "client": request.remote_addr, "client_user_agent": request.user_agent.browser, "privacyidea_server": request.host, "action": "%s %s" % (request.method, request.url_rule), "action_detail": "", "info": "" }) if g.logged_in_user.get("role") == "user": # A user is calling this API # In case the token API is called by the user and not by the admin we # need to restrict the token view. CurrentUser = get_user_from_param({ "user": g.logged_in_user.get("username"), "realm": g.logged_in_user.get("realm") }) request.all_data["user"] = CurrentUser.login request.all_data["resolver"] = CurrentUser.resolver request.all_data["realm"] = CurrentUser.realm g.audit_object.log({ "user": CurrentUser.login, "realm": CurrentUser.realm }) else: # An administrator is calling this API g.audit_object.log({"administrator": g.logged_in_user.get("username")})
def test_27_get_default_settings(self): params = {} logged_in_user = {"user": "******", "realm": "default", "role": "user"} set_policy("pol1", scope=SCOPE.USER, action="hotp_hashlib=sha256," "hotp_otplen=8") pol = PolicyClass() p = HotpTokenClass.get_default_settings(params, logged_in_user=logged_in_user, policy_object=pol) self.assertEqual(p.get("otplen"), "8") self.assertEqual(p.get("hashlib"), "sha256") delete_policy("pol1")
def __before__(self, action, **params): ''' __before__ is called before every action so we can check the authorization (fixed?) :param action: name of the to be called action :param params: the list of http parameters :return: return response :rtype: pylon response ''' try: c.audit['success'] = False c.audit['client'] = get_client() self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), token_type_list = get_token_type_list()) self.before_identity_check(action) # check authorization if action not in ["_add_dynamic_tokens", 'setupSecurityModule',]: self.Policy.checkPolicyPre('system', action) ## default return for the __before__ and __after__ return response except PolicyException as pex: log.error("%r: policy exception %r" % (action, pex)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, pex, context='before') except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.error("%r: webob.exception %r" % (action, acc)) log.error(traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: log.error("%r: exception %r" % (action, exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: pass
def test_14_fail_unique_policies(self): # create policies with two different texts set_policy(name="email1", scope=SCOPE.AUTH, action="emailtext=text 1") set_policy(name="email2", scope=SCOPE.AUTH, action="emailtext=text 2") # As there are two policies with different action values, # a PolicyError is raised. P = PolicyClass() self.assertRaises(PolicyError, P.get_action_values, action="emailtext", scope=SCOPE.AUTH, unique=True, allow_white_space_in_action=True)
def test_24_challenge_text(self): g = FakeFlaskG() g.client_ip = "10.0.0.1" options = {"g": g, "user": User("cornelius", self.realm1)} set_policy("chaltext", scope=SCOPE.AUTH, action="{0!s}=Wo du wolle?".format(ACTION.CHALLENGETEXT)) g.policy_object = PolicyClass() val = get_action_values_from_options(SCOPE.AUTH, ACTION.CHALLENGETEXT, options) self.assertEqual(val, u"Wo du wolle?") delete_policy("chaltext")
def before_request(): """ This is executed before the request """ ensure_no_config_object() request.all_data = get_all_params(request.values, request.data) privacyidea_server = current_app.config.get("PI_AUDIT_SERVERNAME") or \ request.host g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) g.event_config = EventConfiguration() # access_route contains the ip adresses of all clients, hops and proxies. g.client_ip = get_client_ip(request, get_from_config(SYSCONF.OVERRIDECLIENT)) g.audit_object.log({ "success": False, "client": g.client_ip, "client_user_agent": request.user_agent.browser, "privacyidea_server": privacyidea_server, "action": "{0!s} {1!s}".format(request.method, request.url_rule), "action_detail": "", "info": "" }) username = getParam(request.all_data, "username") if username: # We only fill request.User, if we really have a username. # On endpoints like /auth/rights, this is not available loginname, realm = split_user(username) # overwrite the split realm if we have a realm parameter. Default back to default_realm realm = getParam(request.all_data, "realm", default=realm) or realm or get_default_realm() # Prefill the request.User. This is used by some pre-event handlers try: request.User = User(loginname, realm) except Exception as e: request.User = None log.warning( u"Problem resolving user {0!s} in realm {1!s}: {2!s}.".format( loginname, realm, e)) log.debug(u"{0!s}".format(traceback.format_exc()))
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_20_search_values(self): P = PolicyClass() found, excluded = P._search_value(["v1", "v2"], "v1") self.assertTrue(found) found, excluded = P._search_value(["v1", "v2"], "v3") self.assertFalse(found) found, excluded = P._search_value(["v1", "*"], "v3") self.assertTrue(found) found, excluded = P._search_value(["v1", "-v2"], "v2") self.assertTrue(excluded)
def test_23_priorities_equal_actions(self): # create two policies with the same action values set_policy(name="email1", scope=SCOPE.AUTH, action="emailtext='text 1'", priority=1) set_policy(name="email2", scope=SCOPE.AUTH, action="emailtext='text 1'", priority=1) # this reduces the action values to unique values P = PolicyClass() self.assertEqual(P.get_action_values(scope=SCOPE.AUTH, action="emailtext"), ["text 1"]) # this is allowed if the policies agree self.assertEqual(P.get_action_values(scope=SCOPE.AUTH, action="emailtext", unique=True), ["text 1"]) set_policy(name="email2", action="emailtext='text 2'") P.reload_from_db() with self.assertRaises(PolicyError): P.get_action_values(scope=SCOPE.AUTH, action="emailtext", unique=True) delete_policy("email1") delete_policy("email2")
def before_request(): """ This is executed before the request """ request.all_data = get_all_params(request.values, request.data) # Create a policy_object, that reads the database audit settings # and contains the complete policy definition during the request. # This audit_object can be used in the postpolicy and prepolicy and it # can be passed to the innerpolicies. g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) g.audit_object.log({ "success": False, "action_detail": "", "client": request.remote_addr, "client_user_agent": request.user_agent.browser, "privacyidea_server": request.host, "action": "%s %s" % (request.method, request.url_rule), "info": "" })
def before_request(): """ This is executed before the request """ update_config_object() request.all_data = get_all_params(request.values, request.data) privacyidea_server = current_app.config.get("PI_AUDIT_SERVERNAME") or \ request.host g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) # access_route contains the ip adresses of all clients, hops and proxies. g.client_ip = get_client_ip(request, get_from_config(SYSCONF.OVERRIDECLIENT)) g.audit_object.log({"success": False, "client": g.client_ip, "client_user_agent": request.user_agent.browser, "privacyidea_server": privacyidea_server, "action": "{0!s} {1!s}".format(request.method, request.url_rule), "action_detail": "", "info": ""})
def test_02_userstore_password(self): # create a realm, where cornelius has a password test rid = save_resolver({ "resolver": "myreso", "type": "passwdresolver", "fileName": PWFILE2 }) self.assertTrue(rid > 0, rid) (added, failed) = set_realm("r1", ["myreso"]) self.assertTrue(len(failed) == 0) self.assertTrue(len(added) == 1) # now create a policy with userstore PW set_policy(name="pol1", scope=SCOPE.AUTH, action="{0!s}={1!s}".format(ACTION.OTPPIN, ACTIONVALUE.USERSTORE)) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} # Wrong password r = auth_otppin(self.fake_check_otp, None, "WrongPW", options=options, user=User("cornelius", realm="r1")) self.assertFalse(r) # Correct password from userstore: "test" r = auth_otppin(self.fake_check_otp, None, "test", options=options, user=User("cornelius", realm="r1")) self.assertTrue(r) delete_policy("pol1")
def test_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, attribute = t.create_challenge( options={"g": g}) # 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_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 before_request(): """ This is executed before the request """ ensure_no_config_object() request.all_data = get_all_params(request) request.User = get_user_from_param(request.all_data) privacyidea_server = current_app.config.get("PI_AUDIT_SERVERNAME") or \ request.host # Create a policy_object, that reads the database audit settings # and contains the complete policy definition during the request. # This audit_object can be used in the postpolicy and prepolicy and it # can be passed to the innerpolicies. g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config, g.startdate) g.event_config = EventConfiguration() # access_route contains the ip addresses of all clients, hops and proxies. g.client_ip = get_client_ip(request, get_from_config(SYSCONF.OVERRIDECLIENT)) # Save the HTTP header in the localproxy object g.request_headers = request.headers g.serial = getParam(request.all_data, "serial", default=None) g.audit_object.log({ "success": False, "action_detail": "", "client": g.client_ip, "client_user_agent": request.user_agent.browser, "privacyidea_server": privacyidea_server, "action": "{0!s} {1!s}".format(request.method, request.url_rule), "info": "" })
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_user_does_not_exist(self): user = User("MisterX", realm="NoRealm") passw = "wrongPW" options = {} # A non-existing user will fail to authenticate without a policy self.assertRaises(UserError, auth_user_does_not_exist, check_user_pass, user, passw, options) # Now we set a policy, that a non existing user will authenticate set_policy(name="pol1", scope=SCOPE.AUTH, action=ACTION.PASSNOUSER) g = FakeFlaskG() g.policy_object = PolicyClass() options = {"g": g} rv = auth_user_does_not_exist(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"user does not exist, accepted due " u"to 'pol1'") delete_policy("pol1")
def test_08_encrypt_pin(self): g.logged_in_user = {"username": "******", "role": "admin"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" req = Request(env) # Set a policy that defines the PIN to be encrypted set_policy(name="pol1", scope=SCOPE.ENROLL, action=ACTION.ENCRYPTPIN) g.policy_object = PolicyClass() # request, that matches the policy req.all_data = {"user": "******", "realm": "home"} encrypt_pin(req) # Check, if the tokenlabel was added self.assertEqual(req.all_data.get("encryptpin"), "True") # finally delete policy delete_policy("pol1")
def test_10_auth_lastauth(self): serial = "SPASSLASTAUTH" pin = "secretpin" def fake_auth_missing_serial(user, pin, options=None): return True, {} def fake_auth(user, pin, options): return True, {"serial": serial} user = User("cornelius", realm="r1") init_token({"type": "spass", "pin": pin, "serial": serial}, user=user) # set time limit policy set_policy(name="pol_lastauth", scope=SCOPE.AUTHZ, action="{0!s}=1d".format(ACTION.LASTAUTH)) g = FakeFlaskG() g.policy_object = PolicyClass() g.audit_object = FakeAudit() options = {"g": g} rv = auth_lastauth(fake_auth, user, pin, options) self.assertEqual(rv[0], True) token = get_tokens(serial=serial)[0] # Set a very old last_auth token.add_tokeninfo(ACTION.LASTAUTH, datetime.datetime.utcnow()-datetime.timedelta(days=2)) rv = auth_lastauth(fake_auth, user, pin, options) self.assertEqual(rv[0], False) self.assertTrue("The last successful authentication was" in rv[1].get("message"), rv[1]) remove_token(serial) delete_policy("pol_lastauth")
def test_04a_user_does_not_exist_without_resolver(self): user = User("MisterX", realm=self.realm1) passw = "somePW" # Now we set a policy, that a non existing user will authenticate set_policy(name="pol1", scope=SCOPE.AUTH, action="{0}, {1}, {2}, {3}=none".format( ACTION.RESETALLTOKENS, ACTION.PASSNOUSER, ACTION.PASSNOTOKEN, ACTION.OTPPIN), realm=self.realm1) g = FakeFlaskG() g.policy_object = PolicyClass() options = {"g": g} rv = auth_user_does_not_exist(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"user does not exist, accepted due " u"to 'pol1'") delete_policy("pol1")
def test_03_no_detail_on_success(self): builder = EnvironBuilder(method='POST', data={'serial': "HOTP123435"}, headers={}) env = builder.get_environ() # Set the remote address so that we can filter for it env["REMOTE_ADDR"] = "10.0.0.1" g.client_ip = env["REMOTE_ADDR"] req = Request(env) # The response contains the token type SPASS res = { "jsonrpc": "2.0", "result": { "status": True, "value": True }, "version": "privacyIDEA test", "id": 1, "detail": { "message": "matching 1 tokens", "serial": "HOTP123456", "type": "hotp" } } resp = Response(json.dumps(res)) # Set a policy, that does not allow the detail on success set_policy(name="pol2", scope=SCOPE.AUTHZ, action="no_detail_on_success", client="10.0.0.0/8") g.policy_object = PolicyClass() new_response = no_detail_on_success(req, resp) jresult = json.loads(new_response.data) self.assertTrue("detail" not in jresult, jresult) delete_policy("pol2")
def test_10_check_external(self): g.logged_in_user = {"username": "******", "role": "user"} builder = EnvironBuilder(method='POST', data={'serial': "OATH123456"}, headers={}) env = builder.get_environ() req = Request(env) g.policy_object = PolicyClass() req.all_data = {"user": "******", "realm": "home"} # Check success on no definition r = check_external(req) self.assertTrue(r) # Check success with external function current_app.config["PI_INIT_CHECK_HOOK"] = \ "privacyidea.api.lib.prepolicy.mock_success" r = check_external(req) self.assertTrue(r) # Check exception with external function current_app.config["PI_INIT_CHECK_HOOK"] = \ "privacyidea.api.lib.prepolicy.mock_fail" self.assertRaises(Exception, check_external, req)
def test_05_user_has_no_tokens(self): user = User("cornelius", realm="r1") passw = "test" options = {} # A user with no tokens will fail to authenticate rv = auth_user_has_no_token(check_user_pass, user, passw, options) self.assertFalse(rv[0]) self.assertEqual(rv[1].get("message"), "The user has no tokens assigned") # Now we set a policy, that a non existing user will authenticate set_policy(name="pol1", scope=SCOPE.AUTH, action=ACTION.PASSNOTOKEN) g = FakeFlaskG() g.policy_object = PolicyClass() options = {"g": g} rv = auth_user_has_no_token(check_user_pass, user, passw, options=options) self.assertTrue(rv[0]) self.assertEqual(rv[1].get("message"), u"user has no token, accepted due to " u"'pol1'") delete_policy("pol1")
def before_request(): """ This is executed before the request """ g.config_object = ConfigClass() request.all_data = get_all_params(request.values, request.data) privacyidea_server = current_app.config.get("PI_AUDIT_SERVERNAME") or \ request.host # Create a policy_object, that reads the database audit settings # and contains the complete policy definition during the request. # This audit_object can be used in the postpolicy and prepolicy and it # can be passed to the innerpolicies. g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) # access_route contains the ip adresses of all clients, hops and proxies. g.client_ip = get_client_ip(request, get_from_config(SYSCONF.OVERRIDECLIENT)) g.audit_object.log({"success": False, "action_detail": "", "client": g.client_ip, "client_user_agent": request.user_agent.browser, "privacyidea_server": privacyidea_server, "action": "{0!s} {1!s}".format(request.method, request.url_rule), "info": ""})
def before_request(): """ This is executed before the request. user_required checks if there is a logged in admin or user The checks for ONLY admin are preformed in api/system.py """ # remove session from param and gather all parameters, either # from the Form data or from JSON in the request body. ensure_no_config_object() request.all_data = get_all_params(request.values, request.data) if g.logged_in_user.get("role") == "user": # A user is calling this API. First thing we do is restricting the user parameter. # ...to restrict token view, audit view or token actions. request.all_data["user"] = g.logged_in_user.get("username") request.all_data["realm"] = g.logged_in_user.get("realm") try: request.User = get_user_from_param(request.all_data) # overwrite or set the resolver parameter in case of a logged in user if g.logged_in_user.get("role") == "user": request.all_data["resolver"] = request.User.resolver except AttributeError: # Some endpoints do not need users OR e.g. the setPolicy endpoint # takes a list as the userobject request.User = None except UserError: # In cases like the policy API, the parameter "user" is part of the # policy and will not resolve to a user object request.User = User() g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) g.event_config = EventConfiguration() # access_route contains the ip adresses of all clients, hops and proxies. g.client_ip = get_client_ip(request, get_from_config(SYSCONF.OVERRIDECLIENT)) privacyidea_server = current_app.config.get("PI_AUDIT_SERVERNAME") or \ request.host # Already get some typical parameters to log serial = getParam(request.all_data, "serial") if serial: tokentype = get_token_type(serial) else: tokentype = None if request.User: audit_username = request.User.login audit_realm = request.User.realm audit_resolver = request.User.resolver else: audit_realm = getParam(request.all_data, "realm") audit_resolver = getParam(request.all_data, "resolver") audit_username = getParam(request.all_data, "user") g.audit_object.log({ "success": False, "serial": serial, "user": audit_username, "realm": audit_realm, "resolver": audit_resolver, "token_type": tokentype, "client": g.client_ip, "client_user_agent": request.user_agent.browser, "privacyidea_server": privacyidea_server, "action": "{0!s} {1!s}".format(request.method, request.url_rule), "action_detail": "", "info": "" }) if g.logged_in_user.get("role") == "admin": # An administrator is calling this API g.audit_object.log({"administrator": g.logged_in_user.get("username")})
def test_23_priorities(self): # create three policies with three different texts and different priorities set_policy(name="email1", scope=SCOPE.AUTH, action="emailtext=text 1", priority=4) set_policy(name="email2", scope=SCOPE.AUTH, action="emailtext=text 2", priority=1) set_policy(name="email3", scope=SCOPE.AUTH, action="emailtext=text 3", priority=77) # this chooses email2, because it has the highest priority P = PolicyClass() self.assertEqual( P.get_action_values(action="emailtext", scope=SCOPE.AUTH, unique=True, allow_white_space_in_action=True), ["text 2"]) delete_policy("email2") P.reload_from_db() # with email2 gone, this chooses email1 self.assertEqual( P.get_action_values(action="emailtext", scope=SCOPE.AUTH, unique=True, allow_white_space_in_action=True), ["text 1"]) # if we now add another policy with priority 77, we get no conflict # because email1 is chosen set_policy(name="email4", scope=SCOPE.AUTH, action="emailtext=text 4", priority=77) P.reload_from_db() self.assertEqual( P.get_action_values(action="emailtext", scope=SCOPE.AUTH, unique=True, allow_white_space_in_action=True), ["text 1"]) # but we get a conflict if we change the priority of email4 to 4 set_policy(name="email4", scope=SCOPE.AUTH, action="emailtext=text 4", priority=4) P.reload_from_db() with self.assertRaises(PolicyError) as cm: P.get_action_values(action="emailtext", scope=SCOPE.AUTH, unique=True, allow_white_space_in_action=True) self.assertIn("policies with conflicting actions", str(cm.exception)) pols = P.get_policies(action="emailtext", scope=SCOPE.AUTH) self.assertEqual(len(pols), 3) with self.assertRaises(PolicyError) as cm: P.check_for_conflicts(pols, "emailtext") P.check_for_conflicts([], "emailtext") P.check_for_conflicts([pols[0]], "emailtext") # we can also change the priority set_policy(name="email4", priority=3) P.reload_from_db() self.assertEqual( P.get_action_values(action="emailtext", scope=SCOPE.AUTH, unique=True, allow_white_space_in_action=True), ["text 4"]) # now we have # email1, priority=4 # email3, priority=77 # email4, priority=3 # export, delete all, re-import exported = export_policies(P.get_policies()) self.assertIn("priority = 4", exported) self.assertIn("priority = 77", exported) delete_all_policies() import_policies(exported) pols = P.get_policies(action="emailtext", scope=SCOPE.AUTH) self.assertEqual(len(pols), 3) # this sorts by priority self.assertEqual([p['name'] for p in pols], ['email4', 'email1', 'email3']) # priority must be at least 1 with self.assertRaises(ParameterError): set_policy(name="email4", scope=SCOPE.AUTH, priority=0) with self.assertRaises(ParameterError): set_policy(name="email4", scope=SCOPE.AUTH, priority=-5) delete_policy("email1") delete_policy("email3") delete_policy("email4")
def single_page_application(): instance = request.script_root if instance == "/": instance = "" # The backend URL should come from the configuration of the system. backend_url = "" if current_app.config.get("PI_UI_DEACTIVATED"): # Do not provide the UI return render_template("deactivated.html") # The default theme. We can change this later theme = current_app.config.get("PI_CSS", DEFAULT_THEME) # Get further customizations customization = current_app.config.get("PI_CUSTOMIZATION", "/static/customize/") customization = customization.strip('/') # TODO: we should add the CSS into PI_CUSTOMZATION/css # Enrollment-Wizard: # PI_CUSTOMIZATION/views/includes/token.enroll.pre.top.html # PI_CUSTOMIZATION/views/includes/token.enroll.pre.bottom.html # PI_CUSTOMIZATION/views/includes/token.enroll.post.top.html # PI_CUSTOMIZATION/views/includes/token.enroll.post.bottom.html # Get the hidden external links external_links = current_app.config.get("PI_EXTERNAL_LINKS", True) # Get the logo file logo = current_app.config.get("PI_LOGO", "privacyIDEA1.png") browser_lang = request.accept_languages.best_match( ["en", "de", "de-DE"], default="en").split("-")[0] # The page title can be configured in pi.cfg page_title = current_app.config.get("PI_PAGE_TITLE", "privacyIDEA Authentication System") # check if login with REMOTE_USER is allowed. remote_user = "" password_reset = False if not hasattr(request, "all_data"): request.all_data = {} # Depending on displaying the realm dropdown, we fill realms or not. policy_object = PolicyClass() realms = "" client_ip = get_client_ip(request, get_from_config(SYSCONF.OVERRIDECLIENT)) realm_dropdown = policy_object.get_policies(action=ACTION.REALMDROPDOWN, scope=SCOPE.WEBUI, client=client_ip, active=True) if realm_dropdown: try: realm_dropdown_values = policy_object.get_action_values( action=ACTION.REALMDROPDOWN, scope=SCOPE.WEBUI, client=client_ip) # Use the realms from the policy. realms = ",".join(realm_dropdown_values) except AttributeError as ex: # The policy is still a boolean realm_dropdown action # Thus we display ALL realms realms = ",".join(get_realms()) try: if is_remote_user_allowed(request): remote_user = request.remote_user password_reset = is_password_reset() hsm_ready = True except HSMException: hsm_ready = False # Use policies to determine the customization of menu # and baseline. get_action_values returns an array! sub_state = subscription_status() customization_menu_file = policy_object.get_action_values( allow_white_space_in_action=True, action=ACTION.CUSTOM_MENU, scope=SCOPE.WEBUI, client=client_ip, unique=True) if len(customization_menu_file) and list(customization_menu_file)[0] \ and sub_state not in [1, 2]: customization_menu_file = list(customization_menu_file)[0] else: customization_menu_file = "templates/menu.html" customization_baseline_file = policy_object.get_action_values( allow_white_space_in_action=True, action=ACTION.CUSTOM_BASELINE, scope=SCOPE.WEBUI, client=client_ip, unique=True) if len(customization_baseline_file) and list(customization_baseline_file)[0] \ and sub_state not in [1, 2]: customization_baseline_file = list(customization_baseline_file)[0] else: customization_baseline_file = "templates/baseline.html" login_text = policy_object.get_action_values( allow_white_space_in_action=True, action=ACTION.LOGIN_TEXT, scope=SCOPE.WEBUI, client=client_ip, unique=True) if len(login_text) and list(login_text)[0] and sub_state not in [1, 2]: login_text = list(login_text)[0] else: login_text = "" return render_template( "index.html", instance=instance, backendUrl=backend_url, browser_lang=browser_lang, remote_user=remote_user, theme=theme, password_reset=password_reset, hsm_ready=hsm_ready, has_job_queue=str(has_job_queue()), customization=customization, customization_menu_file=customization_menu_file, customization_baseline_file=customization_baseline_file, realms=realms, external_links=external_links, login_text=login_text, logo=logo, page_title=page_title)
def before_request(): """ This is executed before the request. user_required checks if there is a logged in admin or user The checks for ONLY admin are preformed in api/system.py """ # remove session from param and gather all parameters, either # from the Form data or from JSON in the request body. request.all_data = get_all_params(request.values, request.data) g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) # We can add logic to use X-Forwarded-For g.client_ip = request.remote_addr privacyidea_server = current_app.config.get("PI_AUDIT_SERVERNAME") or \ request.host # Already get some typical parameters to log serial = getParam(request.all_data, "serial") realm = getParam(request.all_data, "realm") user_loginname = "" if "blueprint_token" in request.endpoint: # In case of token endpoint we evaluate the user in the request. # Note: In policy-endpoint "user" is part of the policy configuration # and will cause an exception user = get_user_from_param(request.all_data) user_loginname = user.login realm = user.realm or realm g.audit_object.log({ "success": False, "serial": serial, "user": user_loginname, "realm": realm, "client": g.client_ip, "client_user_agent": request.user_agent.browser, "privacyidea_server": privacyidea_server, "action": "{0!s} {1!s}".format(request.method, request.url_rule), "action_detail": "", "info": "" }) if g.logged_in_user.get("role") == "user": # A user is calling this API # In case the token API is called by the user and not by the admin we # need to restrict the token view. CurrentUser = get_user_from_param({ "user": g.logged_in_user.get("username"), "realm": g.logged_in_user.get("realm") }) request.all_data["user"] = CurrentUser.login request.all_data["resolver"] = CurrentUser.resolver request.all_data["realm"] = CurrentUser.realm g.audit_object.log({ "user": CurrentUser.login, "realm": CurrentUser.realm }) else: # An administrator is calling this API g.audit_object.log({"administrator": g.logged_in_user.get("username")})
def test_19_emailtext(self): # create a EMAILTEXT policy: p = set_policy(name="emailtext", action="{0!s}={1!s}".format(EMAILACTION.EMAILTEXT, "'Your <otp>'"), scope=SCOPE.AUTH) self.assertTrue(p > 0) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} smtpmock.setdata(response={"*****@*****.**": (200, "OK")}) transactionid = "123456098713" db_token = Token.query.filter_by(serial=self.serial1).first() token = EmailTokenClass(db_token) c = token.create_challenge(transactionid, options=options) self.assertTrue(c[0], c) display_message = c[1] self.assertTrue(c[3].get("state"), transactionid) self.assertEqual(display_message, _("Enter the OTP from the Email:")) _n, mimetype = token._get_email_text_or_subject( options, EMAILACTION.EMAILTEXT) self.assertEqual(mimetype, "plain") # Test AUTOEMAIL p = set_policy(name="autoemail", action=EMAILACTION.EMAILAUTO, scope=SCOPE.AUTH) self.assertTrue(p > 0) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} r = token.check_otp("287922", options=options) self.assertTrue(r > 0, r) # create a EMAILTEXT policy with template p = set_policy(name="emailtext", action="{0!s}=file:{1!s}".format( EMAILACTION.EMAILTEXT, TEMPLATE_FILE), scope=SCOPE.AUTH) self.assertTrue(p > 0) g = FakeFlaskG() P = PolicyClass() g.policy_object = P g.audit_object = FakeAudit() options = {"g": g} smtpmock.setdata(response={"*****@*****.**": (200, "OK")}) transactionid = "123456098714" db_token = Token.query.filter_by(serial=self.serial1).first() token = EmailTokenClass(db_token) email_text, mimetype = token._get_email_text_or_subject( options, EMAILACTION.EMAILTEXT) self.assertTrue("<p>Hello,</p>" in email_text) self.assertEqual(mimetype, "html") c = token.create_challenge(transactionid, options=options) self.assertTrue(c[0], c) display_message = c[1] self.assertTrue(c[3].get("state"), transactionid) self.assertEqual(display_message, _("Enter the OTP from the Email:"))