def getUserId(user, check_existance=False): """ getUserId (userObject) :param user: user object :return: (uid,resId,resIdC) """ uid = None resId = '' uids = set() resolvers = getResolversOfUser(user) for resolver_spec in resolvers: _login, uid, _user_info = lookup_user_in_resolver( user.login, None, resolver_spec) if not uid: continue y = getResolverObject(resolver_spec) resId = y.getResolverId() if check_existance: uinfo = y.getUserInfo(uid) if not uinfo: uid = None if not uid: continue uids.add(uid) user.resolverUid[resolver_spec] = uid if not uid: log.warning("No uid found for the user >%r< in realm %r" % (user.login, user.realm)) raise UserError("getUserId failed: no user >%s< found!" % user.login, id=1205) if len(uids) > 1: log.warning("multiple uid s found for the user >%r< in realm %r" % (user.login, user.realm)) raise UserError( "getUserId failed: multiple uids for user >%s< found!" % user.login, id=1205) log.debug("we are done!") return (uid, resId, resolver_spec)
def getUserResolverId(user, report=False): # here we call the userid resolver!!" log.debug('getUserResolverId for %r', user) (uuserid, uidResolver, uidResolverClass) = (u'', u'', u'') if (user is not None and user.isEmpty() is not True): try: (uuserid, uidResolver, uidResolverClass) = getUserId(user) except Exception as e: log.exception('[getUserResolverId] for %r@%r failed: %r' % (user.login, user.realm, e)) if report is True: raise UserError("getUserResolverId failed: %r" % e, id=1112) return (uuserid, uidResolver, uidResolverClass)
def getUserId(user, resolvers=None): """ getUserId (userObject) return (uid,resId,resIdC) """ uid = '' loginUser = user.login if not resolvers: resolvers = getResolversOfUser(user) for resolver_spec in resolvers: resId = "" resIdC = "" uid = user.getResolverUId(resolver_spec) if uid != '': (resId, resIdC, _conf) = user.getResolverConf(resolver_spec) break cls_identifier, config_identifier = parse_resolver_spec(resolver_spec) if user.resolver_config_identifier: lower_config_id = user.resolver_config_identifier.lower() if config_identifier.lower() != lower_config_id: continue # try to load the UserIdResolver Class try: log.debug('[getUserId] Getting resolver class: [%s]', cls_identifier) y = getResolverObject(resolver_spec) log.debug("[getUserId] Getting UserID for user %r", loginUser) uid = y.getUserId(loginUser) log.debug("[getUserId] Got UserId for user %r: %r", loginUser, uid) log.debug("[getUserId] Retrieving ResolverID...") resId = y.getResolverId() resIdC = resolver_spec log.debug("[getUserId] Got ResolverID: %r, Loginuser: %r, " "Uid: %r ]", resId, loginUser, uid) if uid != "": break except Exception as exx: log.exception("[getUserId] resolver class identifier %s: %r ]", cls_identifier, exx) continue if (uid == ''): log.warning("[getUserId] No uid found for the user >%r< in realm %r" % (loginUser, user.realm)) raise UserError("getUserId failed: no user >%s< found!" % unicode(loginUser), id=1205) log.debug("[getUserId] we are done!") return (unicode(uid), unicode(resId), unicode(resIdC))
def finish_valid_tokens(self): """ processing of the valid tokens """ valid_tokens = self.valid_tokens validation_results = self.validation_results user = self.user if len(valid_tokens) == 1: token = valid_tokens[0] if user: action_detail = ("user %r@%r successfully authenticated." % (user.login, user.realm)) else: action_detail = ("serial %r successfully authenticated." % token.getSerial()) log.info(action_detail) # there could be a match in the window ahead, # so we need the last valid counter here (counter, _reply) = validation_results[token.getSerial()] token.setOtpCount(counter + 1) token.statusValidationSuccess() # finish as well related open challenges Challenges.finish_challenges(token, success=True) if token.getFromTokenInfo('count_auth_success_max', default=None): auth_count = token.get_count_auth_success() token.set_count_auth_success(auth_count + 1) detail = None auth_info = self.options.get('auth_info', 'False') if auth_info.lower() == "true": detail = token.getAuthDetail() # 1. check if token supports offline at all supports_offline_at_all = token.supports_offline_mode # 2. check if policy allows to use offline authentication if user is not None and user.login and user.realm: realms = [user.realm] else: realms = token.getRealms() offline_is_allowed = supports_offline(realms, token) # 3. check if parameter 'use_offline' is provided use_offline_param = self.options.get('use_offline', 'False') use_offline = use_offline_param.lower() == 'true' if supports_offline_at_all and \ offline_is_allowed and \ use_offline: offline_info = token.getOfflineInfo() if detail is None: detail = {} offline = {'serial': token.getSerial(), 'type': token.type} offline['offline_info'] = offline_info detail.update({'offline': offline}) return (True, detail, action_detail) else: # we have to set the matching counter to prevent replay one one # single token for token in valid_tokens: (res, _reply) = validation_results[token.getSerial()] token.setOtpCount(res) context['audit']['action_detail'] = "Multiple valid tokens found!" if user: log.error( "[__checkTokenList] multiple token match error: " "Several Tokens matching with the same OTP PIN " "and OTP for user %r. Not sure how to auth", user.login) raise UserError("multiple token match error", id=-33)
def getUserId(user): """ getUserId (userObject) return (uid,resId,resIdC) """ uid = '' loginUser = u'' loginUser = user.login; resolvers = ''; realms = getRealms(); # Get the first resolver they're present in, because UID is independent of realm. for key, v in realms.items(): resolvers = getResolversOfUser(User(user.login, v['realmname'], "")) if (resolvers): break; for reso in resolvers: resId = "" resIdC = "" conf = "" uid = user.getResolverUId(reso) if uid != '': (resId, resIdC, conf) = user.getResolverConf(reso) break (package, module, class_, conf) = splitResolver(reso) if len(user.conf) > 0: if conf.lower() != user.conf.lower(): continue ## try to load the UserIdResolver Class try: module = package + "." + module log.debug("[getUserId] Getting resolver class: [%r] [%r]" % (module, class_)) y = getResolverObject(reso) log.debug("[getUserId] Getting UserID for user %r" % loginUser) uid = y.getUserId(loginUser) log.debug("[getUserId] Got UserId for user %r: %r" % (loginUser, uid)) log.debug("[getUserId] Retrieving ResolverID...") resId = y.getResolverId() resIdC = reso log.debug("[getUserId] Got ResolverID: %r, Loginuser: %r, " "Uid: %r ]" % (resId, loginUser, uid)) if uid != "": break; except Exception as e: log.error("[getUserId] module %r: %r ]" % (module, e)) continue if (uid == ''): log.warning("[getUserId] No uid found for the user >%r< in realm %r" % (loginUser, user.realm)) raise UserError(u"getUserId failed: no user >%s< found!" % unicode(loginUser), id=1205) log.debug("[getUserId] we are done!") return (unicode(uid), unicode(resId), unicode(resIdC))
def request(self): """ method: ocra/request description: request a challenge for a user or for a serial number (token). arguments: * serial: (required - string) Serial number of the token, for which a challenge should be generated (either serial or user is required) * user: (required - string) The user for whose token a challenge should be generated If the user has more than one token, an error is returend. (either serial or user is required) * data: (required - String: URLendoced) These are the display data, that can be used to generate the challenge remark: the app will report a wrong qrcode, if the policy:: {'authentication' : qrtanurl=https://localhost } is not defined !! returns: A JSON respone:: { "version": "LinOTP 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": false, }, "detail": { "transactionid" : TRANSAKTIONSID, "data" : DATAOBJECT, } } * transactionid: This is the transaction ID, that is used later for verifying the Return code /TAN. * data: This is an object (URL) which can be used to generate a QR-Code to be displayed to the QRTAN App """ res = {} description = ('ocra/request: request a challenge for a given user or' ' token (serial). You must either provide a parameter ' '"user" or a parameter "serial".') dataobj = "" try: param = getLowerParams(request.params) log.info("[request] saving default configuration: %r" % param) checkPolicyPre('ocra', "request") serial = param.get('serial') user = getUserFromParam(param) if user.is_empty and serial is None: log.exception("[request] user or serial is required") raise ParameterError("Usage: %s" % description, id=77) if not serial: if not user.exists(): raise UserError("getUserId failed: no user >%s< found!" % user.login, id=1205) message = param.get('data') if message is None: message = '' # ocra token tokens = getTokens4UserOrSerial(user, serial) if len(tokens) > 1: error = ('More than one token found: unable to create ' 'challenge for (u:%r,s:%r)!' % (user, serial)) raise Exception(error) if len(tokens) == 0: error = ('No token found: unable to create challenge for' ' (u:%r,s:%r)!' % (user, serial)) raise Exception(error) ocra = tokens[0] (transId, challenge, res, url) = ocra.challenge(message) u = urlencode({'u': str(url.encode("utf-8"))}) uInfo = {'tr': transId, 'ch': challenge, 'me': str(message.encode("utf-8")), 'u': u[2:]} detail = {"transactionid": transId, 'challenge': challenge, 'message': str(message.encode("utf-8")), 'url': str(url.encode("utf-8")), } # create the app_url from the data dataobj = 'lseqr://req?%s' % (str(urlencode(uInfo))) # append the signature to the url signature = {'si': ocra.signData(dataobj)} uInfo['si'] = signature dataobj = '%s&%s' % (dataobj, str(urlencode(signature))) detail["data"] = dataobj c.audit['success'] = res Session.commit() qr = param.get('qr') if qr is not None: param['alt'] = detail return sendQRImageResult(response, dataobj, param) else: return sendResult(response, res, 1, opt=detail) except PolicyException as pe: log.exception("[request] policy failed: %r" % pe) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.exception("[request] failed: %r" % exx) Session.rollback() return sendError(response, unicode(exx)) finally: Session.close()
def finish_valid_tokens(self): """ processing of the valid tokens """ valid_tokens = self.valid_tokens validation_results = self.validation_results user = self.user if len(valid_tokens) == 1: token = valid_tokens[0] if user: action_detail = "user %r@%r successfully authenticated." % ( user.login, user.realm, ) else: action_detail = ("serial %r successfully authenticated." % token.getSerial()) log.info(action_detail) # there could be a match in the window ahead, # so we need the last valid counter here (counter, _reply) = validation_results[token.getSerial()] token.setOtpCount(counter + 1) token.statusValidationSuccess() # finish as well related open challenges Challenges.finish_challenges(token, success=True) if token.count_auth_success_max > 0: token.inc_count_auth_success() if token.count_auth_max > 0: token.inc_count_auth() detail = None auth_info = self.options.get("auth_info", "False") if auth_info.lower() == "true": detail = token.getAuthDetail() # 1. check if token supports offline at all supports_offline_at_all = token.supports_offline_mode # 2. check if policy allows to use offline authentication if user is not None and user.login and user.realm: realms = [user.realm] else: realms = token.getRealms() offline_is_allowed = supports_offline(realms, token) # 3. check if parameter 'use_offline' is provided use_offline_param = self.options.get("use_offline", "False") use_offline = use_offline_param.lower() == "true" if supports_offline_at_all and offline_is_allowed and use_offline: offline_info = token.getOfflineInfo() if detail is None: detail = {} offline = {"serial": token.getSerial(), "type": token.type} offline["offline_info"] = offline_info detail.update({"offline": offline}) janitor_to_remove_enrollment_token(valid_tokens=[token]) return (True, detail, action_detail) else: # we have to set the matching counter to prevent replay one one # single token for token in valid_tokens: (res, _reply) = validation_results[token.getSerial()] token.setOtpCount(res) # in case of multiple matches the tokens were accessed # so we count them as well if token.count_auth_max > 0: token.inc_count_auth() janitor_to_remove_enrollment_token(valid_tokens=valid_tokens) g.audit["action_detail"] = "Multiple valid tokens found!" if user: log.error( "multiple token match error: " "Several Tokens matching with the same OTP PIN " "and OTP for user %r. Not sure how to auth", user.login, ) raise UserError("multiple token match error", id=-33)