def webkdc_userinfo(self): # Called by WebAuth via the Elm remctld scripts. # Returns information about whether the user owns any tokens. # TODO: Require some sort of session token. param = {} try: param.update(request.params) user = getUserFromParam(param, optionalOrRequired = True) if (user is not None and user.isEmpty() == False): (userid, idResolver, idResolverClass) = getUserId(user) sqlQuery = Session.query(model.Token).with_lockmode("update").filter( model.Token.LinOtpUserid == userid).filter( model.Token.LinOtpIdResClass == idResolverClass).filter( model.Token.LinOtpIsactive == 1) tokenList = [] for token in sqlQuery: tokenList.append(token.LinOtpTokenSerialnumber) Session.commit() return sendResult(response, tokenList, 0) except Exception as exx: log.error("[webkdc_userinfo] validate/webkdc_userinfo failed: %r" % exx) log.error("[webkdc_userinfo] %s" % traceback.format_exc()) Session.rollback() return sendError(response, u"validate/webkdc_userinfo failed: %s" % unicode(exx), 0) finally: Session.close()
def samlcheck(self): ''' This function is used to validate the username and the otp value/password in a SAML environment. If ``linotp.allowSamlAttributes = True`` then the attributes of the authenticated users are also contained in the response. method: validate/samlcheck arguments: * user: username / loginname * pass: the password that consists of a possible fixes password component and the OTP value * realm: optional realm to match the user to a useridresolver returns: JSON response ''' try: opt = None param = self.request_params (ok, opt) = self._check(param) attributes = {} if True == ok: allowSAML = False try: allowSAML = getFromConfig("allowSamlAttributes") except: log.warning("[samlcheck] Calling controller samlcheck. But allowSamlAttributes is False.") if "True" == allowSAML: ## Now we get the attributes of the user user = getUserFromParam(param) (uid, resId, resIdC) = getUserId(user) userInfo = getUserInfo(uid, resId, resIdC) log.debug("[samlcheck] getting attributes for: %s@%s" % (user.login, user.realm)) res = userInfo for key in ['username', 'surname', 'mobile', 'phone', 'givenname', 'email']: if key in res: attributes[key] = res[key] Session.commit() return sendResult(response, { 'auth': ok, 'attributes' : attributes } , 0, opt) except Exception as exx: log.exception("[samlcheck] validate/check failed: %r" % exx) Session.rollback() return sendResult(response, False, 0) finally: Session.close()
def samlcheck(self): ''' This function is used to validate the username and the otp value/password in a SAML environment. If ``linotp.allowSamlAttributes = True`` then the attributes of the authenticated users are also contained in the response. method: validate/samlcheck arguments: * user: username / loginname * pass: the password that consists of a possible fixes password component and the OTP value * realm: optional realm to match the user to a useridresolver returns: JSON response ''' try: opt = None param = request.params (ok, opt) = self._check(param) attributes = {} if True == ok: allowSAML = False try: allowSAML = getFromConfig("allowSamlAttributes") except: log.warning("[samlcheck] Calling controller samlcheck. But allowSamlAttributes is False.") if "True" == allowSAML: ## Now we get the attributes of the user user = getUserFromParam(param) (uid, resId, resIdC) = getUserId(user) userInfo = getUserInfo(uid, resId, resIdC) log.debug("[samlcheck] getting attributes for: %s@%s" % (user.login, user.realm)) res = userInfo for key in ['username', 'surname', 'mobile', 'phone', 'givenname', 'email']: if key in res: attributes[key] = res[key] Session.commit() return sendResult(response, { 'auth': ok, 'attributes' : attributes } , 0, opt) except Exception as exx: log.exception("[samlcheck] validate/check failed: %r" % exx) Session.rollback() return sendResult(response, False, 0) finally: Session.close()
def get_userinfo(user): (uid, resolver, resolver_class) = getUserId(user) uinfo = getUserInfo(uid, resolver, resolver_class) if 'cryptpass' in uinfo: del uinfo['cryptpass'] return uinfo
def get_userinfo(user): (uid, resolver, resolver_class) = getUserId(user) uinfo = getUserInfo(uid, resolver, resolver_class) if "cryptpass" in uinfo: del uinfo["cryptpass"] uinfo["realm"] = user.realm return uinfo
def samlcheck(self): """ This function is used to validate the username and the otp value/password in a SAML environment. If ``linotp.allowSamlAttributes = True`` then the attributes of the authenticated users are also contained in the response. method: validate/samlcheck arguments: * user: username / loginname * pass: the password that consists of a possible fixes password component and the OTP value * realm: optional realm to match the user to a useridresolver returns: JSON response """ try: opt = None param = request.params (ok, opt) = self._check(param) attributes = {} if True == ok: allowSAML = False try: allowSAML = getFromConfig("allowSamlAttributes") except: log.warning("[samlcheck] Calling controller samlcheck. But allowSamlAttributes == False.") if "True" == allowSAML: ## Now we get the attributes of the user user = getUserFromParam(param, optional) (uid, resId, resIdC) = getUserId(user) userInfo = getUserInfo(uid, resId, resIdC) # users = getUserList({ 'username':user.getUser()} , user) log.debug("[samlcheck] getting attributes for: %s@%s" % (user.getUser(), user.getRealm())) res = userInfo for key in ["username", "surname", "mobile", "phone", "givenname", "email"]: if key in res: attributes[key] = res[key] Session.commit() return sendResult(response, {"auth": ok, "attributes": attributes}, 0, opt) except Exception as exx: log.error("[samlcheck] validate/check failed: %r" % exx) log.error("[samlcheck] %s" % traceback.format_exc()) Session.rollback() return sendError(response, "validate/samlcheck failed: %s" % unicode(exx), 0) finally: Session.close() log.debug("[samlcheck] done")
def check_pin(token, passw, user=None, options=None): """ check the provided pin w.r.t. the policy definition :param token: the token to be checked :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 pin_policies = linotp.lib.policy.get_pin_policies(user) if 0 in pin_policies or "token_pin" in pin_policies: # old stuff: We check The fixed OTP PIN log.debug('[__checkToken] pin policy=0: checkin the PIN') res = token.checkPin(passw, options=options) elif 1 in pin_policies or "password" 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 or not user.login: log.info('- fail for pin policy == 1 with user = None') return False (uid, _resolver, resolver_class) = getUserId(user) r_obj = getResolverObject(resolver_class) if r_obj.checkPass(uid, passw): log.debug('[__checkToken] Successfully authenticated user %r.' % uid) res = True else: log.info('[__checkToken] user %r failed to auth.' % uid) elif 2 in pin_policies or "only_otp" in pin_policies: # NO PIN should be entered at all log.debug('[__checkToken] pin policy=2: checking no pin') if len(passw) == 0: res = True else: # old stuff: We check The fixed OTP PIN log.debug('[__checkToken] pin policy=0: checkin the PIN') res = token.checkPin(passw, options=options) return res
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 context = token.context pin_policies = linotp.lib.policy.get_pin_policies(user, context=context) if 1 in pin_policies: # We check the Users Password as PIN log.debug("[check_pin] pin policy=1: checking the users" " password as pin") if (user is None or not user.login): log.info("[check_pin] - fail for pin policy == 1 " "with user = None") return False (uid, _resolver, resolver_class) = getUserId(user) r_obj = getResolverObject(resolver_class) if r_obj.checkPass(uid, passw): log.debug("[__checkToken] Successfully authenticated user %r." % uid) res = True else: log.info("[__checkToken] user %r failed to authenticate." % uid) elif 2 in pin_policies: # NO PIN should be entered atall log.debug("[__checkToken] pin policy=2: checking no pin") if len(passw) == 0: res = True else: # old stuff: We check The fixed OTP PIN log.debug("[__checkToken] pin policy=0: checkin the PIN") res = token.checkPin(passw, options=options) return res
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 pin_policies = linotp.lib.policy.get_pin_policies(user) if 1 in pin_policies: # We check the Users Password as PIN LOG.debug("[check_pin] pin policy=1: checking the users" " password as pin") if (user is None): raise Exception("[check_pin] - 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("[__checkToken] Successfully authenticated user %r." % uid) res = True else: LOG.info("[__checkToken] user %r failed to authenticate." % uid) elif 2 in pin_policies: # NO PIN should be entered atall LOG.debug("[__checkToken] pin policy=2: checking no pin") if len(passw) == 0: res = True else: # old stuff: We check The fixed OTP PIN LOG.debug("[__checkToken] pin policy=0: checkin the PIN") res = token.checkPin(passw, options=options) return res
def get_userinfo(login): uinfo = {} if "@" in login: uuser, rrealm = login.split("@") user = User(uuser, rrealm) else: realm = getDefaultRealm() user = User(login, realm) (uid, resolver, resolver_class) = getUserId(user) uinfo = getUserInfo(uid, resolver, resolver_class) # the passwd resolver should not expose the crypted/hasehd password if "cryptpass" in uinfo: del uinfo["cryptpass"] return uinfo
def get_userinfo(login): uinfo = {} if '@' in login: uuser, rrealm = login.split("@") user = User(uuser, rrealm) else: realm = getDefaultRealm() user = User(login, realm) (uid, resolver, resolver_class) = getUserId(user) uinfo = getUserInfo(uid, resolver, resolver_class) # the passwd resolver should not expose the crypted/hasehd password if 'cryptpass' in uinfo: del uinfo['cryptpass'] return uinfo
def get_user_detail(self): """ get detail info about openid cookie owner :return: tuple of (email,firstname,lastname,fullname) """ email = "" fullname = "" firstname = "" lastname = "" ## search in userresolvers for user detail user = self.user if "@" not in user: user = "******" % (user, getDefaultRealm()) login, realm = user.split('@') usr = User(login, realm) (userid, res_id, res_conf) = getUserId(usr) usr_detail = getUserInfo(userid, res_id, res_conf) if "email" in usr_detail: email = usr_detail["email"] if "givenname" in usr_detail: firstname = usr_detail["givenname"] if "surname" in usr_detail: lastname = usr_detail["surname"] if firstname and lastname: fullname = "%s %s" % (firstname, lastname) elif firstname: fullname = "%s" % firstname elif lastname: fullname = "%s" % lastname return (email, firstname, lastname, fullname)
def webkdc_userinfo(self): # Called by WebAuth via the Elm remctld scripts. # Returns information about whether the user owns any tokens. # TODO: Require some sort of session token. param = {} try: param.update(request.params) user = getUserFromParam(param, optionalOrRequired=True) if (user is not None and user.isEmpty() == False): (userid, idResolver, idResolverClass) = getUserId(user) sqlQuery = Session.query( model.Token).with_lockmode("update").filter( model.Token.LinOtpUserid == userid).filter( model.Token.LinOtpIdResClass == idResolverClass ).filter(model.Token.LinOtpIsactive == True) tokenList = {} for token in sqlQuery: tokenList[token.LinOtpTokenSerialnumber] = json.loads( token.LinOtpTokenInfo) Session.commit() return sendResult(response, tokenList, 0) except Exception as exx: log.error("[webkdc_userinfo] validate/webkdc_userinfo failed: %r" % exx) log.error("[webkdc_userinfo] %s" % traceback.format_exc()) Session.rollback() return sendError( response, u"validate/webkdc_userinfo failed: %s" % unicode(exx), 0) finally: Session.close()
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 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_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 otppin_mode = _get_otppin_mode(get_pin_policies(user)) if 1 == otppin_mode: # We check the Users Password as PIN log.debug("pin policy=1: checking the users password as pin") # this should not be the case if not options: options = {} selfservice_state = context.get('selfservice', {}).get('state', '') if selfservice_state in ['credentials_verified', 'challenge_triggered']: return True if 'pin_match' not in options: options['pin_match'] = {} hashed_passw = sha256(passw.encode('utf-8')).hexdigest() # if password already found, we can return result again if hashed_passw in options['pin_match']: log.debug("check if password already checked! %r " % options['pin_match'][hashed_passw]) return options['pin_match'][hashed_passw] # if a password already matched, this one will fail if 'found' in options['pin_match']: log.debug("check if password already found but its not this one!") return False if user is None or not user.login: log.info("fail for pin policy == 1 with user = None") res = False else: (uid, _resolver, resolver_class) = getUserId(user) resolver = getResolverObject(resolver_class) if resolver.checkPass(uid, passw): log.debug("Successfully authenticated user %r." % uid) res = True else: log.info("user %r failed to authenticate." % uid) # we register our result key = sha256(passw.encode('utf-8')).hexdigest() options['pin_match'][key] = res # and register the success, to shorten lookups after # already one positive was found if res is True: options['pin_match']['found'] = True return res elif otppin_mode == 2: # NO PIN should be entered atall log.debug("[__checkToken] pin policy=2: checking no pin") return len(passw) == 0 elif otppin_mode == 3: # ignore pin or password log.debug("[__checkToken] pin policy=3: ignoreing pin") if token.type in ['spass']: return token.checkPin(passw, options=options) return True else: # old stuff: We check The fixed OTP PIN log.debug("[__checkToken] pin policy=0: checkin the PIN") return token.checkPin(passw, options=options)
def _get_user_condition(self, user, valid_realms): ucondition = None log.debug('[TokenIterator::init] start search for username: >%r<' % (user)) if not user or user.isEmpty() or not user.login: return ucondition loginUser = user.login.lower() loginUser = loginUser.replace('"', '') loginUser = loginUser.replace("'", '') searchType = "any" ## search for a 'blank' user if len(loginUser) == 0 and len(user.login) > 0: searchType = "blank" elif loginUser == "/:no user:/" or loginUser == "/:none:/": searchType = "blank" elif loginUser == "/:no user info:/": searchType = "wildcard" elif "*" in loginUser or "." in loginUser: searchType = "wildcard" else: ## no blank and no wildcard search searchType = "exact" if searchType == "blank": log.debug('[TokenIterator::init] search for empty user: >%r<' % (user.login)) ucondition = and_(or_(Token.LinOtpUserid == u'', Token.LinOtpUserid is None)) if searchType == "exact": log.debug('[TokenIterator::init] search for exact user: %r' % (user)) serials = [] users = [] ## if search for a realmuser 'user@realm' we can take the ## realm from the argument if len(user.realm) > 0: users.append(user) else: for realm in valid_realms: users.append(User(user.login, realm)) # resolve the realm with wildcard: # identify all users and add these to the userlist userlist = [] for usr in users: urealm = usr.realm if urealm == '*': # if the realm is set to *, the getUserId # triggers the identification of all resolvers, where the # user might reside: tigger the user resolver lookup (uid, resolver, resolverClass) = getUserId(usr) userlist.extend(usr.getUserPerConf()) else: userlist.append(usr) for usr in userlist: try: tokens = getTokens4UserOrSerial(user=usr, _class=False) for tok in tokens: serials.append(tok.LinOtpTokenSerialnumber) except UserError as ex: ## we get an exception if the user is not found log.debug('[TokenIterator::init] no exact user: %r' % (user)) log.debug('[TokenIterator::init] %r' % ex) if len(serials) > 0: # if tokens found, search for their serials ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: # if no token is found, block search for user # and return nothing ucondition = and_(Token.LinOtpTokenSerialnumber == u'') ## handle case, when nothing found in former cases if searchType == "wildcard": log.debug('[TokenIterator::init] wildcard search: %r' % (user)) serials = [] users = getAllTokenUsers() logRe = None lU = loginUser.replace('*', '.*') #lU = lU.replace('..', '.') logRe = re.compile(lU) for ser in users: userInfo = users.get(ser) tokenUser = userInfo.get('username').lower() try: if logRe.match(u'' + tokenUser) is not None: serials.append(ser) except Exception as e: log.error('error no express %r ' % e) ## to prevent warning, we check is serials are found ## SAWarning: The IN-predicate on ## "Token.LinOtpTokenSerialnumber" was invoked with an ## empty sequence. This results in a contradiction, which ## nonetheless can be expensive to evaluate. Consider ## alternative strategies for improved performance. if len(serials) > 0: ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: ucondition = and_(Token.LinOtpTokenSerialnumber == u'') return ucondition
def _get_user_condition(self, user, valid_realms): ucondition = None log.debug('[TokenIterator::init] start search for username: >%r<' % (user)) if not user or user.isEmpty() or not user.login: return ucondition loginUser = user.login.lower() loginUser = loginUser.replace('"', '') loginUser = loginUser.replace("'", '') searchType = "any" ## search for a 'blank' user if len(loginUser) == 0 and len(user.login) > 0: searchType = "blank" elif loginUser == "/:no user:/" or loginUser == "/:none:/": searchType = "blank" elif loginUser == "/:no user info:/": searchType = "wildcard" elif "*" in loginUser or "." in loginUser: searchType = "wildcard" else: ## no blank and no wildcard search searchType = "exact" if searchType == "blank": log.debug('[TokenIterator::init] search for empty user: >%r<' % (user.login)) ucondition = and_( or_(Token.LinOtpUserid == u'', Token.LinOtpUserid is None)) if searchType == "exact": log.debug('[TokenIterator::init] search for exact user: %r' % (user)) serials = [] users = [] ## if search for a realmuser 'user@realm' we can take the ## realm from the argument if len(user.realm) > 0: users.append(user) else: for realm in valid_realms: users.append(User(user.login, realm)) # resolve the realm with wildcard: # identify all users and add these to the userlist userlist = [] for usr in users: urealm = usr.realm if urealm == '*': # if the realm is set to *, the getUserId # triggers the identification of all resolvers, where the # user might reside: tigger the user resolver lookup (uid, resolver, resolverClass) = getUserId(usr) userlist.extend(usr.getUserPerConf()) else: userlist.append(usr) for usr in userlist: try: tokens = getTokens4UserOrSerial(user=usr, _class=False) for tok in tokens: serials.append(tok.LinOtpTokenSerialnumber) except UserError as ex: ## we get an exception if the user is not found log.debug('[TokenIterator::init] no exact user: %r' % (user)) log.debug('[TokenIterator::init] %r' % ex) if len(serials) > 0: # if tokens found, search for their serials ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: # if no token is found, block search for user # and return nothing ucondition = and_(Token.LinOtpTokenSerialnumber == u'') ## handle case, when nothing found in former cases if searchType == "wildcard": log.debug('[TokenIterator::init] wildcard search: %r' % (user)) serials = [] users = getAllTokenUsers() logRe = None lU = loginUser.replace('*', '.*') #lU = lU.replace('..', '.') logRe = re.compile(lU) for ser in users: userInfo = users.get(ser) tokenUser = userInfo.get('username').lower() try: if logRe.match(u'' + tokenUser) is not None: serials.append(ser) except Exception as e: log.error('error no express %r ' % e) ## to prevent warning, we check is serials are found ## SAWarning: The IN-predicate on ## "Token.LinOtpTokenSerialnumber" was invoked with an ## empty sequence. This results in a contradiction, which ## nonetheless can be expensive to evaluate. Consider ## alternative strategies for improved performance. if len(serials) > 0: ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: ucondition = and_(Token.LinOtpTokenSerialnumber == u'') return ucondition
def _get_user_condition(self, user, valid_realms): ucondition = None if not user or user.is_empty or not user.login: return ucondition loginUser = user.login.lower() loginUser = loginUser.replace('"', '') loginUser = loginUser.replace("'", '') searchType = "any" ## search for a 'blank' user if len(loginUser) == 0 and len(user.login) > 0: searchType = "blank" elif loginUser == "/:no user:/" or loginUser == "/:none:/": searchType = "blank" elif loginUser == "/:no user info:/": searchType = "wildcard" elif "*" in loginUser: searchType = "wildcard" else: ## no blank and no wildcard search searchType = "exact" if searchType == "blank": ucondition = and_(or_(Token.LinOtpUserid == u'', Token.LinOtpUserid is None)) if searchType == "exact": serials = [] users = [] # if search for a realmuser 'user@realm' we can take the # realm from the argument if len(user.realm) > 0: users.append(user) else: # otherwise we add all users which are possible combinations # from loginname and entry of the valid realms. # In case of a '*' wildcard in the list, we take all available # realms if '*' in valid_realms: valid_realm_list = getRealms().keys() else: valid_realm_list = valid_realms for realm in valid_realm_list: users.append(User(user.login, realm)) # resolve the realm with wildcard: # identify all users and add these to the userlist userlist = [] for usr in users: urealm = usr.realm if urealm == '*': # if the realm is set to *, the getUserId # triggers the identification of all resolvers, where the # user might reside: trigger the user resolver lookup for realm in getRealms().keys(): if realm in valid_realms or '*' in valid_realms: usr.realm = realm try: (_uid, _resolver, _resolverClass) = getUserId(usr) except UserError as exx: log.info('User %r not found in realm %r', usr, realm) continue userlist.extend(usr.getUserPerConf()) else: userlist.append(usr) for usr in userlist: try: tokens = getTokens4UserOrSerial(user=usr, _class=False) for tok in tokens: serials.append(tok.LinOtpTokenSerialnumber) except UserError as ex: ## we get an exception if the user is not found log.debug('[TokenIterator::init] no exact user: %r' % (user)) log.debug('[TokenIterator::init] %r' % ex) if len(serials) > 0: # if tokens found, search for their serials ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: # if no token is found, block search for user # and return nothing ucondition = and_(Token.LinOtpTokenSerialnumber == u'') ## handle case, when nothing found in former cases if searchType == "wildcard": serials = _user_expression_match(loginUser, token_owner_iterator()) # to prevent warning, we check is serials are found # SAWarning: The IN-predicate on # "Token.LinOtpTokenSerialnumber" was invoked with an # empty sequence. This results in a contradiction, which # nonetheless can be expensive to evaluate. Consider # alternative strategies for improved performance. if len(serials) > 0: ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: ucondition = and_(Token.LinOtpTokenSerialnumber == u'') return ucondition
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 pin_policies = linotp.lib.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") # this should not be the case if not options: options = {} if 'pin_match' not in options: options['pin_match'] = {} hashed_passw = sha256(passw.encode('utf-8')).hexdigest() # if password already found, we can return result again if hashed_passw in options['pin_match']: log.debug("check if password already checked! %r " % options['pin_match'][hashed_passw]) return options['pin_match'][hashed_passw] # if a password already matched, this one will fail if 'found' in options['pin_match']: log.debug("check if password already found but its not this one!") return False if user is None or not user.login: log.info("fail for pin policy == 1 with user = None") res = False else: (uid, _resolver, resolver_class) = getUserId(user) resolver = getResolverObject(resolver_class) if resolver.checkPass(uid, passw): log.debug("Successfully authenticated user %r." % uid) res = True else: log.info("user %r failed to authenticate." % uid) # we register our result key = sha256(passw.encode('utf-8')).hexdigest() options['pin_match'][key] = res # and register the success, to shorten lookups after # already one positive was found if res is True: options['pin_match']['found'] = True elif 2 in pin_policies: # NO PIN should be entered atall log.debug("[__checkToken] pin policy=2: checking no pin") if len(passw) == 0: res = True else: # old stuff: We check The fixed OTP PIN log.debug("[__checkToken] pin policy=0: checkin the PIN") res = token.checkPin(passw, options=options) return res
def __init__(self, user, serial, page=None, psize=None, filter=None, sort=None, sortdir=None, filterRealm=None, user_fields=None, params=None): ''' constructor of Tokeniterator, which gathers all conditions to build a sqalchemy query - iterator :param user: User object - user provides as well the searchfield entry :type user: User class :param serial: serial number of a token :type serial: string :param page: page number :type page: int :param psize: how many entries per page :type psize: int :param filter: additional condition :type filter: string :param sort: sort field definition :type sort: string :param sortdir: sort direction: ascending or descending :type sortdir: string :param filterRealm: restrict the set of token to those in the filterRealm :type filterRealm: string or list :param user_fields: list of additional fields from the user owner :type user_fields: array :param params: list of additional request parameters - currently not used :type params: dict :return: - nothing / None ''' log.debug('[TokenIterator::init] begin. start creating TokenIterator \ class with parameters: user:%r, serial:%r, page=%r, psize:%r, \ filter:%r, sort:%r, sortdir:%r, filterRealm:%r' % (user, serial, page, psize, filter, sort, sortdir, filterRealm)) if params is None: params = {} self.page = 1 self.pages = 1 self.tokens = 0 self.user_fields = user_fields if self.user_fields == None: self.user_fields = [] condition = None ucondition = None scondition = None r_condition = None if type(filterRealm) in (str, unicode): filterRealm = filterRealm.split(',') if type(filterRealm) in [list]: s_realms = [] for f in filterRealm: # support for multiple realm filtering in the ui # as a coma separated string for s_realm in f.split(','): s_realms.append(s_realm.strip()) filterRealm = s_realms # create a list of all realms, which are allowed to be searched # based on the list of the existing ones valid_realms = [] realms = getRealms().keys() if '*' in filterRealm: valid_realms.append("*") else: for realm in realms: if realm in filterRealm: realm = linotp.lib.crypt.uencode(realm) valid_realms.append(realm) if serial is not None: # check if the requested serial is in the realms of # the admin (filterRealm) log.debug('[TokenIterator::init] start search for serial: >%r<' % (serial)) allowed = False if filterRealm == ['*']: allowed = True else: realms = getTokenRealms(serial) for realm in realms: if realm in filterRealm: allowed = True if allowed == True: if '*' in serial: serial = serial.replace('*', '%') scondition = and_(Token.LinOtpTokenSerialnumber.like(serial)) else: scondition = and_(Token.LinOtpTokenSerialnumber == serial) if user.isEmpty() == False and user is not None: log.debug('[TokenIterator::init] start search for username: >%r<' % (user)) if user.login is not None and (user.login) > 0 : loginUser = user.login.lower() loginUser = loginUser.replace('"', '') loginUser = loginUser.replace("'", '') searchType = "any" # search for a 'blank' user if len(loginUser) == 0 and len(user.login) > 0: searchType = "blank" elif loginUser == "/:no user:/" or loginUser == "/:none:/": searchType = "blank" elif loginUser == "/:no user info:/": searchType = "wildcard" elif "*" in loginUser or "." in loginUser: searchType = "wildcard" else: # no blank and no wildcard search searchType = "exact" if searchType == "blank": log.debug('[TokenIterator::init] search for empty user:'******' >%r<' % (user.login)) ucondition = and_(or_(Token.LinOtpUserid == u'', Token.LinOtpUserid == None)) if searchType == "exact": log.debug('[TokenIterator::init] search for exact user:'******' %r' % (user)) serials = [] users = [] # if search for a realmuser 'user@realm' we can take the # realm from the argument if len(user.realm) > 0: users.append(user) else: for realm in valid_realms: users.append(User(user.login, realm)) # resolve the realm with wildcard: # identify all users and add these to the userlist userlist = [] for usr in users: urealm = usr.realm if urealm == '*': # if the realm is set to *, the getUserId # triggers the identification of all resolvers, # where the user might reside: tigger the user # resolver lookup (uid, resolver, resolverClass) = getUserId(usr) userlist.extend(usr.getUserPerConf()) else: userlist.append(usr) for usr in userlist: try: tokens = getTokens4UserOrSerial(user=usr, _class=False) for tok in tokens: serials.append(tok.LinOtpTokenSerialnumber) except UserError as ex: # we get an exception if the user is not found log.debug('[TokenIterator::init] no exact user: %r' % (user)) log.debug('[TokenIterator::init] %r' % ex) if len(serials) > 0: # if tokens found, search for their serials ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: # if no token is found, block search for user # and return nothing ucondition = and_(Token.LinOtpTokenSerialnumber == u'') # handle case, when nothing found in former cases if searchType == "wildcard": log.debug('[TokenIterator::init] wildcard search: %r' % (user)) serials = [] users = getAllTokenUsers() logRe = None lU = loginUser.replace('*', '.*') # lU = lU.replace('..', '.') logRe = re.compile(lU) for ser in users: userInfo = users.get(ser) tokenUser = userInfo.get('username').lower() try: if logRe.match(u'' + tokenUser) is not None: serials.append(ser) except Exception as e: log.error('error no express %r ' % e) # to prevent warning, we check is serials are found # SAWarning: The IN-predicate on # "Token.LinOtpTokenSerialnumber" was invoked with an # empty sequence. This results in a contradiction, which # nonetheless can be expensive to evaluate. Consider # alternative strategies for improved performance. if len(serials) > 0: ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: ucondition = and_(Token.LinOtpTokenSerialnumber == u'') if filter is None: condition = None elif filter in ['/:active:/', '/:enabled:/', '/:token is active:/', '/:token is enabled:/' ]: condition = and_(Token.LinOtpIsactive == True) elif filter in ['/:inactive:/', '/:disabled:/', '/:token is inactive:/', '/:token is disabled:/']: condition = and_(Token.LinOtpIsactive == False) else: # search in other colums filter = linotp.lib.crypt.uencode(filter) condition = or_(Token.LinOtpTokenDesc.contains(filter), Token.LinOtpIdResClass.contains(filter), Token.LinOtpTokenSerialnumber.contains(filter), Token.LinOtpUserid.contains(filter), Token.LinOtpTokenType.contains(filter)) ################################################################### # The condition for only getting certain realms! if '*' in valid_realms: log.debug("[TokenIterator::init] wildcard for realm '*' found." " Tokens of all realms will be displayed") elif len(valid_realms) > 0: log.debug("[TokenIterator::init] adding filter condition" " for realm %r" % valid_realms) # get all matching realms realm_id_tuples = Session.query(Realm.id).\ filter(Realm.name.in_(valid_realms)).all() realm_ids = set() for realm_tuple in realm_id_tuples: realm_ids.add(realm_tuple[0]) # get all tokenrealm ids token_id_tuples = Session.query(TokenRealm.token_id).\ filter(TokenRealm.realm_id.in_(realm_ids)).all() token_ids = set() for token_tuple in token_id_tuples: token_ids.add(token_tuple[0]) # define the token id condition r_condition = and_(Token.LinOtpTokenId.in_(token_ids)) elif ("''" in filterRealm or '""' in filterRealm or "/:no realm:/" in filterRealm): log.debug("[TokenIterator::init] search for all tokens, which are" " in no realm") # get all tokenrealm ids token_id_tuples = Session.query(TokenRealm.token_id).all() token_ids = set() for token_tuple in token_id_tuples: token_ids.add(token_tuple[0]) # define the token id not condition r_condition = and_(not_(Token.LinOtpTokenId.in_(token_ids))) # create the final condition as AND of all conditions condTuple = () for conn in (condition, ucondition, scondition, r_condition): if type(conn).__name__ != 'NoneType': condTuple += (conn,) condition = and_(*condTuple) order = Token.LinOtpTokenDesc if sort == "TokenDesc": order = Token.LinOtpTokenDesc elif sort == "TokenId": order = Token.LinOtpTokenId elif sort == "TokenType": order = Token.LinOtpTokenType elif sort == "TokenSerialnumber": order = Token.LinOtpTokenSerialnumber elif sort == "TokenType": order = Token.LinOtpTokenType elif sort == "IdResClass": order = Token.LinOtpIdResClass elif sort == "IdResolver": order = Token.LinOtpIdResolver elif sort == "Userid": order = Token.LinOtpUserid elif sort == "FailCount": order = Token.LinOtpFailCount elif sort == "Userid": order = Token.LinOtpUserid elif sort == "Isactive": order = Token.LinOtpIsactive # care for the result sort order if sortdir is not None and sortdir == "desc": order = order.desc() else: order = order.asc() # care for the result pageing if page is None: self.toks = Session.query(Token).filter(condition).order_by(order).distinct() self.tokens = self.toks.count() log.debug("[TokenIterator] DB-Query returned # of objects:" " %i" % self.tokens) self.pagesize = self.tokens self.it = iter(self.toks) return try: if psize is None: pagesize = int(getFromConfig("pagesize", 50)) else: pagesize = int(psize) except: pagesize = 20 try: thePage = int (page) - 1 except: thePage = 0 if thePage < 0: thePage = 0 start = thePage * pagesize stop = (thePage + 1) * pagesize self.toks = Session.query(Token).filter(condition).\ order_by(order).distinct() self.tokens = self.toks.count() log.debug("[TokenIterator::init] DB-Query returned # of objects:" " %i" % self.tokens) self.page = thePage + 1 fpages = float(self.tokens) / float(pagesize) self.pages = int(fpages) if fpages - int(fpages) > 0: self.pages = self.pages + 1 self.pagesize = pagesize self.toks = self.toks.slice(start, stop) self.it = iter(self.toks) log.debug('[TokenIterator::init] end. Token iterator created: %r' % \ (self.it)) return
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 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 __init__(self, user, serial, page=None, psize=None, filter=None, sort=None, sortdir=None, filterRealm=None, user_fields=None, params=None): ''' constructor of Tokeniterator, which gathers all conditions to build a sqalchemy query - iterator :param user: User object - user provides as well the searchfield entry :type user: User class :param serial: serial number of a token :type serial: string :param page: page number :type page: int :param psize: how many entries per page :type psize: int :param filter: additional condition :type filter: string :param sort: sort field definition :type sort: string :param sortdir: sort direction: ascending or descending :type sortdir: string :param filterRealm: restrict the set of token to those in the filterRealm :type filterRealm: string or list :param user_fields: list of additional fields from the user owner :type user_fields: array :param params: list of additional request parameters - currently not used :type params: dict :return: - nothing / None ''' log.debug('[TokenIterator::init] begin. start creating TokenIterator \ class with parameters: user:%r, serial:%r, page=%r, psize:%r, \ filter:%r, sort:%r, sortdir:%r, filterRealm:%r' % (user, serial, page, psize, filter, sort, sortdir, filterRealm)) if params is None: params = {} self.page = 1 self.pages = 1 self.tokens = 0 self.user_fields = user_fields if self.user_fields == None: self.user_fields = [] condition = None ucondition = None scondition = None r_condition = None if type(filterRealm) in (str, unicode): filterRealm = filterRealm.split(',') if type(filterRealm) in [list]: s_realms = [] for f in filterRealm: # support for multiple realm filtering in the ui # as a coma separated string for s_realm in f.split(','): s_realms.append(s_realm.strip()) filterRealm = s_realms # create a list of all realms, which are allowed to be searched # based on the list of the existing ones valid_realms = [] realms = getRealms().keys() if '*' in filterRealm: valid_realms.append("*") else: for realm in realms: if realm in filterRealm: realm = linotp.lib.crypt.uencode(realm) valid_realms.append(realm) if serial is not None: # check if the requested serial is in the realms of # the admin (filterRealm) log.debug('[TokenIterator::init] start search for serial: >%r<' % (serial)) allowed = False if filterRealm == ['*']: allowed = True else: realms = getTokenRealms(serial) for realm in realms: if realm in filterRealm: allowed = True if allowed == True: if '*' in serial: serial = serial.replace('*', '%') scondition = and_(Token.LinOtpTokenSerialnumber.like(serial)) else: scondition = and_(Token.LinOtpTokenSerialnumber == serial) if user.isEmpty() == False and user is not None: log.debug('[TokenIterator::init] start search for username: >%r<' % (user)) if user.login is not None and (user.login) > 0 : loginUser = user.login.lower() loginUser = loginUser.replace('"', '') loginUser = loginUser.replace("'", '') searchType = "any" # search for a 'blank' user if len(loginUser) == 0 and len(user.login) > 0: searchType = "blank" elif loginUser == "/:no user:/" or loginUser == "/:none:/": searchType = "blank" elif loginUser == "/:no user info:/": searchType = "wildcard" elif "*" in loginUser or "." in loginUser: searchType = "wildcard" else: # no blank and no wildcard search searchType = "exact" if searchType == "blank": log.debug('[TokenIterator::init] search for empty user:'******' >%r<' % (user.login)) ucondition = and_(or_(Token.LinOtpUserid == u'', Token.LinOtpUserid == None)) if searchType == "exact": log.debug('[TokenIterator::init] search for exact user:'******' %r' % (user)) serials = [] users = [] # if search for a realmuser 'user@realm' we can take the # realm from the argument if len(user.realm) > 0: users.append(user) else: for realm in valid_realms: users.append(User(user.login, realm)) # resolve the realm with wildcard: # identify all users and add these to the userlist userlist = [] for usr in users: urealm = usr.realm if urealm == '*': # if the realm is set to *, the getUserId # triggers the identification of all resolvers, # where the user might reside: tigger the user # resolver lookup (uid, resolver, resolverClass) = getUserId(usr) userlist.extend(usr.getUserPerConf()) else: userlist.append(usr) for usr in userlist: try: tokens = getTokens4UserOrSerial(user=usr, _class=False) for tok in tokens: serials.append(tok.LinOtpTokenSerialnumber) except UserError as ex: # we get an exception if the user is not found log.debug('[TokenIterator::init] no exact user: %r' % (user)) log.debug('[TokenIterator::init] %r' % ex) if len(serials) > 0: # if tokens found, search for their serials ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: # if no token is found, block search for user # and return nothing ucondition = and_(or_(Token.LinOtpUserid == u'', Token.LinOtpUserid == None)) # handle case, when nothing found in former cases if searchType == "wildcard": log.debug('[TokenIterator::init] wildcard search: %r' % (user)) serials = [] users = getAllTokenUsers() logRe = None lU = loginUser.replace('*', '.*') # lU = lU.replace('..', '.') logRe = re.compile(lU) for ser in users: userInfo = users.get(ser) tokenUser = userInfo.get('username').lower() try: if logRe.match(u'' + tokenUser) is not None: serials.append(ser) except Exception as e: log.error('error no express %r ' % e) # to prevent warning, we check is serials are found # SAWarning: The IN-predicate on # "Token.LinOtpTokenSerialnumber" was invoked with an # empty sequence. This results in a contradiction, which # nonetheless can be expensive to evaluate. Consider # alternative strategies for improved performance. if len(serials) > 0: ucondition = and_(Token.LinOtpTokenSerialnumber.in_(serials)) else: ucondition = and_(or_(Token.LinOtpUserid == u'', Token.LinOtpUserid == None)) if filter is None: condition = None elif filter in ['/:active:/', '/:enabled:/', '/:token is active:/', '/:token is enabled:/' ]: condition = and_(Token.LinOtpIsactive == True) elif filter in ['/:inactive:/', '/:disabled:/', '/:token is inactive:/', '/:token is disabled:/']: condition = and_(Token.LinOtpIsactive == False) else: # search in other colums filter = linotp.lib.crypt.uencode(filter) condition = or_(Token.LinOtpTokenDesc.contains(filter), Token.LinOtpIdResClass.contains(filter), Token.LinOtpTokenSerialnumber.contains(filter), Token.LinOtpUserid.contains(filter), Token.LinOtpTokenType.contains(filter)) ################################################################### # The condition for only getting certain realms! if '*' in valid_realms: log.debug("[TokenIterator::init] wildcard for realm '*' found." " Tokens of all realms will be displayed") elif len(valid_realms) > 0: log.debug("[TokenIterator::init] adding filter condition" " for realm %r" % valid_realms) # get all matching realms realm_id_tuples = Session.query(Realm.id).\ filter(Realm.name.in_(valid_realms)).all() realm_ids = set() for realm_tuple in realm_id_tuples: realm_ids.add(realm_tuple[0]) # get all tokenrealm ids token_id_tuples = Session.query(TokenRealm.token_id).\ filter(TokenRealm.realm_id.in_(realm_ids)).all() token_ids = set() for token_tuple in token_id_tuples: token_ids.add(token_tuple[0]) # define the token id condition r_condition = and_(Token.LinOtpTokenId.in_(token_ids)) elif ("''" in filterRealm or '""' in filterRealm or "/:no realm:/" in filterRealm): log.debug("[TokenIterator::init] search for all tokens, which are" " in no realm") # get all tokenrealm ids token_id_tuples = Session.query(TokenRealm.token_id).all() token_ids = set() for token_tuple in token_id_tuples: token_ids.add(token_tuple[0]) # define the token id not condition r_condition = and_(not_(Token.LinOtpTokenId.in_(token_ids))) # create the final condition as AND of all conditions condTuple = () for conn in (condition, ucondition, scondition, r_condition): if type(conn).__name__ != 'NoneType': condTuple += (conn,) condition = and_(*condTuple) order = Token.LinOtpTokenDesc if sort == "TokenDesc": order = Token.LinOtpTokenDesc elif sort == "TokenId": order = Token.LinOtpTokenId elif sort == "TokenType": order = Token.LinOtpTokenType elif sort == "TokenSerialnumber": order = Token.LinOtpTokenSerialnumber elif sort == "TokenType": order = Token.LinOtpTokenType elif sort == "IdResClass": order = Token.LinOtpIdResClass elif sort == "IdResolver": order = Token.LinOtpIdResolver elif sort == "Userid": order = Token.LinOtpUserid elif sort == "FailCount": order = Token.LinOtpFailCount elif sort == "Userid": order = Token.LinOtpUserid elif sort == "Isactive": order = Token.LinOtpIsactive # care for the result sort order if sortdir is not None and sortdir == "desc": order = order.desc() else: order = order.asc() # care for the result pageing if page is None: self.toks = Session.query(Token).filter(condition).order_by(order).distinct() self.tokens = self.toks.count() log.debug("[TokenIterator] DB-Query returned # of objects:" " %i" % self.tokens) self.pagesize = self.tokens self.it = iter(self.toks) return try: if psize is None: pagesize = int(getFromConfig("pagesize", 50)) else: pagesize = int(psize) except: pagesize = 20 try: thePage = int (page) - 1 except: thePage = 0 if thePage < 0: thePage = 0 start = thePage * pagesize stop = (thePage + 1) * pagesize self.toks = Session.query(Token).filter(condition).\ order_by(order).distinct() self.tokens = self.toks.count() log.debug("[TokenIterator::init] DB-Query returned # of objects:" " %i" % self.tokens) self.page = thePage + 1 fpages = float(self.tokens) / float(pagesize) self.pages = int(fpages) if fpages - int(fpages) > 0: self.pages = self.pages + 1 self.pagesize = pagesize self.toks = self.toks.slice(start, stop) self.it = iter(self.toks) log.debug('[TokenIterator::init] end. Token iterator created: %r' % \ (self.it)) return
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)