def check_yubikey(self): ''' This function is used to validate the output of a yubikey method: validate/check_yubikey :param pass: The password that consist of the static yubikey prefix and the otp :type pass: string :return: JSON Object returns: JSON response:: { "version": "LinOTP 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": false }, "detail" : { "username": username, "realm": realm }, "id": 0 } ''' param = request.params passw = getParam(param, "pass", required) try: ok = False try: th = TokenHandler() ok, opt = th.checkYubikeyPass(passw) c.audit['success'] = ok except AuthorizeException as exx: log.warning("[check_yubikey] authorization failed for validate/check_yubikey: %r" % exx) c.audit['success'] = False c.audit['info'] = unicode(exx) ok = False Session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("[check_yubikey] validate/check_yubikey failed: %r" % exx) c.audit['info'] = unicode(exx) Session.rollback() return sendError(response, u"validate/check_yubikey failed: %s" % unicode(exx), 0) finally: Session.close() log.debug('[check_yubikey] done')
def webkdc_validate(self): # Called by WebAuth via the Elm remctld scripts. # Verifies a one-time passcode and indicates how long # the token should be considered valid. param = {} try: param.update(request.params) username = param["user"] code = param["code"] user = User(username, "", "") th = TokenHandler() if ('token' in param): serial = param["token"] (ok, opt) = th.checkSerialPass(serial, code, options=None, user=user) else: (ok, opt) = th.checkUserPass(user, code) ret = { "success": ok, } if (ok): ret['expiration'] = round( time.time()) + 60 * 60, # one hour from now else: if opt == None: opt = {} ret['error'] = c.audit.get('info') log.error("[webkdc_validate] authorization failed: %s" % ret['error']) ret['code'] = -310 Session.commit() return sendResult(response, ret, 0, opt=opt) except Exception as exx: log.error("[webkdc_validate] validate/webkdc_validate failed: %r" % exx) log.error("[webkdc_validate] %s" % traceback.format_exc()) Session.rollback() return sendError( response, u"validate/webkdc_validate failed: %s" % unicode(exx), 0) finally: Session.close()
def test_autenroll_wo_pass(self, mocked_policy_src_realm, mocked_policy_autosignment_wo, mockedgetTokens4UserOrSerial, mocked_getTokensOfType, mocked_assignToken, mocked_context ): thdle = TokenHandler() options = {} user = User("Hugo", realm="def_realm") otp = '123467' class Token(object): LinOtpCountWindow = 10 typ = "" def setType(self, type_name): self.typ = type_name def getType(self): return self.typ def getSerial(self): return 'ABCDEFG' aToken = Token() class MockPasswordTokenClass(PasswordTokenClass): def check_otp_exist(self, *args, **kwargs): return 1 pwtoken = MockPasswordTokenClass(aToken) mocked_policy_src_realm.return_value = None mocked_policy_autosignment_wo.return_value = True mockedgetTokens4UserOrSerial.return_value = [] mocked_getTokensOfType.return_value = [pwtoken] mocked_assignToken.return_value = True mocked_context = {'audit': {}} res = thdle.auto_assign_otp_only(otp, user, options) self.assertTrue(res) self.assertTrue(mocked_assignToken.called) return
def test_autenroll_wo_pass( self, mocked_policy_src_realm, mocked_policy_autosignment_wo, mockedgetTokens4UserOrSerial, mocked_getTokensOfType, mocked_assignToken, mocked_context, ): thdle = TokenHandler() options = {} user = User("Hugo", realm="def_realm") otp = "123467" class Token(object): LinOtpCountWindow = 10 typ = "" def setType(self, type_name): self.typ = type_name def getType(self): return self.typ def getSerial(self): return "ABCDEFG" aToken = Token() class MockPasswordTokenClass(PasswordTokenClass): def check_otp_exist(self, *args, **kwargs): return 1 pwtoken = MockPasswordTokenClass(aToken) mocked_policy_src_realm.return_value = None mocked_policy_autosignment_wo.return_value = True mockedgetTokens4UserOrSerial.return_value = [] mocked_getTokensOfType.return_value = [pwtoken] mocked_assignToken.return_value = True g.audit = {} res = thdle.auto_assign_otp_only(otp, user, options) assert res assert mocked_assignToken.called return
def test_isTokenOwner_no_user(self): """ test if no user is given """ serial = "fake_123_token" user = User() th = TokenHandler() with pytest.raises(TokenAdminError) as exx: th.isTokenOwner(serial, user) exx.match('no user found') return
def test_isTokenOwner_no_user(self): """ test if no user is given """ serial = "fake_123_token" user = User() th = TokenHandler() with self.assertRaises(TokenAdminError) as exx: th.isTokenOwner(serial, user) assert 'no user found' in exx.exception.message return
def webkdc_validate(self): # Called by WebAuth via the Elm remctld scripts. # Verifies a one-time passcode and indicates how long # the token should be considered valid. param = {} try: param.update(request.params) username = param["user"] code = param["code"] user = User(username, "", "") th = TokenHandler() if ('token' in param): serial = param["token"] (ok, opt) = th.checkSerialPass(serial, code, options = None, user=user) else: (ok, opt) = th.checkUserPass(user, code) ret = { "success" : ok, } if (ok): ret['expiration'] = round(time.time()) + 60 * 60, # one hour from now else: if opt == None: opt = {} ret['error'] = c.audit.get('info') log.error("[webkdc_validate] authorization failed: %s" % ret['error']) ret['code'] = -310 Session.commit() return sendResult(response, ret, 0, opt=opt) except Exception as exx: log.error("[webkdc_validate] validate/webkdc_validate failed: %r" % exx) log.error("[webkdc_validate] %s" % traceback.format_exc()) Session.rollback() return sendError(response, u"validate/webkdc_validate failed: %s" % unicode(exx), 0) finally: Session.close()
def test_compare_user(self, mocked_getUserId, mocked_getTokens4UserOrSerial): """ test for isTokenOwner the isTokenOwner should only compare the resolver conf and user id """ th = TokenHandler() user = User(login="******", realm="realm", resolver_config_identifier="blah") # ----------------------------------------------------------------- -- # test for same user as uid is the same and the resolver class with # conf is the same, only the resolver description is different mocked_getUserId.return_value = ( "1234", "migrated resolver info", "passwdResolver.conf1", ) mocked_getTokens4UserOrSerial.return_value = [MockedToken()] result = th.isTokenOwner("TokenSerial", user) assert result # ----------------------------------------------------------------- -- # test for different user as uid is the same and the resolver class # with different conf, but same resolver description mocked_getUserId.return_value = ( "1234", "resolver info", "passwdResolver.conf2", ) mocked_getTokens4UserOrSerial.return_value = [MockedToken()] result = th.isTokenOwner("TokenSerial", user) assert not result return
def test_hasOwner_token_and_root_user(self, mocked_getTokens4UserOrSerial): """ test if token hasOwner """ serial = "fake_123_token" mocked_getTokens4UserOrSerial.return_value = [ FakeToken('0', 'res', "resC") ] th = TokenHandler() res = th.hasOwner(serial) assert res == True return
def test_hasOwner_token_and_no_user(self, mocked_getTokens4UserOrSerial): """ test if token hasOwner with user is 0,0,0 """ serial = "fake_123_token" mocked_getTokens4UserOrSerial.return_value = [ FakeToken(None, 'res', 'resC') ] th = TokenHandler() res = th.hasOwner(serial) assert res == False return
def test_isTokenOwner_no_token(self, mocked_getUserId, mocked_getTokens4UserOrSerial): """ test if no token is found """ mocked_getUserId.return_value = ('123', 'res', 'resC') mocked_getTokens4UserOrSerial.return_value = [] serial = "fake_123_token" user = User(login="******") th = TokenHandler() with self.assertRaises(TokenAdminError) as exx: th.isTokenOwner(serial, user) assert 'no token found' in exx.exception.message return
def test_isTokenOwner_no_token(self, mocked_getUserId, mocked_getTokens4UserOrSerial): """ test if no token is found """ mocked_getUserId.return_value = ('123', 'res', 'resC') mocked_getTokens4UserOrSerial.return_value = [] serial = "fake_123_token" user = User(login="******") th = TokenHandler() with pytest.raises(TokenAdminError) as exx: th.isTokenOwner(serial, user) exx.match('no token found') return
def test_compare_user(self, mocked_getUserId, mocked_getTokens4UserOrSerial): """ test for isTokenOwner the isTokenOwner should only compare the resolver conf and user id """ th = TokenHandler() user = User(login='******', realm='realm', resolver_config_identifier='blah') # ----------------------------------------------------------------- -- # test for same user as uid is the same and the resolver class with # conf is the same, only the resolver description is different mocked_getUserId.return_value = ('1234', 'migrated resolver info', 'passwdResolver.conf1') mocked_getTokens4UserOrSerial.return_value = [MockedToken()] result = th.isTokenOwner('TokenSerial', user) self.assertTrue(result) # ----------------------------------------------------------------- -- # test for different user as uid is the same and the resolver class # with different conf, but same resolver description mocked_getUserId.return_value = ('1234', 'resolver info', 'passwdResolver.conf2') mocked_getTokens4UserOrSerial.return_value = [MockedToken()] result = th.isTokenOwner('TokenSerial', user) self.assertFalse(result) return
def test_isTokenOwner_token_and_user(self, mocked_getUserId, mocked_getTokens4UserOrSerial): """ test if token owner is found """ serial = "fake_123_token" user = User(login="******") mocked_getUserId.return_value = ('123', 'res', 'resC') mocked_getTokens4UserOrSerial.return_value = [ FakeToken("123", 'res', "resC") ] th = TokenHandler() res = th.isTokenOwner(serial, user) assert res == True return
def test_hasOwner_token_and_user(self, mocked_getUserId, mocked_getTokens4UserOrSerial): """ test if token hasOwner """ serial = "fake_123_token" user = User(login="******") mocked_getUserId.return_value = ("123", "res", "resC") mocked_getTokens4UserOrSerial.return_value = [ FakeToken("123", "res", "resC") ] th = TokenHandler() res = th.hasOwner(serial) assert res return
def test_losttoken(self, mocked_getTokenOwner, mocked__get_policies, mocked_get_policy_definitions): """Verify the policy evaluation in losttoken honores general actions.""" fake_user = LinotpUser(login='******', realm='defaultrealm') mocked_getTokenOwner.return_value = fake_user policy_set = copy.deepcopy(PolicySet) mocked_get_policy_definitions.return_value = { 'enrollment': { 'lostTokenPWLen': { 'type': 'int', 'desc': 'The length of the password in case of ' 'temporary token.' }, 'lostTokenPWContents': { 'type': 'str', 'desc': 'The contents of the temporary password, ' 'described by the characters C, c, n, s.' }, 'lostTokenValid': { 'type': 'set', 'value': ['int', 'duration'], 'desc': 'The length of the validity for the temporary ' 'token as days or duration with "d"-days, "h"-hours,' ' "m"-minutes, "s"-seconds.' }, } } # ----------------------------------------------------------------- -- # verify that general policy is honored policy_set['general']['action'] = ( 'lostTokenPWLen=5, lostTokenPWContents=n, lostTokenValid=2') mocked__get_policies.return_value = policy_set end_date = (datetime.date.today() + datetime.timedelta(days=2)).strftime("%d/%m/%y") end_date = "%s 23:59" % end_date th = TokenHandler() res = th.losttoken('mySerial', 'mySerial_new') assert res['password'].isdigit() assert len(res['password']) == 5 assert res['end_date'] == end_date # ----------------------------------------------------------------- -- # verify that user specific policy is honored policy_set['fake_user']['action'] = ( 'lostTokenPWLen=3, lostTokenPWContents=c, lostTokenValid=1') mocked__get_policies.return_value = policy_set end_date = (datetime.date.today() + datetime.timedelta(days=1)).strftime("%d/%m/%y") end_date = "%s 23:59" % end_date th = TokenHandler() res = th.losttoken(serial='mySerial', new_serial='mySerial_new') assert not res['password'].isdigit() assert len(res['password']) == 3 assert res['end_date'] == end_date
def test_losttoken( self, mocked_getTokenOwner, mocked__get_policies, mocked_get_policy_definitions, ): """Verify the policy evaluation in losttoken honores general actions.""" fake_user = LinotpUser(login="******", realm="defaultrealm") mocked_getTokenOwner.return_value = fake_user policy_set = copy.deepcopy(PolicySet) mocked_get_policy_definitions.return_value = { "enrollment": { "lostTokenPWLen": { "type": "int", "desc": "The length of the password in case of " "temporary token.", }, "lostTokenPWContents": { "type": "str", "desc": "The contents of the temporary password, " "described by the characters C, c, n, s.", }, "lostTokenValid": { "type": "set", "value": ["int", "duration"], "desc": "The length of the validity for the temporary " 'token as days or duration with "d"-days, "h"-hours,' ' "m"-minutes, "s"-seconds.', }, } } # ----------------------------------------------------------------- -- # verify that general policy is honored policy_set["general"][ "action"] = "lostTokenPWLen=5, lostTokenPWContents=n, lostTokenValid=2" mocked__get_policies.return_value = policy_set end_date = (datetime.date.today() + datetime.timedelta(days=2)).strftime("%d/%m/%y") end_date = "%s 23:59" % end_date th = TokenHandler() res = th.losttoken("mySerial", "mySerial_new") assert res["password"].isdigit() assert len(res["password"]) == 5 assert res["end_date"] == end_date # ----------------------------------------------------------------- -- # verify that user specific policy is honored policy_set["fake_user"][ "action"] = "lostTokenPWLen=3, lostTokenPWContents=c, lostTokenValid=1" mocked__get_policies.return_value = policy_set end_date = (datetime.date.today() + datetime.timedelta(days=1)).strftime("%d/%m/%y") end_date = "%s 23:59" % end_date th = TokenHandler() res = th.losttoken(serial="mySerial", new_serial="mySerial_new") assert not res["password"].isdigit() assert len(res["password"]) == 3 assert res["end_date"] == end_date
def checkUserPass(self, user, passw, options=None): """ :param user: the to be identified user :param passw: the identifiaction pass :param options: optional parameters, which are provided to the token checkOTP / checkPass :return: tuple of True/False and optional information """ log.debug('entering function checkUserPass(%r)' % user.login) # the upper layer will catch / at least should ;-) opt = None serial = None resolverClass = None uid = None audit = context['audit'] user_exists = False if user is not None and (user.isEmpty() is False): # the upper layer will catch / at least should try: (uid, _resolver, resolverClass) = getUserId(user) user_exists = True except: pass_on = context.get('Config').get( 'linotp.PassOnUserNotFound', False) if pass_on and 'true' == pass_on.lower(): audit['action_detail'] = ( 'authenticated by PassOnUserNotFound') return (True, opt) else: audit['action_detail'] = 'User not found' return (False, opt) # if we have an user, check if we forward the request to another server if user_exists: servers = get_auth_forward(user) if servers: res, opt = ForwardServerPolicy.do_request( servers, env, user, passw, options) return res, opt tokenList = linotp.lib.token.getTokens4UserOrSerial(user, serial) if len(tokenList) == 0: audit['action_detail'] = 'User has no tokens assigned' # here we check if we should to autoassign and try to do it log.debug('about to check auto_assigning') th = TokenHandler() auto_assign_return = th.auto_assignToken(passw, user) if auto_assign_return is True: # We can not check the token, as the OTP value is already used! # but we will auth the user.... return (True, opt) auto_enroll_return, opt = th.auto_enrollToken(passw, user, options=options) if auto_enroll_return is True: # we always have to return a false, as # we have a challenge tiggered return (False, opt) pass_on = context.get('Config').get('linotp.PassOnUserNoToken', False) if pass_on and 'true' == pass_on.lower(): audit['action_detail'] = 'authenticated by PassOnUserNoToken' return (True, opt) # Check if there is an authentication policy passthru from linotp.lib.policy import get_auth_passthru if get_auth_passthru(user): log.debug('user %r has no token. Checking for ' 'passthru in realm %r' % (user.login, user.realm)) y = getResolverObject(resolverClass) audit['action_detail'] = 'Authenticated against Resolver' if y.checkPass(uid, passw): return (True, opt) # Check if there is an authentication policy passOnNoToken from linotp.lib.policy import get_auth_passOnNoToken if get_auth_passOnNoToken(user): log.info('user %r has not token. PassOnNoToken' ' set - authenticated!') audit['action_detail'] = ( 'Authenticated by passOnNoToken policy') return (True, opt) return (False, opt) if passw is None: raise ParameterError(u"Missing parameter:pass", id=905) (res, opt) = self.checkTokenList(tokenList, passw, user, options=options) log.debug('return of __checkTokenList: %r ' % (res, )) return (res, opt)
def checkUserPass(self, user, passw, options=None): """ :param user: the to be identified user :param passw: the identification pass :param options: optional parameters, which are provided to the token checkOTP / checkPass :return: tuple of True/False and optional information """ # the upper layer will catch / at least should ;-) opt = None serial = None resolverClass = None uid = None user_exists = False if user: # the upper layer will catch / at least should try: (uid, _resolver, resolverClass) = getUserId(user, check_existance=True) user_exists = True except Exception as _exx: pass_on = context.get("Config").get( "linotp.PassOnUserNotFound", False) if pass_on and pass_on.lower() == "true": g.audit[ "action_detail"] = "authenticated by PassOnUserNotFound" return (True, opt) else: g.audit["action_detail"] = "User not found" return (False, opt) # if we have an user, check if we forward the request to another server if user_exists and not get_auth_forward_on_no_token(user): servers = get_auth_forward(user) if servers: log.info("forwarding auth request for user {} to {}".format( user, servers)) res, opt = ForwardServerPolicy.do_request( servers, env, user, passw, options) log.info("result of auth request for user {}: ({}, {})".format( user, res, opt)) g.audit["action_detail"] = "Forwarded, result {}".format(res) return res, opt else: log.info( "NOT forwarding auth request for user {} (no servers)". format(user)) g.audit["action_detail"] = "Not forwarded (no servers)" else: log.info( "NOT forwarding auth request for user {} " "(get_auth_forward_on_no_token returned False)".format(user)) # ------------------------------------------------------------------ -- th = TokenHandler() # ------------------------------------------------------------------ -- # auto asignement with otp only if user has no active token auto_assign_otp_return = th.auto_assign_otp_only(otp=passw, user=user, options=options) if auto_assign_otp_return: return (True, None) # ------------------------------------------------------------------ -- token_type = None if options: token_type = options.get("token_type", None) # ------------------------------------------------------------------ -- # if there is a serial provided in the parameters, it overwrites the # token selection by user query_user = user if options and "serial" in options and options["serial"]: serial = options["serial"] query_user = None # ------------------------------------------------------------------ -- tokenList = getTokens4UserOrSerial(query_user, serial, token_type=token_type, read_for_update=True) if len(tokenList) == 0: g.audit["action_detail"] = "User has no tokens assigned" # here we check if we should to autoassign and try to do it auto_assign_return = th.auto_assignToken(passw, user) if auto_assign_return: # We can not check the token, as the OTP value is already used! # but we will auth the user.... return (True, opt) auto_enroll_return, opt = th.auto_enrollToken(passw, user, options=options) if auto_enroll_return: # we always have to return a false, as # we have a challenge tiggered return (False, opt) pass_on = context.get("Config").get("linotp.PassOnUserNoToken", False) if pass_on and pass_on.lower() == "true": g.audit["action_detail"] = "authenticated by PassOnUserNoToken" return (True, opt) # Check if there is an authentication policy passthru if get_auth_passthru(user): log.debug( "user %r has no token. Checking for passthru in realm %r", user.login, user.realm, ) y = getResolverObject(resolverClass) g.audit["action_detail"] = "Authenticated against Resolver" if y.checkPass(uid, passw): return (True, opt) # Check alternatively if there is an authentication # policy passOnNoToken elif get_auth_passOnNoToken(user): log.info("user %r has not token. PassOnNoToken" " set - authenticated!") g.audit[ "action_detail"] = "Authenticated by passOnNoToken policy" return (True, opt) # if we have an user, check if we forward the request to another # server elif get_auth_forward_on_no_token(user): servers = get_auth_forward(user) if servers: log.info( "forwarding auth request for user {} to {}".format( user, servers)) res, opt = ForwardServerPolicy.do_request( servers, env, user, passw, options) log.info( "result of auth request for user {}: ({}, {})".format( user, res, opt)) g.audit["action_detail"] = "Forwarded, result {}".format( res) return res, opt else: log.info( "NOT forwarding auth request for user {} (no servers)". format(user)) g.audit["action_detail"] = "Not forwarded (no servers)" return False, opt if passw is None: raise ParameterError("Missing parameter:pass", id=905) (res, opt) = self.checkTokenList(tokenList, passw, user, options=options) return (res, opt)
def check(self): ''' This function is used to login method: openid/check arguments: user - user to login realm - in which realm the user should login pass - password returns: JSON response ''' ok = False param = {} do_redirect = None message = None try: param.update(request.params) same_user = True passw = getParam(param, "pass", optional) ## getUserFromParam will return default realm if no realm is ## provided via @ append or extra parameter realm ## if the provided realm does not exist, the realm is left empty user = getUserFromParam(param, optional) ## if the requested user has a realm specified (via @realm append) ## and this is not the same as the user from getUserFromParam ## the requested user is not a valid one! p_user = param.get('user', '') if "@" in p_user: if p_user != "%s@%s" % (user.login, user.realm): same_user = False c.audit['user'] = user.login c.audit['realm'] = user.realm or getDefaultRealm() th = TokenHandler() if same_user is True: (ok, opt) = th.checkUserPass(user, passw) c.audit['success'] = ok if ok: ## if the user authenticated successfully we need to set the cookie aka ## the ticket and we need to remember this ticket. user = "******" % (user.login, c.audit['realm']) log.debug("[check] user=%s" % user) token = self.storage.set_user_token(user, expire=self.COOKIE_EXPIRE) log.debug("[check] token=%s" % token) cookie = "%s:%s" % (user, token) log.debug("[check] cookie=%s" % cookie) response.set_cookie(COOKIE_NAME, cookie, max_age=self.COOKIE_EXPIRE) else: message = "Your login attempt was not successful!" Session.commit() # Only if we logged in successfully we redirect to the original # page (Servive Provider). Otherwise we will redirect to the # status page p = {} redirect_to = getParam(param, "redirect_to", optional) if redirect_to and ok: p = {} for k in [ 'openid.return_to', "openid.realm", "openid.ns", "openid.claimed_id", "openid.mode", "openid.identity" ]: p[k] = param[k] else: if message is not None: p["message"] = message redirect_to = "/openid/status" do_redirect = url(str("%s?%s" % (redirect_to, urlencode(p)))) except Exception as exx: log.exception("[check] openid/check failed: %r" % exx) Session.rollback() return sendError(response, "openid/check failed: %r" % exx, 0) finally: Session.close() log.debug('[check] done') if do_redirect: log.debug("[check] now redirecting to %s" % do_redirect) redirect(do_redirect)
def _check(self, param): ''' basic check function, that can be used by different controllers :param param: dict of all caller parameters :type param: dict :return: Tuple of True or False and opt :rtype: Tuple(boolean, opt) ''' opt = None options = {} ## put everythin in the options but the user, pass, init options.update(param) for para in ["pass", "user", "init"]: if options.has_key(para): del options[para] passw = getParam(param, "pass", optional) user = getUserFromParam(param, optional) # support for ocra application challenge verification challenge = getParam(param, "challenge", optional) if challenge is not None: options = {} options['challenge'] = challenge c.audit['user'] = user.login realm = user.realm or getDefaultRealm() c.audit['realm'] = realm # AUTHORIZATION Pre Check # we need to overwrite the user.realm in case the user does not exist in the original realm (setrealm-policy) user.realm = set_realm(user.login, realm, exception=True) check_user_authorization(user.login, user.realm, exception=True) if isSelfTest() == True: initTime = getParam(param, "init", optional) if initTime is not None: if options is None: options = {} options['initTime'] = initTime th = TokenHandler() (ok, opt) = th.checkUserPass(user, passw, options=options) c.audit['success'] = ok if ok: # AUTHORIZATION post check check_auth_tokentype(c.audit['serial'], exception=True, user=user) check_auth_serial(c.audit['serial'], exception=True, user=user) # add additional details if is_auth_return(ok, user=user): if opt == None: opt = {} if ok: opt['realm'] = c.audit.get('realm') opt['user'] = c.audit.get('user') opt['tokentype'] = c.audit.get('token_type') opt['serial'] = c.audit.get('serial') else: opt['error'] = c.audit.get('action_detail') return (ok, opt)
def _check(self, param): ''' basic check function, that can be used by different controllers :param param: dict of all caller parameters :type param: dict :return: Tuple of True or False and opt :rtype: Tuple(boolean, opt) ''' log.debug("[_check] entering function") opt = None options = {} ## put everything in the options but the user, pass, init options.update(param) for para in ["pass", "user", "init"]: if options.has_key(para): del options[para] passw = getParam(param, "pass", optional) user = getUserFromParam(param, optional) # support for ocra application challenge verification challenge = getParam(param, "challenge", optional) if challenge is not None: options = {} options['challenge'] = challenge c.audit['user'] = user.login realm = user.realm or getDefaultRealm() c.audit['realm'] = realm # AUTHORIZATION Pre Check # we need to overwrite the user.realm in case the user does not exist in the original realm (setrealm-policy) user.realm = set_realm(user.login, realm, exception=True) check_user_authorization(user.login, user.realm, exception=True) if isSelfTest() == True: initTime = getParam(param, "init", optional) if initTime is not None: if options is None: options = {} options['initTime'] = initTime th = TokenHandler() log.debug("[_check] calling th.checkUserPass") (ok, opt) = th.checkUserPass(user, passw, options=options) c.audit['success'] = ok if ok: # AUTHORIZATION post check check_auth_tokentype(c.audit['serial'], exception=True, user=user) check_auth_serial(c.audit['serial'], exception=True, user=user) # add additional details if is_auth_return(ok, user=user): if opt == None: opt = {} if ok: opt['realm'] = c.audit.get('realm') opt['user'] = c.audit.get('user') opt['tokentype'] = c.audit.get('token_type') opt['serial'] = c.audit.get('serial') else: opt['error'] = c.audit.get('action_detail') log.debug("[_check] exiting function") return (ok, opt)
def checkUserPass(self, user, passw, options=None): """ :param user: the to be identified user :param passw: the identifiaction pass :param options: optional parameters, which are provided to the token checkOTP / checkPass :return: tuple of True/False and optional information """ log.debug('entering function checkUserPass(%r)' % user.login) # the upper layer will catch / at least should ;-) opt = None serial = None resolverClass = None uid = None audit = context['audit'] user_exists = False if user is not None and (user.isEmpty() == False): # the upper layer will catch / at least should try: (uid, _resolver, resolverClass) = getUserId(user) user_exists = True except: pass_on = context.get('Config').get( 'linotp.PassOnUserNotFound', False) if pass_on and 'true' == pass_on.lower(): audit['action_detail'] = ( 'authenticated by PassOnUserNotFound') return (True, opt) else: audit['action_detail'] = 'User not found' return (False, opt) # if we have an user, check if we forward the request to another server if user_exists: from linotp.lib.policy import get_auth_forward servers = get_auth_forward(user) if servers: if 'radius://' in servers: rad = RadiusRequest(servers=servers) res, opt = rad.do_request(servers, user, passw, options) return res, opt elif 'http://' in servers or 'https://' in servers: http = HttpRequest(servers=servers) res, opt = http.do_request(user, passw, options) return res, opt tokenList = linotp.lib.token.getTokens4UserOrSerial(user, serial) if len(tokenList) == 0: audit['action_detail'] = 'User has no tokens assigned' # here we check if we should to autoassign and try to do it log.debug('about to check auto_assigning') th = TokenHandler() auto_assign_return = th.auto_assignToken(passw, user) if auto_assign_return is True: # We can not check the token, as the OTP value is already used! # but we will auth the user.... return (True, opt) auto_enroll_return, opt = th.auto_enrollToken(passw, user, options=options) if auto_enroll_return is True: # we always have to return a false, as # we have a challenge tiggered return (False, opt) pass_on = context.get('Config').get('linotp.PassOnUserNoToken', False) if pass_on and 'true' == pass_on.lower(): audit['action_detail'] = 'authenticated by PassOnUserNoToken' return (True, opt) # Check if there is an authentication policy passthru from linotp.lib.policy import get_auth_passthru if get_auth_passthru(user): log.debug('user %r has no token. Checking for ' 'passthru in realm %r' % (user.login, user.realm)) y = getResolverObject(resolverClass) audit['action_detail'] = 'Authenticated against Resolver' if y.checkPass(uid, passw): return (True, opt) # Check if there is an authentication policy passOnNoToken from linotp.lib.policy import get_auth_passOnNoToken if get_auth_passOnNoToken(user): log.info('user %r has not token. PassOnNoToken' ' set - authenticated!') audit['action_detail'] = ( 'Authenticated by passOnNoToken policy') return (True, opt) return (False, opt) if passw is None: raise ParameterError(u"Missing parameter:pass", id=905) (res, opt) = self.checkTokenList( tokenList, passw, user, options=options) log.debug('return of __checkTokenList: %r ' % (res,)) return (res, opt)
def check_yubikey(self): ''' This function is used to validate the output of a yubikey method: validate/check_yubikey :param pass: The password that consist of the static yubikey prefix and the otp :type pass: string :return: JSON Object returns: JSON response:: { "version": "LinOTP 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": false }, "detail" : { "username": username, "realm": realm }, "id": 0 } ''' param = request.params passw = getParam(param, "pass", required) try: ok = False try: th = TokenHandler() ok, opt = th.checkYubikeyPass(passw) c.audit['success'] = ok except AuthorizeException as exx: log.warning( "[check_yubikey] authorization failed for validate/check_yubikey: %r" % exx) c.audit['success'] = False c.audit['info'] = unicode(exx) ok = False Session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.error("[check_yubikey] validate/check_yubikey failed: %r" % exx) log.error("[check_yubikey] %s" % traceback.format_exc()) c.audit['info'] = unicode(exx) Session.rollback() return sendError( response, u"validate/check_yubikey failed: %s" % unicode(exx), 0) finally: Session.close() log.debug('[check_yubikey] done')
def enroll(self): """ method: api/helpdesk/enroll description: method to enroll a token as helpdesk arguments: * type: the token type, currently only 'email' * user: the new token owner * realm: (optional) the realm the user belongs to - used to identify the user returns: success as boolean """ ret = False response_detail = {} params = self.request_params try: if 'user' not in params: raise ParameterError('missing parameter: user!') if 'type' not in params: raise ParameterError('missing parameter: type!') # --------------------------------------------------------------- -- # determine token class token_cls_alias = params.get("type") lower_alias = token_cls_alias.lower() if lower_alias not in tokenclass_registry: raise TokenAdminError('admin/init failed: unknown token ' 'type %r' % token_cls_alias, id=1610) token_cls = tokenclass_registry.get(lower_alias) # --------------------------------------------------------------- -- # call the token class hook in order to enrich/overwrite the # parameters helper_params = token_cls.get_helper_params_pre(params) params.update(helper_params) # --------------------------------------------------------------- -- # fetch user from parameters. user = getUserFromParam(params) # --------------------------------------------------------------- -- # create a new pin according to the policies if 'pin' not in params: params['pin'] = createRandomPin(user, min_pin_length=6) # --------------------------------------------------------------- -- if 'otpkey' not in params: params['genkey'] = '1' # --------------------------------------------------------------- -- # check admin authorization res = checkPolicyPre('admin', 'init', params, user=user) # --------------------------------------------------------------- -- helper_params = token_cls.get_helper_params_post(params, user=user) params.update(helper_params) # --------------------------------------------------------------- -- # create new serial th = TokenHandler() serial = th.genSerial(token_cls_alias) params['serial'] = serial log.info("[init] initialize token. user: %s, serial: %s" % (user.login, serial)) # --------------------------------------------------------------- -- # scope_extension: we are in scope helpdesk # this is eg required to notify the emailtoken to use the # email from user if none is given as param params['::scope::'] = { 'helpdesk': True, 'user': user } (ret, token) = th.initToken(params, user) # --------------------------------------------------------------- -- # different token types return different information on # initialization (e.g. otpkey, pairing_url, etc) initDetail = token.getInitDetail(params, user) response_detail.update(initDetail) # --------------------------------------------------------------- -- # prepare data for audit if token is not None and ret is True: c.audit['serial'] = token.getSerial() c.audit['token_type'] = token.type c.audit['success'] = ret c.audit['user'] = user.login c.audit['realm'] = user.realm c.audit['action_detail'] += get_token_num_info() res = checkPolicyPost('admin', 'init', params, user=user) pin = res.get('new_pin', params['pin']) message = ("A new ${tokentype} token (${serial}) " "with pin '${Pin}' " "for ${givenname} ${surname} has been enrolled.") info = { 'message': message, 'Subject': 'New %s token enrolled' % token.type, 'Pin': pin, 'tokentype': token.type } info.update(response_detail) notify_user(user, 'enrollment', info, required=True) c.audit['action_detail'] += get_token_num_info() c.audit['success'] = ret return sendResult(response, ret) except PolicyException as pex: log.exception("Policy Exception while enrolling token") Session.rollback() return sendError(response, pex, 1) except Exception as exx: log.exception("Exception while enrolling token") Session.rollback() return sendError(response, exx, 1)
def checkUserPass(self, user, passw, options=None): """ :param user: the to be identified user :param passw: the identification pass :param options: optional parameters, which are provided to the token checkOTP / checkPass :return: tuple of True/False and optional information """ # the upper layer will catch / at least should ;-) opt = None serial = None resolverClass = None uid = None user_exists = False if user is not None and not user.is_empty: # the upper layer will catch / at least should try: (uid, _resolver, resolverClass) = getUserId( user, check_existance=True) user_exists = True except Exception as _exx: pass_on = context.get('Config').get( 'linotp.PassOnUserNotFound', False) if pass_on and 'true' == pass_on.lower(): g.audit['action_detail'] = ( 'authenticated by PassOnUserNotFound') return (True, opt) else: g.audit['action_detail'] = 'User not found' return (False, opt) # if we have an user, check if we forward the request to another server if user_exists and get_auth_forward_on_no_token(user) is False: servers = get_auth_forward(user) if servers: res, opt = ForwardServerPolicy.do_request(servers, env, user, passw, options) return res, opt # ------------------------------------------------------------------ -- th = TokenHandler() # ------------------------------------------------------------------ -- # auto asignement with otp only if user has no active token auto_assign_otp_return = th.auto_assign_otp_only( otp=passw, user=user, options=options) if auto_assign_otp_return is True: return (True, None) # ------------------------------------------------------------------ -- token_type = None if options: token_type = options.get('token_type', None) # ------------------------------------------------------------------ -- # if there is a serial provided in the parameters, it overwrites the # token selection by user query_user = user if options and 'serial' in options and options['serial']: serial = options['serial'] query_user = None # ------------------------------------------------------------------ -- tokenList = getTokens4UserOrSerial( query_user, serial, token_type=token_type, read_for_update=True ) if len(tokenList) == 0: g.audit['action_detail'] = 'User has no tokens assigned' # here we check if we should to autoassign and try to do it auto_assign_return = th.auto_assignToken(passw, user) if auto_assign_return is True: # We can not check the token, as the OTP value is already used! # but we will auth the user.... return (True, opt) auto_enroll_return, opt = th.auto_enrollToken(passw, user, options=options) if auto_enroll_return is True: # we always have to return a false, as # we have a challenge tiggered return (False, opt) pass_on = context.get('Config').get('linotp.PassOnUserNoToken', False) if pass_on and 'true' == pass_on.lower(): g.audit['action_detail'] = 'authenticated by PassOnUserNoToken' return (True, opt) # Check if there is an authentication policy passthru if get_auth_passthru(user): log.debug('user %r has no token. Checking for ' 'passthru in realm %r' % (user.login, user.realm)) y = getResolverObject(resolverClass) g.audit['action_detail'] = 'Authenticated against Resolver' if y.checkPass(uid, passw): return (True, opt) # Check alternatively if there is an authentication # policy passOnNoToken elif get_auth_passOnNoToken(user): log.info('user %r has not token. PassOnNoToken' ' set - authenticated!') g.audit['action_detail'] = ( 'Authenticated by passOnNoToken policy') return (True, opt) # if we have an user, check if we forward the request to another server elif get_auth_forward_on_no_token(user) is True: servers = get_auth_forward(user) if servers: res, opt = ForwardServerPolicy.do_request( servers, env, user, passw, options) return res, opt return False, opt if passw is None: raise ParameterError("Missing parameter:pass", id=905) (res, opt) = self.checkTokenList( tokenList, passw, user, options=options) return (res, opt)
def checkUserPass(self, user, passw, options=None): """ :param user: the to be identified user :param passw: the identification pass :param options: optional parameters, which are provided to the token checkOTP / checkPass :return: tuple of True/False and optional information """ # the upper layer will catch / at least should ;-) opt = None serial = None resolverClass = None uid = None audit = context['audit'] user_exists = False if user is not None and not user.is_empty: # the upper layer will catch / at least should try: (uid, _resolver, resolverClass) = getUserId( user, check_existance=True) user_exists = True except Exception as _exx: pass_on = context.get('Config').get( 'linotp.PassOnUserNotFound', False) if pass_on and 'true' == pass_on.lower(): audit['action_detail'] = ( 'authenticated by PassOnUserNotFound') return (True, opt) else: audit['action_detail'] = 'User not found' return (False, opt) # if we have an user, check if we forward the request to another server if user_exists and get_auth_forward_on_no_token(user) is False: servers = get_auth_forward(user) if servers: res, opt = ForwardServerPolicy.do_request(servers, env, user, passw, options) return res, opt # ------------------------------------------------------------------ -- th = TokenHandler() # ------------------------------------------------------------------ -- # auto asignement with otp only if user has no active token auto_assign_otp_return = th.auto_assign_otp_only( otp=passw, user=user, options=options) if auto_assign_otp_return is True: return (True, None) # ------------------------------------------------------------------ -- token_type = None if options: token_type = options.get('token_type', None) # ------------------------------------------------------------------ -- # if there is a serial provided in the parameters, it overwrites the # token selection by user query_user = user if options and 'serial' in options and options['serial']: serial = options['serial'] query_user = None # ------------------------------------------------------------------ -- tokenList = getTokens4UserOrSerial( query_user, serial, token_type=token_type, read_for_update=True ) if len(tokenList) == 0: audit['action_detail'] = 'User has no tokens assigned' # here we check if we should to autoassign and try to do it auto_assign_return = th.auto_assignToken(passw, user) if auto_assign_return is True: # We can not check the token, as the OTP value is already used! # but we will auth the user.... return (True, opt) auto_enroll_return, opt = th.auto_enrollToken(passw, user, options=options) if auto_enroll_return is True: # we always have to return a false, as # we have a challenge tiggered return (False, opt) pass_on = context.get('Config').get('linotp.PassOnUserNoToken', False) if pass_on and 'true' == pass_on.lower(): audit['action_detail'] = 'authenticated by PassOnUserNoToken' return (True, opt) # Check if there is an authentication policy passthru if get_auth_passthru(user): log.debug('user %r has no token. Checking for ' 'passthru in realm %r' % (user.login, user.realm)) y = getResolverObject(resolverClass) audit['action_detail'] = 'Authenticated against Resolver' if y.checkPass(uid, passw): return (True, opt) # Check alternatively if there is an authentication # policy passOnNoToken elif get_auth_passOnNoToken(user): log.info('user %r has not token. PassOnNoToken' ' set - authenticated!') audit['action_detail'] = ( 'Authenticated by passOnNoToken policy') return (True, opt) # if we have an user, check if we forward the request to another server elif get_auth_forward_on_no_token(user) is True: servers = get_auth_forward(user) if servers: res, opt = ForwardServerPolicy.do_request( servers, env, user, passw, options) return res, opt return False, opt if passw is None: raise ParameterError(u"Missing parameter:pass", id=905) (res, opt) = self.checkTokenList( tokenList, passw, user, options=options) return (res, opt)