def getUserRealms(user, allRealms=None, defaultRealm=None): ''' Returns the realms, a user belongs to. If the user has no realm but only a useridresolver, than all realms, containing this resolver are returned. This function is used for the policy module ''' if not allRealms: allRealms = getRealms() if not defaultRealm: defRealm = getDefaultRealm().lower() else: defRealm = defaultRealm.lower() Realms = [] if user.realm == "" and user.resolver_config_identifier == "": defRealm = getDefaultRealm().lower() Realms.append(defRealm) user.realm = defRealm elif user.realm != "": Realms.append(user.realm.lower()) else: # we got a resolver and will get all realms the resolver belongs to. for key, v in allRealms.items(): log.debug("[getUserRealms] evaluating realm %r: %r " % (key, v)) for reso in v['useridresolver']: resotype, resoname = reso.rsplit('.', 1) log.debug("[getUserRealms] found resolver %r of type %r" % (resoname, resotype)) if resoname == user.resolver_config_identifier: Realms.append(key.lower()) log.debug("[getUserRealms] added realm %r to Realms due to resolver %r" % (key, user.resolver_config_identifier)) return Realms
def _get_realms_(): realms = {} if getRealmBox(): realms = getRealms() else: def_realm = getDefaultRealm() if getDefaultRealm(): realms = getRealms(def_realm) return realms
def authenticate(self, environ, identity): log.info("[authenticate] entering repoze authenticate function.") # log.debug( identity ) username = None realm = None authUser = None try: if isSelfTest(): if ('login' not in identity and 'repoze.who.plugins.auth_tkt.userid' in identity): uid = identity.get('repoze.who.plugins.auth_tkt.userid') identity['login'] = uid identity['password'] = uid if getRealmBox(): username = identity['login'] realm = identity['realm'] else: log.info("[authenticate] no realmbox") if '@' in identity['login']: if getSplitAtSign(): log.debug("trying to split the loginname") username, _at_, realm = identity['login'].rpartition( '@') else: log.debug("no split for the @ of the loginname") username = identity['login'] realm = identity.get('realm', getDefaultRealm()) else: username = identity['login'] realm = getDefaultRealm() log.info("[authenticate]: username: %r, realm: %r" % (username, realm)) password = identity['password'] except KeyError as e: log.error("[authenticate] Keyerror in identity: %r." % e) log.error("[authenticate] %s" % traceback.format_exc()) return None # as repoze does not run through the std pylons middleware, we have to # convert the input which might be UTF8 to unicode username = str2unicode(username) password = str2unicode(password) # check username/realm, password if isSelfTest(): authUser = "******" % (username, realm) else: authUser = get_authenticated_user(username, realm, password) return authUser
def authenticate(self, environ, identity): log.info("[authenticate] entering repoze authenticate function.") # log.debug( identity ) username = None realm = None authUser = None try: if isSelfTest(): if ('login' not in identity and 'repoze.who.plugins.auth_tkt.userid' in identity): uid = identity.get('repoze.who.plugins.auth_tkt.userid') identity['login'] = uid identity['password'] = uid if getRealmBox(): username = identity['login'] realm = identity['realm'] else: log.info("[authenticate] no realmbox") if '@' in identity['login']: if getSplitAtSign(): log.debug("trying to split the loginname") username, _at_, realm = identity['login'].rpartition('@') else: log.debug("no split for the @ of the loginname") username = identity['login'] realm = identity.get('realm', getDefaultRealm()) else: username = identity['login'] realm = getDefaultRealm() log.info("[authenticate]: username: %r, realm: %r" % (username, realm)) password = identity['password'] except KeyError as e: log.error("[authenticate] Keyerror in identity: %r." % e) log.error("[authenticate] %s" % traceback.format_exc()) return None # as repoze does not run through the std pylons middleware, we have to # convert the input which might be UTF8 to unicode username = str2unicode(username) password = str2unicode(password) # check username/realm, password if isSelfTest(): authUser = "******" % (username, realm) else: authUser = get_authenticated_user(username, realm, password) return authUser
def valid_facets(self, realm=None): """ Show the JSON output for the valid facets configured by the enrollment policy 'u2f_valid_facets'. The form of the JSON output is specified by the FIDO Alliance. """ if realm is None: realm = getDefaultRealm() # Get the valid facets as specified in the enrollment policy 'u2f_valid_facets' # for the specific realm get_policy_params = { 'action': 'u2f_valid_facets', 'scope': 'enrollment', 'realm': realm } valid_facets_action_value = getPolicyActionValue( getPolicy(get_policy_params), 'u2f_valid_facets', is_string=True) # the action value contains the semicolon-separated list of valid facets valid_facets = valid_facets_action_value.split(';') # Prepare the response response.content_type = 'application/fido.trusted-apps+json' # as specified by FIDO response_dict = { "trustedFacets": [{ "version": {"major": 1, "minor": 0}, "ids": [] }] } for facet in valid_facets: facet = facet.strip() response_dict['trustedFacets'][0]['ids'].append(facet) return json.dumps(response_dict)
def valid_facets(self, realm=None): """ Show the JSON output for the valid facets configured by the enrollment policy 'u2f_valid_facets'. The form of the JSON output is specified by the FIDO Alliance. """ if realm is None: realm = getDefaultRealm() # Get the valid facets as specified in the enrollment policy 'u2f_valid_facets' # for the specific realm get_policy_params = { 'action': 'u2f_valid_facets', 'scope': 'enrollment', 'realm': realm } valid_facets_action_value = getPolicyActionValue(getPolicy(get_policy_params), 'u2f_valid_facets', String=True ) # the action value contains the semicolon-separated list of valid facets valid_facets = valid_facets_action_value.split(';') # Prepare the response response.content_type = 'application/fido.trusted-apps+json' # as specified by FIDO response_dict = { "trustedFacets": [{ "version": {"major": 1, "minor": 0}, "ids": [] }] } for facet in valid_facets: facet = facet.strip() response_dict['trustedFacets'][0]['ids'].append(facet) return json.dumps(response_dict)
def login(self): ''' This is the redirect of the first template ''' param = request.params c.defaultRealm = getDefaultRealm() c.p = {} c.user = "" c.title = "LinOTP OpenID Service" for k in param: c.p[k] = param[k] if "openid.claimed_id" == k: c.user = param[k].rsplit("/", 1)[1] ## if we have already a cookie but ## a difference between login and cookie user ## we show (via /status) that he is already logged in ## and that he first must log out cookie = request.cookies.get(COOKIE_NAME) if cookie is not None: cookie_user, token = cookie.split(":") if cookie_user != c.user: c.login = cookie_user c.message = ("Before logging in as >%s< you have to log out." % (c.user)) return render("/openid/status.mako") return render('/openid/login.mako')
def getUserRealms(user): ''' Returns the realms, a user belongs to. If the user has no realm but only a useridresolver, than all realms, containing this resolver are returned. This function is used for the policy module ''' allRealms = getRealms() Realms = [] if user.realm == "" and user.conf == "": defRealm = getDefaultRealm().lower() Realms.append(defRealm) user.realm = defRealm elif user.realm != "": Realms.append(user.realm.lower()) else: # we got a resolver and will get all realms the resolver belongs to. for key, v in allRealms.items(): log.debug("[getUserRealms] evaluating realm %r: %r " % (key, v)) for reso in v['useridresolver']: resotype, resoname = reso.rsplit('.', 1) log.debug("[getUserRealms] found resolver %r of type %r" % (resoname, resotype)) if resoname == user.conf: Realms.append(key.lower()) log.debug("[getUserRealms] added realm %r to Realms due to resolver %r" % (key, user.conf)) return Realms
def smspin(self): ''' This function is used in conjunction with an SMS token: the user authenticates with user and pin (pass) and will receive on his mobile an OTP as message method: validate/smspin arguments: * user: username / loginname * pass: the password that consists of a possible fixed password * realm: additional realm to match the user to a useridresolver returns: JSON response ''' ret = False param = self.request_params state = '' message = 'No sms message defined!' try: user = getUserFromParam(param) g.audit['user'] = user.login g.audit['realm'] = user.realm or getDefaultRealm() g.audit['success'] = 0 (ret, opt) = self._check(param) ## here we build some backward compatibility if type(opt) is dict: state = opt.get('state', '') or '' message = opt.get('message', '') or 'No sms message defined!' # sucessfull submit if (message in ['sms with otp already submitted', 'sms submitted'] and len(state) > 0): ret = True g.audit['success'] = 1 # sending sms failed should be an error elif message in ['sending sms failed']: ret = True g.audit['success'] = 0 # anything else is an exception else: raise Exception(message) db.session.commit() return sendResult(response, ret, opt) except Exception as exx: log.exception("[smspin] validate/smspin failed: %r" % exx) # If an internal error occurs or the SMS gateway did not send # the SMS, we write this to the detail info. g.audit['info'] = str(exx) db.session.rollback() return sendResult(response, False, 0)
def login(self): log.debug("[login] selfservice login screen") identity = request.environ.get('repoze.who.identity') if identity is not None: # After login We always redirect to the start page redirect("/") res = {} try: c.defaultRealm = getDefaultRealm() res = getRealms() c.realmArray = [] #log.debug("[login] %s" % str(res) ) for (k, v) in res.items(): c.realmArray.append(k) c.realmbox = getRealmBox() log.debug("[login] displaying realmbox: %i" % int(c.realmbox)) Session.commit() response.status = '%i Logout from LinOTP selfservice' % LOGIN_CODE return render('/selfservice/login.mako') except Exception as e: log.exception('[login] failed %r' % e) Session.rollback() return sendError(response, e) finally: Session.close()
def _compare_users(self, u1, u2): realm = getDefaultRealm() if len(u1.split('@')) == 1: u1 = "%s@%s" % (u1, realm) if len(u2.split('@')) == 1: u2 = "%s@%s" % (u2, realm) log.debug("[compare_users] %s == %s?" % (u1, u2)) return u1 == u2
def getUserFromParam(param, optionalOrRequired, optional=False, required=False): realm = "" conf = "" if optional: optionalOrRequired = True if required: optionalOrRequired = False log.debug("[getUserFromParam] entering function") user = getParam(param, "user", optionalOrRequired) log.debug("[getUserFromParam] got user <<%r>>" % user) if user is None: user = "" else: splitAtSign = getFromConfig("splitAtSign", "true") if splitAtSign.lower() == "true": (user, realm) = splitUser(user) if "realm" in param: realm = param["realm"] if user != "": if realm is None or realm == "": realm = getDefaultRealm() usr = User(user, realm, "") if "resConf" in param: conf = param["resConf"] # with the short resolvernames, we have to extract the # configuration name from the resolver spec if "(" in conf and ")" in conf: res_conf, resolver_typ = conf.split(" ") conf = res_conf usr.conf = conf else: if len(usr.login) > 0 or len(usr.realm) > 0 or len(usr.conf) > 0: res = getResolversOfUser(usr) usr.saveResolvers(res) if len(res) > 1: log.error("[getUserFromParam] user %r@%r in more than one " "resolver: %r" % (user, realm, res)) raise Exception("The user %s@%s is in more than one resolver:" " %s" % (user, realm, unicode(res))) log.debug("[getUserFromParam] creating user object %r,%r,%r" % (user, realm, conf)) log.debug("[getUserFromParam] created user object %r " % usr) return usr
def get_pre_context(client): """ get the rendering context before the login is shown, so the rendering of the login page could be controlled if realm_box or mfa_login is defined :param client: the rendering is client dependend, so we need the info :return: context dict, with all rendering attributes """ # check for mfa_login, autoassign and autoenroll in policy definition mfa_login_action = get_selfservice_action_value( action="mfa_login", default=False ) mfa_3_fields_action = get_selfservice_action_value( action="mfa_3_fields", default=False ) autoassignment_action = get_selfservice_action_value( action="autoassignment", default=False ) autoenrollment_action = get_selfservice_action_value( action="autoenrollment", default=False ) footer_text_action = get_selfservice_action_value( action="footer_text", default=None ) imprint_url_action = get_selfservice_action_value( action="imprint_url", default=None ) privacy_notice_url_action = get_selfservice_action_value( action="privacy_notice_url", default=None ) return { "version": get_version(), "copyright": get_copyright_info(), "realms": _get_realms_(), "settings": { "default_realm": getDefaultRealm(), "realm_box": getRealmBox(), "mfa_login": mfa_login_action, "mfa_3_fields": mfa_3_fields_action, "autoassign": autoassignment_action, "autoenroll": autoenrollment_action, "footer_text": footer_text_action, "imprint_url": imprint_url_action, "privacy_notice_url": privacy_notice_url_action, }, }
def getUserFromParam(param, optionalOrRequired, optional=False, required=False): realm = "" # TODO: merge result - could this be removed if optional: optionalOrRequired = True if required: optionalOrRequired = False log.debug("[getUserFromParam] entering function") user = getParam(param, "user", optionalOrRequired) log.debug("[getUserFromParam] got user <<%r>>", user) if user is None: user = "" else: splitAtSign = getFromConfig("splitAtSign", "true") if splitAtSign.lower() == "true": (user, realm) = splitUser(user) if "realm" in param: realm = param["realm"] if user != "": if not realm: realm = getDefaultRealm() usr = User(user, realm, "") resolver_config_id = '' if "resConf" in param: resolver_config_identifier = param["resConf"] # with the short resolvernames, we have to extract the # configuration name from the resolver spec if "(" in resolver_config_identifier and \ ")" in resolver_config_identifier: resolver_config_id, __ = resolver_config_identifier.split(" ") usr.resolver_config_identifier = resolver_config_id else: if len(usr.login) > 0 or \ len(usr.realm) > 0 or \ len(usr.resolver_config_identifier) > 0: res = getResolversOfUser(usr) usr.saveResolvers(res) log.debug("[getUserFromParam] creating user object %r,%r,%r", user, realm, resolver_config_id) log.debug("[getUserFromParam] created user object %r ", usr) return usr
def getUserFromParam(param, optionalOrRequired, optional=False, required=False): realm = "" conf = "" if optional: optionalOrRequired = True if required: optionalOrRequired = False log.debug("[getUserFromParam] entering function") user = getParam(param, "user", optionalOrRequired) log.debug("[getUserFromParam] got user <<%r>>" % user) if user is None: user = "" else: splitAtSign = getFromConfig("splitAtSign", "true") if splitAtSign.lower() == "true": (user, realm) = splitUser(user) if "realm" in param: realm = param["realm"] if user != "": if realm is None or realm == "" : realm = getDefaultRealm() usr = User(user, realm, "") if "resConf" in param: conf = param["resConf"] # with the short resolvernames, we have to extract the # configuration name from the resolver spec if "(" in conf and ")" in conf: res_conf, resolver_typ = conf.split(" ") conf = res_conf usr.conf = conf else: if len(usr.login) > 0 or len(usr.realm) > 0 or len(usr.conf) > 0: res = getResolversOfUser(usr) usr.saveResolvers(res) if len(res) > 1: log.error("[getUserFromParam] user %r@%r in more than one " "resolver: %r" % (user, realm, res)) raise Exception("The user %s@%s is in more than one resolver:" " %s" % (user, realm, unicode(res))) log.debug("[getUserFromParam] creating user object %r,%r,%r" % (user, realm, conf)) log.debug("[getUserFromParam] created user object %r " % usr) return usr
def getResolversOfUser(user): ''' getResolversOfUser returns the list of the Resolvers of a user in a given realm. A user can be be in more than one resolver if the login name is the same and if the user has the same id. The usecase behind this constrain is that an user for example could be ldap wise in a group which could be addressed by two queries. :param user: userobject with user.login, user.realm :returns: array of resolvers, the user was found in ''' login = user.login realm = user.realm if not realm: realm = getDefaultRealm() realm = realm.lower() # calling the worker which stores resolver in the cache resolvers = get_resolvers_of_user(login, realm) # -- ------------------------------------------------------------------ -- # below we adjust the legacy stuff and put the resolver info into the user # -- ------------------------------------------------------------------ -- for resolver_spec in resolvers: # this is redundant but cached login, uid, _user_info = lookup_user_in_resolver( login, None, resolver_spec) if not uid: continue try: # we require the resId y = getResolverObject(resolver_spec) resId = y.getResolverId() resCId = resolver_spec except Exception as exx: log.exception("Failed to establish resolver %r: %r", resolver_spec, exx) continue __, config_identifier = parse_resolver_spec(resolver_spec) user.addResolverUId(resolver_spec, uid, config_identifier, resId, resCId) return resolvers
def checkSerialPass(self, serial, passw, options=None, user=None): """ This function checks the otp for a given serial :attention: the parameter user must be set, as the pin policy==1 will verify the user pin """ token_type = options.get("token_type", None) tokenList = getTokens4UserOrSerial(None, serial, token_type=token_type, read_for_update=True) if passw is None: # other than zero or one token should not happen, as serial is # unique if len(tokenList) == 1: theToken = tokenList[0] tok = theToken.token realms = tok.getRealmNames() if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo( tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass, ) user = User(login=userInfo.get("username"), realm=realm) user.info = userInfo if theToken.is_challenge_request(passw, user, options=options): (res, opt) = Challenges.create_challenge(theToken, options) res = False else: raise ParameterError("Missing parameter: pass", id=905) else: raise Exception("No token found: " "unable to create challenge for %s" % serial) else: (res, opt) = self.checkTokenList(tokenList, passw, user=user, options=options) return (res, opt)
def get_pre_context(client): """ get the rendering context before the login is shown, so the rendering of the login page could be controlled if realm_box or mfa_login is defined :param client: the rendering is client dependend, so we need the info :return: context dict, with all rendering attributes """ pre_context = {} pre_context["version"] = get_version() pre_context["licenseinfo"] = get_copyright_info() pre_context["default_realm"] = getDefaultRealm() pre_context["realm_box"] = getRealmBox() pre_context["realms"] = json.dumps(_get_realms_()) # check for mfa_login, autoassign and autoenroll in policy definition pre_context['mfa_login'] = False policy = get_client_policy(client=client, scope='selfservice', action='mfa_login') if policy: pre_context['mfa_login'] = True pre_context['mfa_3_fields'] = False policy = get_client_policy(client=client, scope='selfservice', action='mfa_3_fields') if policy: pre_context['mfa_3_fields'] = True pre_context['autoassign'] = False policy = get_client_policy(client=client, scope='enrollment', action='autoassignment') if policy: pre_context['autoassign'] = True pre_context['autoenroll'] = False policy = get_client_policy(client=client, scope='enrollment', action='autoenrollment') if policy: pre_context['autoenroll'] = True return pre_context
def authenticate(self, environ, identity): log.info("[authenticate] entering repoze authenticate function.") #log.debug( identity ) username = None realm = None success = None try: if isSelfTest(): if identity.has_key('login') == False and identity.has_key( 'repoze.who.plugins.auth_tkt.userid') == True: u = identity.get('repoze.who.plugins.auth_tkt.userid') identity['login'] = u identity['password'] = u if getRealmBox(): username = identity['login'] realm = identity['realm'] else: log.info( "[authenticate] no realmbox, so we are trying to split the loginname" ) m = re.match("(.*)\@(.*)", identity['login']) if m: if 2 == len(m.groups()): username = m.groups()[0] realm = m.groups()[1] log.info( "[authenticate] found @: username: %r, realm: %r" % (username, realm)) else: username = identity['login'] realm = getDefaultRealm() log.info( "[authenticate] using default Realm: username: %r, realm: %r" % (username, realm)) password = identity['password'] except KeyError as e: log.error("[authenticate] Keyerror in identity: %r." % e) log.error("[authenticate] %s" % traceback.format_exc()) return None # check username/realm, password if isSelfTest(): success = "%s@%s" % (unicode(username), unicode(realm)) else: success = check_user_password(username, realm, password) return success
def checkSerialPass(self, serial, passw, options=None, user=None): """ This function checks the otp for a given serial :attention: the parameter user must be set, as the pin policy==1 will verify the user pin """ log.debug('checking for serial %r' % serial) tokenList = linotp.lib.token.getTokens4UserOrSerial(None, serial) if passw is None: # other than zero or one token should not happen, as serial is # unique if len(tokenList) == 1: theToken = tokenList[0] tok = theToken.token realms = tok.getRealmNames() if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo(tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass) user = User(login=userInfo.get('username'), realm=realm) user.info = userInfo if theToken.is_challenge_request(passw, user, options=options): (res, opt) = Challenges.create_challenge(theToken, options) res = False else: raise ParameterError('Missing parameter: pass', id=905) else: raise Exception('No token found: ' 'unable to create challenge for %s' % serial) else: log.debug('checking len(pass)=%r for serial %r' % (len(passw), serial)) (res, opt) = self.checkTokenList(tokenList, passw, user=user, options=options) return (res, opt)
def checkSerialPass(self, serial, passw, options=None, user=None): """ This function checks the otp for a given serial :attention: the parameter user must be set, as the pin policy==1 will verify the user pin """ log.debug('checking for serial %r' % serial) tokenList = linotp.lib.token.getTokens4UserOrSerial( None, serial) if passw is None: # other than zero or one token should not happen, as serial is # unique if len(tokenList) == 1: theToken = tokenList[0] tok = theToken.token realms = tok.getRealmNames() if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo(tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass) user = User(login=userInfo.get('username'), realm=realm) user.info = userInfo if theToken.is_challenge_request(passw, user, options=options): (res, opt) = Challenges.create_challenge( theToken, options) res = False else: raise ParameterError('Missing parameter: pass', id=905) else: raise Exception('No token found: ' 'unable to create challenge for %s' % serial) else: log.debug('checking len(pass)=%r for serial %r' % (len(passw), serial)) (res, opt) = self.checkTokenList( tokenList, passw, user=user, options=options) return (res, opt)
def getRealms(self): """ return all realms in which the user is located :return: list of realms """ if not self.exists(): return [self.realm or getDefaultRealm()] realms = set() for realm, realm_definition in getRealms().items(): if self.resolver in realm_definition['useridresolver']: realms.add(realm) return realms
def login(self): ''' render the selfservice login page ''' c.title = _("LinOTP Self Service Login") # ------------------------------------------------------------------ -- # prepare the realms and put the default realm on the top defaultRealm = getDefaultRealm() realmArray = [defaultRealm] for realm in getRealms(): if realm != defaultRealm: realmArray.append(realm) # ------------------------------------------------------------------ -- # prepare the global context c for the rendering context c.defaultRealm = defaultRealm c.realmArray = realmArray c.realmbox = getRealmBox() context = get_pre_context(c.audit['client']) mfa_login = context['mfa_login'] mfa_3_fields = context['mfa_3_fields'] c.otp = False c.mfa_3_fields = False if mfa_login and mfa_3_fields: c.mfa_3_fields = True response = Response(render('/selfservice/login.mako')) if request.cookies.get('user_selfservice'): remove_auth_cookie(request.cookies.get('user_selfservice')) response.delete_cookie('user_selfservice') return response
def valid_facets(self, realm=None): """ Show the JSON output for the valid facets configured by the enrollment policy 'u2f_valid_facets'. The form of the JSON output is specified by the FIDO Alliance. """ if realm is None: realm = getDefaultRealm() # Get the valid facets as specified in the enrollment policy 'u2f_valid_facets' # for the specific realm get_policy_params = { "action": "u2f_valid_facets", "scope": "enrollment", "realm": realm, } valid_facets_action_value = get_action_value( getPolicy(get_policy_params), scope="enrollment", action="u2f_valid_facets", default="", ) # the action value contains the semicolon-separated list of valid # facets valid_facets = valid_facets_action_value.split(";") # Prepare the response response.content_type = ( "application/fido.trusted-apps+json" # as specified by FIDO ) response_dict = { "trustedFacets": [{ "version": { "major": 1, "minor": 0 }, "ids": [] }] } for facet in valid_facets: facet = facet.strip() response_dict["trustedFacets"][0]["ids"].append(facet) return json.dumps(response_dict)
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 authenticate(self, environ, identity): log.info("[authenticate] entering repoze authenticate function.") #log.debug( identity ) username = None realm = None success = None try: if isSelfTest(): if identity.has_key('login') == False and identity.has_key('repoze.who.plugins.auth_tkt.userid') == True: u = identity.get('repoze.who.plugins.auth_tkt.userid') identity['login'] = u identity['password'] = u if getRealmBox(): username = identity['login'] realm = identity['realm'] else: log.info("[authenticate] no realmbox, so we are trying to split the loginname") m = re.match("(.*)\@(.*)", identity['login']) if m: if 2 == len(m.groups()): username = m.groups()[0] realm = m.groups()[1] log.info("[authenticate] found @: username: %r, realm: %r" % (username, realm)) else: username = identity['login'] realm = getDefaultRealm() log.info("[authenticate] using default Realm: username: %r, realm: %r" % (username, realm)) password = identity['password'] except KeyError as e: log.error("[authenticate] Keyerror in identity: %r." % e) log.error("[authenticate] %s" % traceback.format_exc()) return None # check username/realm, password if isSelfTest(): success = "%s@%s" % (unicode(username), unicode(realm)) else: success = check_user_password(username, realm, password) return success
def get_token_realm_user(self): user = None realms = getTokenRealms(self.getSerial()) if len(realms) == 1: user = User(login='', realm=realms[0]) elif len(realms) == 0: realm = getDefaultRealm() user = User(login='', realm=realm) log.info('No token realm found - using default realm.') else: msg = ('Multiple realms for token found. But one dedicated ' 'realm is required for further processing.') log.error(msg) raise Exception(msg) return user
def get_token_realm_user(self): user = None realms = getTokenRealms(self.getSerial()) if len(realms) == 1: user = User(login="", realm=realms[0]) elif len(realms) == 0: realm = getDefaultRealm() user = User(login="", realm=realm) log.info("No token realm found - using default realm.") else: msg = ("Multiple realms for token found. But one dedicated " "realm is required for further processing.") log.error(msg) raise Exception(msg) return user
def login(self): """ render the selfservice login page """ c.title = _("LinOTP Self Service Login") # ------------------------------------------------------------------ -- # prepare the realms and put the default realm on the top defaultRealm = getDefaultRealm() realmArray = [defaultRealm] for realm in getRealms(): if realm != defaultRealm: realmArray.append(realm) # ------------------------------------------------------------------ -- # prepare the global context c for the rendering context c.defaultRealm = defaultRealm c.realmArray = realmArray c.realmbox = getRealmBox() context = get_pre_context(g.audit["client"]) mfa_login = bool(context["settings"]["mfa_login"]) mfa_3_fields = bool(context["settings"]["mfa_3_fields"]) c.mfa_login = mfa_login c.mfa_3_fields = mfa_login and mfa_3_fields response = Response(render("/selfservice/login.mako")) if request.cookies.get("user_selfservice"): remove_auth_cookie(request.cookies.get("user_selfservice")) response.delete_cookie("user_selfservice") return response
def getUserObject(login, realm=None, check_if_exist=False): f_realm = realm f_login = login if not realm: if '@' in login: realms = getRealms() lo, rea = login.rsplit('@', 1) if rea.lower() in realms: f_realm = rea.lower() f_login = lo else: f_realm = getDefaultRealm() f_login = login f_user = User(f_login, realm=f_realm) if check_if_exist: _uid, _resolver = f_user.get_uid_resolver() return f_user
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 get_pre_context(client, context=None): """ get the rendering context before the login is shown, so the rendering of the login page could be controlled if realm_box or otpLogin is defined :param client: the rendering is client dependend, so we need the info :return: context dict, with all rendering attributes """ pre_context = {} pre_context["version"] = get_version() pre_context["licenseinfo"] = get_copyright_info() pre_context["default_realm"] = getDefaultRealm() pre_context["realm_box"] = getRealmBox() pre_context["realms"] = json.dumps(_get_realms_()) """ check for otpLogin, autoassign and autoenroll in policy definition """ pre_context["otpLogin"] = False policy = get_client_policy(client=client, scope="selfservice", action="otpLogin", context=context) if policy: pre_context["otpLogin"] = True pre_context["autoassign"] = False policy = get_client_policy(client=client, scope="enrollment", action="autoassignment", context=context) if policy: pre_context["autoassign"] = True pre_context["autoenroll"] = False policy = get_client_policy(client=client, scope="enrollment", action="autoenrollment", context=context) if policy: pre_context["autoenroll"] = True return pre_context
def get_pre_context(client): """ get the rendering context before the login is shown, so the rendering of the login page could be controlled if realm_box or mfa_login is defined :param client: the rendering is client dependend, so we need the info :return: context dict, with all rendering attributes """ # check for mfa_login, autoassign and autoenroll in policy definition mfa_login_policy = get_client_policy(client=client, scope='selfservice', action='mfa_login') mfa_3_fields_policy = get_client_policy(client=client, scope='selfservice', action='mfa_3_fields') autoassignment_policy = get_client_policy(client=client, scope='enrollment', action='autoassignment') autoenrollment_policy = get_client_policy(client=client, scope='enrollment', action='autoenrollment') return { "version": get_version(), "copyright": get_copyright_info(), "realms": _get_realms_(), "settings": { "default_realm": getDefaultRealm(), "realm_box": getRealmBox(), "mfa_login": bool(mfa_login_policy), "mfa_3_fields": bool(mfa_3_fields_policy), "autoassign": bool(autoassignment_policy), "autoenroll": bool(autoenrollment_policy), }, }
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() if same_user is True: (ok, opt) = 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.error("[check] openid/check failed: %r" % exx) log.error("[__before__] %s" % traceback.format_exc()) 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_s(self): """ This function is used to validate the serial and the otp value/password. method: validate/check_s arguments: * serial: the serial number of the token * pass: the password that consists of a possible fixes password component and the OTP value returns: JSON response """ param = {} param.update(request.params) options = {} options.update(param) for k in ["user", "serial", "pass", "init"]: if k in options: del options[k] if "init" in param: if isSelfTest() == True: options["initTime"] = param.get("init") try: passw = getParam(param, "pass", optional) serial = getParam(param, "serial", optional) if serial is None: user = getParam(param, "user", optional) if user is not None: user = getUserFromParam(param, optional) toks = getTokens4UserOrSerial(user=user) if len(toks) == 0: raise Exception("No token found!") elif len(toks) > 1: raise Exception("More than one token found!") else: tok = toks[0].token desc = tok.get() realms = desc.get("LinOtp.RealmNames") if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo(tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass) user = User(login=userInfo.get("username"), realm=realm) serial = tok.getSerial() c.audit["serial"] = serial if isSelfTest() == True: initTime = getParam(param, "init", optional) if initTime is not None: if options is None: options = {} options["initTime"] = initTime (ok, opt) = checkSerialPass(serial, passw, options=options) c.audit["success"] = ok Session.commit() qr = getParam(param, "qr", optional) if qr is not None and opt is not None and opt.has_key("message"): try: dataobj = opt.get("message") param["alt"] = "%s" % opt return sendQRImageResult(response, dataobj, param) except Exception as exc: log.warning("failed to send QRImage: %r " % exc) return sendQRImageResult(response, opt, param) else: return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.error("[check_s] validate/check_s failed: %r" % exx) log.error("[check_s] %s" % traceback.format_exc()) c.audit["info"] = unicode(exx) Session.rollback() return sendError(response, "validate/check_s failed: %s" % unicode(exx), 0) finally: Session.close() log.debug("[check_s] done")
def get_authenticated_user(username, realm, password=None, realm_box=False, authenticate=True, options=None): ''' check the username and password against a userstore. remark: the method is called in the context of repoze.who during authentication and during auto_enrollToken/auto_assignToken :param username: the user login name :param realm: the realm, where the user belongs to :param password: the to be checked userstore password :param realm_box: take the information, if realmbox is displayed :parm authenticate: for the selftest, we skip the authentication :return: None or authenticated user object ''' log.info("User %r from realm %r tries to authenticate to selfservice", username, realm) if type(username) != unicode: username = username.decode(ENCODING) # ease the handling of options if not options: options = {} users = [] uid = None # if we have an realmbox, we take the user as it is # - the realm is always given # - appended realms result in error if realm_box: user = User(username, realm, "") users.append(user) # else if no realm box is given # and realm is not empty: # - create the user from the values (as we are in auto_assign, etc) # and the realm is empty! (s. login.mako # - the user either appends his realm # - or will get the realm appended # else: if realm: user = User(username, realm, "") users.append(user) else: def_realm = options.get('defaultRealm', getDefaultRealm()) if def_realm: user = User(username, def_realm, "") users.append(user) if '@' in username: u_name, u_realm = username.rsplit('@', 1) user = User(u_name, u_realm, "") users.append(user) # Authenticate user auth_user = None for user in users: resolvers = [] username = user.login realm = user.realm realm_info = getRealms(user.realm) if realm_info and realm in realm_info: resolvers = realm_info.get(user.realm).get('useridresolver', []) found_uid = None for resolver_spec in resolvers: y = getResolverObject(resolver_spec) if y is None: log.error("[getResolversOfUser] [ module %r not found!]", resolver_spec) continue uid = y.getUserId(user.login) if not uid: log.debug("user %r not in resolver %r.", username, resolver_spec) continue if found_uid and uid != found_uid: raise Exception('user login %r : missmatch for userid: ' '%r:%r', user.login, found_uid, uid) if authenticate: if y.checkPass(uid, password): log.debug("Successfully authenticated user %r.", username) else: log.info("user %r failed to authenticate.", username) if found_uid: raise Exception('previous authenticated user mismatch' ' - password missmatch!') continue # add the fully qualified resolver to the resolver list user.resolvers_list.append(resolver_spec) if not found_uid: found_uid = uid auth_user = user if not auth_user: log.error("Error while trying to verify the username: %s", username) return auth_user
def check_standard(self, passw, user, options=None): """ do a standard verification, as we are not in a challengeResponse mode the upper interfaces expect in the success the otp counter or at least 0 if we have a success. A -1 identifies an error :param passw: the password, which should be checked :param options: dict with additional request parameters :return: tuple of matching otpcounter and a potential reply """ otp_count = -1 pin_match = False reply = None # fallback in case of check_s, which does not provide a user # but as for further prcessing a dummy user with only the realm defined # is required for the policy evaluation if user is None: realms = getTokenRealms(self.getSerial()) if len(realms) == 1: user = User(login='', realm=realms[0]) elif len(realms) == 0: realm = getDefaultRealm() user = User(login='', realm=realm) log.info('No token realm found - using default realm.') else: msg = ('Multiple realms for token found. But one dedicated ' 'realm is required for further processing.') log.error(msg) raise Exception(msg) import linotp.lib.policy support_challenge_response = \ linotp.lib.policy.get_auth_challenge_response(user, self.getType()) if len(self.mode) == 1 and self.mode[0] == "challenge": # the support_challenge_response is overruled, if the token # supports only challenge processing support_challenge_response = True try: # call the token authentication (pin_match, otp_count, reply) = self.authenticate(passw, user, options=options) except Exception as exx: if (support_challenge_response is True and self.is_challenge_request(passw, user, options=options)): log.info("Retry on base of a challenge request:") pin_match = False otp_count = -1 else: log.exception("%r" % exx) raise Exception(exx) if otp_count < 0 or pin_match is False: if (support_challenge_response is True and self.isActive() and self.is_challenge_request(passw, user, options=options)): # we are in createChallenge mode # fix for #12413: # - moved the create_challenge call to the checkTokenList! # after all tokens are processed and only one is challengeing # (_res, reply) = create_challenge(self.token, options=options) self.challenge_token.append(self) if len(self.challenge_token) == 0: if otp_count >= 0: self.valid_token.append(self) elif pin_match is True: self.pin_matching_token.append(self) else: self.invalid_token.append(self) return (otp_count, reply)
def create_context(self, request): """ create the request context for all controllers """ linotp_config = getLinotpConfig() request_context['Config'] = linotp_config request_context['Policies'] = getPolicies() request_context['translate'] = translate initResolvers() request_params = {} try: request_params.update(request.params) except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) request_context['Params'] = request_params authUser = None try: authUser = getUserFromRequest(request) except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) request_context['AuthUser'] = authUser requestUser = None try: requestUser = getUserFromParam(request_params, True) except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) request_context['RequestUser'] = requestUser client = None try: client = get_client(request=request) except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) request_context['Client'] = client request_context['Audit'] = Audit request_context['audit'] = Audit.initialize(request, client=client) defaultRealm = "" try: defaultRealm = getDefaultRealm(linotp_config) except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) request_context['defaultRealm'] = defaultRealm realms = None try: realms = getRealms() except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) request_context['Realms'] = realms request_context['hsm'] = None if hasattr(self, "hsm"): request_context['hsm'] = self.hsm # copy some system entries from pylons syskeys = { "radius.nas_identifier": "LinOTP", "radius.dictfile": "/etc/linotp2/dictionary" } sysconfig = {} for key, default in syskeys.items(): try: sysconfig[key] = config.get(key, default) except: log.info('no sytem config entry %s' % key) request_context['SystemConfig'] = sysconfig
def check_t(self): param = {} value = {} ok = False opt = None try: param.update(request.params) passw = getParam(param, "pass", required) transid = param.get('state', None) if transid is not None: param['transactionid'] = transid del param['state'] if transid is None: transid = param.get('transactionid', None) if transid is None: raise Exception("missing parameter: state or transactionid!") serial = get_tokenserial_of_transaction(transId=transid) if serial is None: value['value'] = False value['failure'] = 'No challenge for transaction %r found'\ % transid else: param['serial'] = serial tokens = getTokens4UserOrSerial(serial=serial) if len(tokens) == 0 or len(tokens) > 1: raise Exception('tokenmismatch for token serial: %s' % (unicode(serial))) theToken = tokens[0] tok = theToken.token realms = tok.getRealmNames() if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo(tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass) user = User(login=userInfo.get('username'), realm=realm) (ok, opt) = checkSerialPass(serial, passw, user=user, options=param) value['value'] = ok failcount = theToken.getFailCount() value['failcount'] = int(failcount) c.audit['success'] = ok #c.audit['info'] += "%s=%s, " % (k, value) Session.commit() qr = getParam(param, 'qr', optional) if qr is not None and opt is not None and opt.has_key('message'): try: dataobj = opt.get('message') param['alt'] = "%s" % opt return sendQRImageResult(response, dataobj, param) except Exception as exc: log.warning("failed to send QRImage: %r " % exc) return sendQRImageResult(response, opt, param) else: return sendResult(response, value, 1, opt=opt) except Exception as exx: log.error("[check_t] validate/check_t failed: %r" % exx) log.error("[check_t] %s" % traceback.format_exc()) c.audit['info'] = unicode(exx) Session.rollback() return sendError(response, "validate/check_t failed: %s" % unicode(exx), 0) finally: Session.close() log.debug('[check_t] done')
def check_s(self): ''' This function is used to validate the serial and the otp value/password. method: validate/check_s arguments: * serial: the serial number of the token * pass: the password that consists of a possible fixes password component and the OTP value returns: JSON response ''' param = self.request_params options = {} options.update(param) for k in ['user', 'serial', "pass", "init"]: if k in options: del options[k] if 'init' in param: if isSelfTest() is True: options['initTime'] = param.get('init') try: passw = param.get("pass") serial = param.get('serial') if serial is None: user = param.get('user') if user is not None: user = getUserFromParam(param) toks = getTokens4UserOrSerial(user=user) if len(toks) == 0: raise Exception("No token found!") elif len(toks) > 1: raise Exception("More than one token found!") else: tok = toks[0].token desc = tok.get() realms = desc.get('LinOtp.RealmNames') if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo(tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass) user = User(login=userInfo.get('username'), realm=realm) serial = tok.getSerial() c.audit['serial'] = serial if isSelfTest() is True: initTime = param.get("init") if initTime is not None: if options is None: options = {} options['initTime'] = initTime options['scope'] = {"check_s": True} vh = ValidationHandler() (ok, opt) = vh.checkSerialPass(serial, passw, options=options) c.audit['success'] = ok Session.commit() qr = param.get('qr', None) if qr and opt and 'message' in opt: try: dataobj = opt.get('message') param['alt'] = "%s" % opt if 'transactionid' in opt: param['transactionid'] = opt['transactionid'] return sendQRImageResult(response, dataobj, param) except Exception as exc: log.warning("failed to send QRImage: %r " % exc) return sendQRImageResult(response, opt, param) else: return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("[check_s] validate/check_s failed: %r" % exx) c.audit['info'] = unicode(exx) Session.rollback() return sendResult(response, False, id=0, status=False) finally: Session.close()
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 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 = param.get("pass") user = getUserFromParam(param) # support for ocra application challenge verification challenge = param.get("challenge") 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() is True: initTime = param.get("init") if initTime is not None: if options is None: options = {} options['initTime'] = initTime vh = ValidationHandler() (ok, opt) = vh.checkUserPass(user, passw, options=options) c.audit.update(request_context.get('audit')) 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 is 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) ''' 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() is True: initTime = getParam(param, "init", optional) if initTime is not None: if options is None: options = {} options['initTime'] = initTime vh = ValidationHandler() (ok, opt) = vh.checkUserPass(user, passw, options=options) c.audit.update(request_context.get('audit')) 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 is 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 getResolversOfUser(user, use_default_realm=True, allRealms=None, defaultRealm=None): ''' This returns the list of the Resolvers of a user in a given realm. Usually this should only return one resolver input: user.login, user.realm returns: array of resolvers, the user was found in ''' login = user.login realm = user.realm if not defaultRealm: defaultRealm = getDefaultRealm() Resolvers = user.getResolvers() if len(Resolvers) > 0: return Resolvers if not login: return Resolvers if realm is None or realm == "": if use_default_realm: realm = defaultRealm if not allRealms: allRealms = getRealms() realms = allRealms if user.resolver_config_identifier != "": resolver_spec = find_resolver_spec_for_config_identifier(realms, user.resolver_config_identifier) if resolver_spec is not None: Resolvers.append(resolver_spec) else: Realm_resolvers = getResolvers(User("", realm, "")) log.debug("[getResolversOfUser] check if user %r is in resolver %r" % (login, Realm_resolvers)) # Search for user in each resolver in the realm_ for resolver_spec in Realm_resolvers: log.debug("[getResolversOfUser] checking in %r" % resolver_spec) y = getResolverObject(resolver_spec) if y is None: log.error('[getResolversOfUser] [resolver with spec %r ' 'not found!]' % (resolver_spec)) try: log.debug("[getResolversOfUser] checking in module %r" % y) uid = y.getUserId(login) log.debug("[getResolversOfUser] type of uid: %s" % type(uid)) log.debug("[getResolversOfUser] type of resolver_spec: %s" % type(resolver_spec)) log.debug("[getResolversOfUser] type of login: %s" % type(login)) if uid not in ["", None]: log.info("[getResolversOfUser] user %r found in resolver %r" % (login, resolver_spec)) log.info("[getResolversOfUser] userid resolved to %r " % uid) # Unicode Madness: # This will break as soon as the unicode "uid" is put into a tuple # v = (login, realm_resolver, uid) # log.info("[getResolversOfUser] %s %s %s" % v) resId = y.getResolverId(); resCId = resolver_spec Resolvers.append(resolver_spec) __, config_identifier = parse_resolver_spec(resolver_spec) user.addResolverUId(resolver_spec, uid, config_identifier, resId, resCId) else: log.debug("[getResolversOfUser] user %r not found" " in resolver %r" % (login, resolver_spec)) except Exception as e: log.exception('[getResolversOfUser] error searching user in ' 'resolver with spec %r:%r' % (resolver_spec, e)) log.debug("[getResolversOfUser] Resolvers: %r" % Resolvers) log.debug("[getResolversOfUser] Found the user %r in %r" % (login, Resolvers)) return Resolvers
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() vh = ValidationHandler() if same_user is True: (ok, opt) = vh.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 get_authenticated_user(username, realm, password=None, realm_box=False, authenticate=True, options=None): ''' check the username and password against a userstore. remark: the method is called in the context of repoze.who during authentication and during auto_enrollToken/auto_assignToken :param username: the user login name :param realm: the realm, where the user belongs to :param password: the to be checked userstore password :param realm_box: take the information, if realmbox is displayed :parm authenticate: for the selftest, we skip the authentication :return: None or authenticated user object ''' log.info("User %r from realm %r tries to authenticate to selfservice" % (username, realm)) if type(username) != unicode: username = username.decode(ENCODING) # ease the handling of options if not options: options = {} users = [] uid = None resolver = None resolverC = None # if we have an realmbox, we take the user as it is # - the realm is always given # - appended realms result in error if realm_box: user = User(username, realm, "") users.append(user) # else if no realm box is given # and realm is not empty: # - create the user from the values (as we are in auto_assign, etc) # and the realm is empty! (s. login.mako # - the user either appends his realm # - or will get the realm appended # else: if realm: user = User(username, realm, "") users.append(user) else: def_realm = options.get('defaultRealm', getDefaultRealm()) if def_realm: user = User(username, def_realm, "") users.append(user) if '@' in username: u_name, u_realm = username.rsplit('@', 1) user = User(u_name, u_realm, "") users.append(user) identified_users = [] for user in users: username = user.login realm = user.realm res = getResolversOfUser(user, use_default_realm=False) if not res: log.info("The username %r exists in NO resolver within the " "realm %r.", username, realm) continue # fill in the set of resolvers getUserId(user) for resolverClass, uid in user.resolverUid.items(): identified_users.append((user, uid, resolverClass, resolverClass)) log.info("the user resolves to %r", uid) log.info("The username is found within the resolver %r", resolver) if not identified_users: log.info("The username %s could not be found." % username) return None if not authenticate: (user, uid, resolver, resolverC) = identified_users[0] return user # Authenticate user auth_user = None for identified_user in identified_users: (user, uid, resolver, resolverC) = identified_user try: y = getResolverObject(resolverC) if y.checkPass(uid, password): # we stop with the first successful authenticated user log.debug("Successfully authenticated user %r.", username) auth_user = user break else: log.info("user %r failed to authenticate.", username) except UserError as exx: log.info("failed to verify the username: %s@%s: %r", user.login, user.realm, exx) if not auth_user: log.error("Error while trying to verify the username: %s", username) return auth_user
def create_context(self, request, environment): """ create the request context for all controllers """ linotp_config = getLinotpConfig() request_context['Config'] = linotp_config request_context['Policies'] = parse_policies(linotp_config) request_context['translate'] = translate request_context['CacheManager'] = environment['beaker.cache'] initResolvers() request_params = {} try: request_params.update(request.params) except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r" % exx) request_context['Params'] = request_params authUser = None try: authUser = getUserFromRequest(request) except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r" % exx) request_context['AuthUser'] = authUser request_context['UserLookup'] = {} requestUser = None try: requestUser = getUserFromParam(request_params) except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r" % exx) request_context['RequestUser'] = requestUser client = None try: client = get_client(request=request) except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r" % exx) request_context['Client'] = client request_context['Audit'] = Audit request_context['audit'] = Audit.initialize(request, client=client) defaultRealm = "" try: defaultRealm = getDefaultRealm(linotp_config) except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r" % exx) request_context['defaultRealm'] = defaultRealm realms = None try: realms = getRealms() except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r" % exx) request_context['Realms'] = realms request_context['hsm'] = None if hasattr(self, "hsm"): request_context['hsm'] = self.hsm # copy some system entries from pylons syskeys = { "radius.nas_identifier": "LinOTP", "radius.dictfile": "/etc/linotp2/dictionary" } sysconfig = {} for key, default in syskeys.items(): sysconfig[key] = config.get(key, default) request_context['SystemConfig'] = sysconfig
def getResolversOfUser(user): ''' This returns the list of the Resolvers of a user in a given realm. Usually this should only return one resolver input: user.login, user.realm returns: array of resolvers, the user was found in ''' login = user.login realm = user.realm Resolvers = user.getResolvers() if len(Resolvers) > 0: return Resolvers if realm is None or realm == "": realm = getDefaultRealm() #if realm is None or realm=="" or login is None or login == "": # log.error("[getResolversOfUser] You need to specify the name ( %s) and the realm (%s) of a user with conf %s" % (login, realm, user.conf)) realms = getRealms(); if user.conf != "": reso = getConf(realms, user.conf) if len(reso) > 0: Resolvers.append(reso) else: Realm_resolvers = getResolvers(User("", realm, "")) log.debug("[getResolversOfUser] check if user %r is in resolver %r" % (login, Realm_resolvers)) # Search for user in each resolver in the realm_ for realm_resolver in Realm_resolvers: log.debug("[getResolversOfUser] checking in %r" % realm_resolver) (package, module, class_, conf) = splitResolver(realm_resolver) module = package + "." + module y = getResolverObject(realm_resolver) if y is None: log.error("[getResolversOfUser] [ module %r not found!]" % (module)) try: log.debug("[getResolversOfUser] checking in module %r" % y) uid = y.getUserId(login) log.debug("[getResolversOfUser] type of uid: %s" % type(uid)) log.debug("[getResolversOfUser] type of realm_resolver: %s" % type(realm_resolver)) log.debug("[getResolversOfUser] type of login: %s" % type(login)) if uid not in ["", None]: log.debug("[getResolversOfUser] user %r found in resolver %r" % (login, realm_resolver)) log.debug("[getResolversOfUser] userid resolved to %r " % uid) ## Unicode Madness: ## This will break as soon as the unicode "uid" is put into a tuple ## v = (login, realm_resolver, uid) ## log.info("[getResolversOfUser] %s %s %s" % v) resId = y.getResolverId(); resCId = realm_resolver Resolvers.append(realm_resolver) user.addResolverUId(realm_resolver, uid, conf, resId, resCId) else: log.debug("[getResolversOfUser] user %r not found" " in resolver %r" % (login, realm_resolver)) except Exception as e: log.error("[getResolversOfUser] error searching user in" " module %r:%r" % (module, e)) log.error("[getResolversOfUser] %s" % traceback.format_exc()) log.debug("[getResolversOfUser] Resolvers: %r" % Resolvers) log.debug("[getResolversOfUser] Found the user %r in %r" % (login, Resolvers)) return Resolvers
def check_s(self): ''' This function is used to validate the serial and the otp value/password. method: validate/check_s arguments: * serial: the serial number of the token * pass: the password that consists of a possible fixes password component and the OTP value returns: JSON response ''' param = {} param.update(request.params) options = {} options.update(param) for k in ['user', 'serial', "pass", "init"]: if k in options: del options[k] if 'init' in param: if isSelfTest() is True: options['initTime'] = param.get('init') try: passw = getParam(param, "pass", optional) serial = getParam(param, 'serial', optional) if serial is None: user = getParam(param, 'user', optional) if user is not None: user = getUserFromParam(param, optional) toks = getTokens4UserOrSerial(user=user) if len(toks) == 0: raise Exception("No token found!") elif len(toks) > 1: raise Exception("More than one token found!") else: tok = toks[0].token desc = tok.get() realms = desc.get('LinOtp.RealmNames') if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo(tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass) user = User(login=userInfo.get('username'), realm=realm) serial = tok.getSerial() c.audit['serial'] = serial if isSelfTest() is True: initTime = getParam(param, "init", optional) if initTime is not None: if options is None: options = {} options['initTime'] = initTime options['scope'] = {"check_s": True} vh = ValidationHandler() (ok, opt) = vh.checkSerialPass(serial, passw, options=options) c.audit['success'] = ok Session.commit() qr = param.get('qr', None) if qr and opt and 'message' in opt: try: dataobj = opt.get('message') param['alt'] = "%s" % opt if 'transactionid' in opt: param['transactionid'] = opt['transactionid'] return sendQRImageResult(response, dataobj, param) except Exception as exc: log.warning("failed to send QRImage: %r " % exc) return sendQRImageResult(response, opt, param) else: return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("[check_s] validate/check_s failed: %r" % exx) c.audit['info'] = unicode(exx) Session.rollback() return sendResult(response, False, id=0, status=False) finally: Session.close() log.debug('[check_s] done')
def check_t(self): """ method: ocra/check_t description: verify the response of the ocra token arguments: * transactionid: (required - string) Dies ist eine Transaktions-ID, die bei der Challenge ausgegeben wurde. * pass: (required - string) die response, die der OCRA Token auf Grund der Challenge berechnet hat returns: A JSON response:: { "version": "LinOTP 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": { "failcount" : 3, "result": false } }, "id": 0 } exception: """ res = {} description = 'ocra/check_t: validate a token request.' try: param = getLowerParams(request.params) log.info("[check_t] check OCRA token: %r" % param) #checkPolicyPre('ocra', "check_t") passw = getParam(param, 'pass' , optional) if passw is None: ## raise exception''' log.exception("[check_t] missing pass ") raise ParameterError("Usage: %s Missing parameter 'pass'." % description, id=77) transid = getParam(param, 'transactionid', optional) if transid is None: ## raise exception''' log.exception("[check_t] missing transactionid, user or serial number of token") raise ParameterError("Usage: %s Missing parameter 'transactionid'." % description, id=77) ## if we have a transaction, get serial from this challenge value = {} ocraChallenge = OcraTokenClass.getTransaction(transid) if ocraChallenge is not None: serial = ocraChallenge.tokenserial tokens = getTokens4UserOrSerial(serial=serial) if len(tokens) == 0 or len(tokens) > 1: raise Exception('tokenmismatch for token serial: %s' % (unicode(serial))) theToken = tokens[0] tok = theToken.token desc = tok.get() realms = desc.get('LinOtp.RealmNames') if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo(tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass) user = User(login=userInfo.get('username'), realm=realm) vh = ValidationHandler() (ok, opt) = vh.checkSerialPass(serial, passw, user=user, options={'transactionid': transid}) failcount = theToken.getFailCount() value['result'] = ok value['failcount'] = int(failcount) else: ## no challenge found for this transid value['result'] = False value['failure'] = 'No challenge for transaction %r found'\ % transid c.audit['success'] = res #c.audit['info'] += "%s=%s, " % (k, value) Session.commit() return sendResult(response, value, 1) except Exception as e : log.exception("[check_t] failed: %r" % e) Session.rollback() return sendResult(response, unicode(e), 0) finally: Session.close() log.debug("[check_t] done")
def check_standard(self, passw, user, options=None): """ do a standard verification, as we are not in a challengeResponse mode the upper interfaces expect in the success the otp counter or at least 0 if we have a success. A -1 identifies an error :param passw: the password, which should be checked :param options: dict with additional request parameters :return: tuple of matching otpcounter and a potential reply """ otp_count = -1 pin_match = False reply = None # fallback in case of check_s, which does not provide a user # but as for further prcessing a dummy user with only the realm defined # is required for the policy evaluation if user is None: realms = getTokenRealms(self.getSerial()) if len(realms) == 1: user = User(login="", realm=realms[0]) elif len(realms) == 0: realm = getDefaultRealm() user = User(login="", realm=realm) log.info("No token realm found - using default realm.") else: msg = ("Multiple realms for token found. But one dedicated " "realm is required for further processing.") log.error(msg) raise Exception(msg) import linotp.lib.policy support_challenge_response = ( linotp.lib.policy.get_auth_challenge_response( user, self.getType())) if len(self.mode) == 1 and self.mode[0] == "challenge": # the support_challenge_response is overruled, if the token # supports only challenge processing support_challenge_response = True try: # call the token authentication (pin_match, otp_count, reply) = self.authenticate(passw, user, options=options) except Exception as exx: if (support_challenge_response is True and self.is_challenge_request(passw, user, options=options)): log.info("Retry on base of a challenge request:") pin_match = False otp_count = -1 else: log.error(exx) raise if otp_count < 0 or pin_match is False: if (support_challenge_response is True and self.isActive() and self.is_challenge_request(passw, user, options=options)): # we are in createChallenge mode # fix for #12413: # - moved the create_challenge call to the checkTokenList! # after all tokens are processed and only one is challengeing # (_res, reply) = create_challenge(self.token, options=options) self.challenge_token.append(self) if len(self.challenge_token) == 0: if otp_count >= 0: self.valid_token.append(self) elif pin_match is True: self.pin_matching_token.append(self) else: self.invalid_token.append(self) return (otp_count, reply)
def smspin(self): ''' This function is used in conjunction with an SMS token: the user authenticates with user and pin (pass) and will receive on his mobile an OTP as message method: validate/smspin arguments: * user: username / loginname * pass: the password that consists of a possible fixed password * realm: additional realm to match the user to a useridresolver returns: JSON response ''' ret = False param = request.params state = '' message = 'No sms message defined!' try: user = getUserFromParam(param, optional) c.audit['user'] = user.login c.audit['realm'] = user.realm or getDefaultRealm() c.audit['success'] = 0 (ret, opt) = self._check(param) ## here we build some backward compatibility if type(opt) is dict: state = opt.get('state', '') or '' message = opt.get('message', '') or 'No sms message defined!' # sucessfull submit if (message in ['sms with otp already submitted', 'sms submitted'] and len(state) > 0): ret = True c.audit['success'] = 1 # sending sms failed should be an error elif message in ['sending sms failed']: ret = True c.audit['success'] = 0 # anything else is an exception else: raise Exception(message) Session.commit() return sendResult(response, ret, opt) except Exception as exx: log.exception("[smspin] validate/smspin failed: %r" % exx) # If an internal error occurs or the SMS gateway did not send # the SMS, we write this to the detail info. c.audit['info'] = unicode(exx) Session.rollback() return sendResult(response, False, 0) finally: Session.close() log.debug("[smspin] done")