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 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 pair(self): try: params = dict(**request.params) enc_response = params.get('pairing_response') if enc_response is None: raise Exception('Parameter missing') dec_response = decrypt_pairing_response(enc_response) if not dec_response.serial: raise ValidateError( 'Pairing responses with no serial attached ' 'are currently not implemented.') serial = dec_response.serial user_public_key = dec_response.user_public_key user_token_id = dec_response.user_token_id user = dec_response.user_login user = getUserFromParam(params, optional) # TODO: pairing policy tokens = getTokens4UserOrSerial(None, serial) if not tokens: raise Exception('Invalid serial in pairing response') if len(tokens) > 1: raise Exception('Multiple tokens found. Pairing not possible') token = tokens[0] if token.type != 'qr': raise Exception('Pairing is only implemented for the qrtoken') token.ensure_state('pairing_url_sent') token.addToTokenInfo('user_token_id', user_token_id) b64_user_public_key = b64encode(user_public_key) token.addToTokenInfo('user_public_key', b64_user_public_key) params['serial'] = serial params['user_public_key'] = user_public_key params['user_token_id'] = user_token_id params['user'] = user params['content_type'] = CONTENT_TYPE_PAIRING params['data'] = serial token.change_state('pairing_response_received') Session.commit() return sendResult(response, False) except Exception: Session.rollback() return sendResult(response, False, 0, status=False) finally: Session.close()
def pair(self): try: params = dict(**request.params) enc_response = params.get('pairing_response') if enc_response is None: raise Exception('Parameter missing') dec_response = decrypt_pairing_response(enc_response) if not dec_response.serial: raise ValidateError('Pairing responses with no serial attached ' 'are currently not implemented.') serial = dec_response.serial user_public_key = dec_response.user_public_key user_token_id = dec_response.user_token_id user = dec_response.user_login user = getUserFromParam(params, optional) # TODO: pairing policy tokens = getTokens4UserOrSerial(None, serial) if not tokens: raise Exception('Invalid serial in pairing response') if len(tokens) > 1: raise Exception('Multiple tokens found. Pairing not possible') token = tokens[0] if token.type != 'qr': raise Exception('Pairing is only implemented for the qrtoken') token.ensure_state('pairing_url_sent') token.addToTokenInfo('user_token_id', user_token_id) b64_user_public_key = b64encode(user_public_key) token.addToTokenInfo('user_public_key', b64_user_public_key) params['serial'] = serial params['user_public_key'] = user_public_key params['user_token_id'] = user_token_id params['user'] = user params['content_type'] = CONTENT_TYPE_PAIRING params['data'] = serial token.change_state('pairing_response_received') Session.commit() return sendResult(response, False) except Exception: Session.rollback() return sendResult(response, False, 0, status=False) finally: Session.close()
def check_status(self): """ check the status of a transaction - for polling support """ try: param = {} param.update(request.params) # # we require either state or transactionid as parameter transid = param.get('state', param.get('transactionid', None)) if not transid: raise ParameterError(_('Missing required parameter "state" or ' '"transactionid"!')) # # serial is an optional parameter serial = param.get('serial', None) # # but user is an required parameter if "user" not in param: raise ParameterError(_('Missing required parameter "serial"' ' or "user"!')) user = getUserFromParam(param) passw = param.get('pass', None) if passw is None: raise ParameterError(_('Missing required parameter "pass"!')) use_offline = param.get('use_offline', False) va = ValidationHandler() ok, opt = va.check_status(transid=transid, user=user, serial=serial, password=passw, use_offline=use_offline) c.audit['success'] = ok c.audit['info'] = unicode(opt) Session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("check_status failed: %r" % exx) c.audit['info'] = unicode(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 == 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_status(self): """ check the status of a transaction - for polling support """ try: param = self.request_params # # we require either state or transactionid as parameter transid = param.get('state', param.get('transactionid', None)) if not transid: raise ParameterError(_('Missing required parameter "state" or ' '"transactionid"!')) # # serial is an optional parameter serial = param.get('serial', None) # user is an optional parameter: # if no 'user' in the parameters, the User object will be empty user = getUserFromParam(param) passw = param.get('pass') if passw is None: raise ParameterError(_('Missing required parameter "pass"!')) use_offline = param.get('use_offline', False) va = ValidationHandler() ok, opt = va.check_status(transid=transid, user=user, serial=serial, password=passw, use_offline=use_offline) c.audit['success'] = ok c.audit['info'] = unicode(opt) Session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("check_status failed: %r" % exx) c.audit['info'] = unicode(exx) Session.rollback() return sendResult(response, False, 0) finally: Session.close()
def check_status(self): """ check the status of a transaction - for polling support """ try: param = self.request_params # # we require either state or transactionid as parameter transid = param.get('state', param.get('transactionid', None)) if not transid: raise ParameterError( _('Missing required parameter "state" or ' '"transactionid"!')) # # serial is an optional parameter serial = param.get('serial', None) # user is an optional parameter: # if no 'user' in the parameters, the User object will be empty user = getUserFromParam(param) passw = param.get('pass') if passw is None: raise ParameterError(_('Missing required parameter "pass"!')) use_offline = param.get('use_offline', False) va = ValidationHandler() ok, opt = va.check_status(transid=transid, user=user, serial=serial, password=passw, use_offline=use_offline) g.audit['success'] = ok g.audit['info'] = str(opt) db.session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("check_status failed: %r" % exx) g.audit['info'] = str(exx) db.session.rollback() return sendResult(response, False, 0)
def test_split_at_atsign( self, mock_getFromConfig, mock_getDefaultRealm, mock_getResolversOfUser, mock_getRealms, ): """ test the test sets for split at @ sign """ errors = [] config_id = 0 for test_set in self.test_sets: config_id += 1 config = test_set["config"] mock_getFromConfig.return_value = config["split@sign"] mock_getDefaultRealm.return_value = config["defaultRealm"] mock_getResolversOfUser.return_value = config["resolversOfUser"] mock_getRealms.return_value = config["realms"] # ------------------------------------------------------------- -- run_id = 0 for run in test_set["runs"]: run_id += 1 param = run["params"] result = run["result"] user = getUserFromParam(param) msg = ("Failed for config: %r\n at run[%r] %r\n" "result was %r" % (config, run_id, run, user)) try: assert user.login == result["login"], msg assert user.realm == result["realm"], msg except Exception as _exx: errors.append(msg) # ----------------------------------------------------------------- -- if errors: raise Exception(errors) return
def check_status(self): """ check the status of a transaction - for polling support """ param = {} ok = False opt = None try: param.update(request.params) transid = param.get('state', param.get('transactionid', None)) if not transid: raise ParameterError(_('Missing required parameter "state" or ' '"transactionid"!')) serial = param.get('serial', None) user = getUserFromParam(param, False) if not user and not serial: raise ParameterError(_('Missing required parameter "serial"' ' or "user"!')) passw = param.get('pass', None) if not passw: raise ParameterError(_('Missing required parameter "pass"!')) use_offline = param.get('use_offline', False) va = ValidationHandler() ok, opt = va.check_status(transid=transid, user=user, serial=serial, password=passw, use_offline=use_offline) c.audit['success'] = ok c.audit['info'] = unicode(opt) Session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("check_status failed: %r" % exx) c.audit['info'] = unicode(exx) Session.rollback() return sendResult(response, False, 0) finally: Session.close() log.debug('[check] done')
def test_split_at_atsign(self, mock_getFromConfig, mock_getDefaultRealm, mock_getResolversOfUser, mock_getRealms): """ test the test sets for split at @ sign """ errors = [] config_id = 0 for test_set in self.test_sets: config_id += 1 config = test_set['config'] mock_getFromConfig.return_value = config['split@sign'] mock_getDefaultRealm.return_value = config['defaultRealm'] mock_getResolversOfUser.return_value = config['resolversOfUser'] mock_getRealms.return_value = config['realms'] # ------------------------------------------------------------- -- run_id = 0 for run in test_set['runs']: run_id += 1 param = run['params'] result = run['result'] user = getUserFromParam(param) msg = ("Failed for config: %r\n at run[%r] %r\n" "result was %r" % (config, run_id, run, user)) try: self.assertTrue(user.login == result['login'], msg) self.assertTrue(user.realm == result['realm'], msg) except Exception as _exx: errors.append(msg) # ----------------------------------------------------------------- -- if errors: raise Exception(errors) return
def do_autosms_test(self, policy, user, client_ip, expected_result): new_policy = { "name": "autosms", "scope": "authentication", "realm": "*", "action": "autosms", } if policy: new_policy.update(policy) self.set_policy(new_policy) context["Client"] = client_ip context["RequestUser"] = getUserFromParam({"user": user}) result = get_auth_AutoSMSPolicy() assert result == expected_result
def parse_requesting_user(self): """ load the requesting user The result is placed into request_context['RequestUser'] """ from linotp.useridresolver.UserIdResolver import (ResolverNotAvailable) requestUser = None try: requestUser = getUserFromParam(self.request_params) except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r", exx) except (ResolverNotAvailable, NoResolverFound) as exx: log.error("Failed to connect to server %r", exx) request_context['RequestUser'] = requestUser
def autosms(self): ''' This function is used to test the autosms policy method: testing/autosms arguments: user - username / loginname realm - additional realm to match the user to a useridresolver returns: JSON response ''' log.debug('[autosms]') param = request.params try: if isSelfTest() == False: Session.rollback() return sendError( response, "The testing controller can only be used in SelfTest mode!", 0) user = getUserFromParam(param, required) ok = get_auth_AutoSMSPolicy() Session.commit() return sendResult(response, ok, 0) except Exception as e: log.error("[autosms] validate/check failed: %r", e) log.error("[autosms] %s" % traceback.format_exc()) Session.rollback() return sendError(response, "validate/check failed:" + unicode(e), 0) finally: Session.close() log.debug('[autosms] done')
def 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 autosms(self): ''' This function is used to test the autosms policy method: testing/autosms arguments: user - username / loginname realm - additional realm to match the user to a useridresolver returns: JSON response ''' log.debug('[autosms]') param = request.params try: if isSelfTest() == False: Session.rollback() return sendError(response, "The testing controller can only be used in SelfTest mode!", 0) user = getUserFromParam(param, required) ok = get_auth_AutoSMSPolicy() Session.commit() return sendResult(response, ok, 0) except Exception as e: log.error("[autosms] validate/check failed: %r", e) log.error("[autosms] %s" % traceback.format_exc()) Session.rollback() return sendError(response, "validate/check failed:" + unicode(e), 0) finally: Session.close() log.debug('[autosms] done')
def resolverinfo(self, realm): """ get the resolvers for one realm and the number of users per resolver :param realm: the realm to query :return: dict with resolvernames as keys and number of users as value """ realminfo = self.context.get('Config').getRealms().get(realm) resolvers = realminfo.get('useridresolver', '') realmdict = {} for resolver in resolvers: package, module, classs, conf = splitResolver(resolver) realmdict[conf] = 0 user = getUserFromParam({'realm': realm}, optionalOrRequired=True) users_iters = iterate_users(getUserListIterators({'realm': realm}, user)) for next_one in users_iters: for key in realmdict: if key in next_one: realmdict[key] += 1 return realmdict
def resolverinfo(self, realm): """ get the resolvers for one realm and the number of users per resolver :param realm: the realm to query :return: dict with resolvernames as keys and number of users as value """ realminfo = context.get('Config').getRealms().get(realm) resolver_specs = realminfo.get('useridresolver', '') realmdict = {} for resolver_spec in resolver_specs: __, config_identifier = parse_resolver_spec(resolver_spec) realmdict[config_identifier] = 0 user = getUserFromParam({'realm': realm}, optionalOrRequired=True) users_iters = iterate_users(getUserListIterators({'realm': realm}, user)) for next_one in users_iters: for key in realmdict: if key in next_one: realmdict[key] += 1 return realmdict
def resolverinfo(self, realm): """ get the resolvers for one realm and the number of users per resolver :param realm: the realm to query :return: dict with resolvernames as keys and number of users as value """ realminfo = context.get('Config').getRealms().get(realm) resolver_specs = realminfo.get('useridresolver', '') realmdict = {} for resolver_spec in resolver_specs: __, config_identifier = parse_resolver_spec(resolver_spec) realmdict[config_identifier] = 0 user = getUserFromParam({'realm': realm}) users = getUserList({'realm': realm, 'username': '******'}, user) for next_one in users: resolver = next_one['useridresolver'].split('.')[-1] if resolver in realmdict: realmdict[resolver] += 1 return realmdict
def resolverinfo(self, realm): """ get the resolvers for one realm and the number of users per resolver :param realm: the realm to query :return: dict with resolvernames as keys and number of users as value """ realminfo = context.get("Config").getRealms().get(realm) resolver_specs = realminfo.get("useridresolver", "") realmdict = {} for resolver_spec in resolver_specs: __, config_identifier = parse_resolver_spec(resolver_spec) realmdict[config_identifier] = 0 user = getUserFromParam({"realm": realm}) users = getUserList({"realm": realm, "username": "******"}, user) for next_one in users: resolver = next_one["useridresolver"].split(".")[-1] if resolver in realmdict: realmdict[resolver] += 1 return realmdict
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 getotp(self): ''' This function is used to retrieve the current otp value for a given user or a given serial If the user has more than one token, the list of the tokens is returend. method: gettoken/getotp arguments: user - username / loginname realm - additional realm to match the user to a useridresolver serial - the serial number of the token curTime - used ONLY for internal testing: datetime.datetime object returns: JSON response ''' getotp_active = config.get("linotpGetotp.active") if "True" != getotp_active: return sendError(response, "getotp is not activated.", 0) param = request.params ret = {} res = -1 otpval = "" passw = "" serials = [] try: serial = getParam(param, "serial", optional) user = getUserFromParam(param, optional) curTime = getParam(param, "curTime", optional) c.audit['user'] = user.login if "" != user.login: c.audit['realm'] = user.realm or getDefaultRealm() if serial: log.debug("[getotp] retrieving OTP value for token %s" % serial) elif user.login: log.debug("[getotp] retrieving OTP value for token for user %s@%s" % (user.login, user.realm)) toks = getTokens4UserOrSerial(user, serial) tokennum = len(toks) if tokennum > 1: log.debug("[getotp] The user has more than one token. Returning the list of serials") res = -3 for token in toks: serials.append(token.getSerial()) elif 1 == tokennum: serial = toks[0].getSerial() log.debug("[getotp] retrieving OTP for token %s for user %s@%s" % (serial, user.login, user.realm)) else: log.debug("[getotp] no token found for user %s@%s" % (user.login, user.realm)) res = -4 else: res = -5 # if a serial was given or a unique serial could be received from the given user. if serial: max_count = checkPolicyPre('gettoken', 'max_count', param) log.debug("[getmultiotp] checkpolicypre returned %s" % max_count) if max_count <= 0: return sendError(response, "The policy forbids receiving OTP values for the token %s in this realm" % serial , 1) (res, pin, otpval, passw) = getOtp(serial, curTime=curTime) c.audit['success'] = True if int(res) < 0: ret['result'] = False if -1 == otpval: ret['description'] = "No Token with this serial number" if -2 == otpval: ret['description'] = "This Token does not support the getOtp function" if -3 == otpval: ret['description'] = "The user has more than one token" ret['serials'] = serials if -4 == otpval: ret['description'] = "No Token found for this user" if -5 == otpval: ret['description'] = "you need to provide a user or a serial" else: ret['result'] = True ret['otpval'] = otpval ret['pin'] = pin ret['pass'] = passw Session.commit() return sendResult(response, ret , 0) except PolicyException as pe: log.exception("[getotp] gettoken/getotp policy failed: %r" % pe) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.exception("[getotp] gettoken/getotp failed: %r" % e) Session.rollback() return sendError(response, "gettoken/getotp failed: %s" % unicode(e), 0) finally: Session.close() log.debug('[getotp] done')
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 document_split_at_atsign(self, mock_getFromConfig, mock_getDefaultRealm, mock_getResolversOfUser, mock_getRealms): """ create documentation for the split at @sign behaviour """ table = [] raisedException = None config_id = 0 for test_set in self.test_sets: config_id += 1 config = test_set['config'] mock_getFromConfig.return_value = config['split@sign'] mock_getDefaultRealm.return_value = config['defaultRealm'] mock_getResolversOfUser.return_value = config['resolversOfUser'] mock_getRealms.return_value = config['realms'] table.append('') cparams = json.dumps(config) cc = cparams.replace( '{', ' * ').replace( ',', ' * ').replace( '}', '') panel = ("{panel:title=Configuration|borderColor=blue|" "titleBGColor=#708090|titleColor=white|bgColor=#dcdcdc}") cc = cc.replace( "true", 'Ja').replace( "resolversOfUser", "User wird Resolver gefunden").replace( "realms", "Benutzer ist in folgenden Realms") table.append('%s %s' % (panel, cc)) table.append('') # ------------------------------------------------------------- -- run_id = 0 for run in test_set['runs']: run_id += 1 param = run['params'] user = getUserFromParam(param) jparams = json.dumps(param) pp = jparams.replace( '{', '|* ').replace( ',', ' * ').replace( '}', '') result = {'login': user.login, 'realm': user.realm} rparams = json.dumps(result) rr = rparams.replace( '{', '|* ').replace( ',', ' * ').replace( '}', '') table.append('||Parameters: %s||Result: %s|' % (pp, rr)) table.append('{panel}') table.append('') with open('/tmp/split_at_atsign.txt', 'w') as ff: ff.write("\n".join(table).replace( ' * ', '\n* ').replace( '[', '- ').replace( ']', '')) # ----------------------------------------------------------------- -- if raisedException: raise raisedException # eof #
def getotp(self): ''' This function is used to retrieve the current otp value for a given user or a given serial If the user has more than one token, the list of the tokens is returend. method: gettoken/getotp arguments: user - username / loginname realm - additional realm to match the user to a useridresolver serial - the serial number of the token curTime - used ONY for internal testing: datetime.datetime object returns: JSON response ''' getotp_active = config.get("linotpGetotp.active") if "True" != getotp_active: return sendError(response, "getotp is not activated.", 0) param = request.params ret = {} res = -1 otpval = "" passw = "" serials = [] try: serial = getParam(param, "serial", optional) user = getUserFromParam(param, optional) curTime = getParam(param, "curTime", optional) c.audit['user'] = user.login if "" != user.login: c.audit['realm'] = user.realm or getDefaultRealm() if serial: log.debug("[getotp] retrieving OTP value for token %s" % serial) elif user.login: log.debug( "[getotp] retrieving OTP value for token for user %s@%s" % (user.login, user.realm)) toks = getTokens4UserOrSerial(user, serial) tokennum = len(toks) if tokennum > 1: log.debug( "[getotp] The user has more than one token. Returning the list of serials" ) res = -3 for token in toks: serials.append(token.getSerial()) elif 1 == tokennum: serial = toks[0].getSerial() log.debug( "[getotp] retrieving OTP for token %s for user %s@%s" % (serial, user.login, user.realm)) else: log.debug("[getotp] no token found for user %s@%s" % (user.login, user.realm)) res = -4 else: res = -5 # if a serial was given or a unique serial could be received from the given user. if serial: max_count = checkPolicyPre('gettoken', 'max_count', param) log.debug("[getmultiotp] checkpolicypre returned %s" % max_count) if max_count <= 0: return sendError( response, "The policy forbids receiving OTP values for the token %s in this realm" % serial, 1) (res, pin, otpval, passw) = getOtp(serial, curTime=curTime) c.audit['success'] = True if int(res) < 0: ret['result'] = False if -1 == otpval: ret['description'] = "No Token with this serial number" if -2 == otpval: ret['description'] = "This Token does not support the getOtp function" if -3 == otpval: ret['description'] = "The user has more than one token" ret['serials'] = serials if -4 == otpval: ret['description'] = "No Token found for this user" if -5 == otpval: ret['description'] = "you need to provide a user or a serial" else: ret['result'] = True ret['otpval'] = otpval ret['pin'] = pin ret['pass'] = passw Session.commit() return sendResult(response, ret, 0) except PolicyException as pe: log.error("[getotp] gettoken/getotp policy failed: %r" % pe) log.error("[getotp] %s" % traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("[getotp] gettoken/getotp failed: %r" % e) log.error("[getotp] %s" % traceback.format_exc()) Session.rollback() return sendError(response, "gettoken/getotp failed: %s" % unicode(e), 0) finally: Session.close() log.debug('[getotp] done')
def userview_flexi(self): ''' This function is used to fill the flexigrid. Unlike the complex /admin/userlist function, it only returns a simple array of the tokens. ''' param = request.params try: #serial = getParam(param,"serial",optional) c.page = getParam(param, "page", optional) c.filter = getParam(param, "query", optional) qtype = getParam(param, "qtype", optional) c.sort = getParam(param, "sortname", optional) c.dir = getParam(param, "sortorder", optional) c.psize = getParam(param, "rp", optional) c.realm = getParam(param, "realm", optional) user = getUserFromParam(param, optional) # check admin authorization # check if we got a realm or resolver, that is ok! checkPolicyPre('admin', 'userlist', { 'user': user.login, 'realm': c.realm }) if c.filter == "": c.filter = "*" log.debug( "[userview_flexi] page: %s, filter: %s, sort: %s, dir: %s" % (c.page, c.filter, c.sort, c.dir)) if c.page is None: c.page = 1 if c.psize is None: c.psize = 20 c.userArray = getUserList({ qtype: c.filter, 'realm': c.realm }, user) c.userNum = len(c.userArray) lines = [] for u in c.userArray: # shorten the useridresolver, to get a better display value resolver_display = "" if "useridresolver" in u: if len(u['useridresolver'].split(".")) > 3: resolver_display = u['useridresolver'].split(".")[ 3] + " (" + u['useridresolver'].split(".")[1] + ")" else: resolver_display = u['useridresolver'] # Arrange the table more helpfully. lines.append({ 'id': u['username'], 'cell': [ (u['username']) if u.has_key('username') else (""), (u['givenname']) if u.has_key('givenname') else (""), (u['surname']) if u.has_key('surname') else (""), (u['email']) if u.has_key('email') else (""), (u['userid']) if u.has_key('userid') else (""), ] }) log.debug("[userview_flexi] Elements in c.userArray: %s" % len(c.userArray)) # sorting reverse = False sortnames = { 'username': 0, 'givenname': 1, 'surname': 2, 'email': 3, 'userid': 4 } if c.dir == "desc": reverse = True lines = sorted(lines, key=lambda user: user['cell'][sortnames[c.sort]], reverse=reverse, cmp=unicode_compare) # end: sorting # reducing the page if c.page and c.psize: page = int(c.page) psize = int(c.psize) start = psize * (page - 1) end = start + psize lines = lines[start:end] # We need to return 'page', 'total', 'rows' response.content_type = 'application/json' res = {"page": int(c.page), "total": c.userNum, "rows": lines} c.audit['success'] = True Session.commit() return json.dumps(res, indent=3) except PolicyException as pe: log.error("[userview_flexi] Error during checking policies: %r" % pe) log.error("[userview_flexi] %s" % traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("[userview_flexi] failed: %r" % e) log.error("[userview_flexi] %s" % traceback.format_exc()) Session.rollback() return sendError(response, e) finally: Session.close() log.debug('[userview_flexi] done')
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")
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 userview_flexi(self): """ This function is used to fill the flexigrid. Unlike the complex /admin/userlist function, it only returns a simple array of the tokens. """ param = request.params try: # serial = getParam(param,"serial",optional) c.page = getParam(param, "page", optional) c.filter = getParam(param, "query", optional) qtype = getParam(param, "qtype", optional) c.sort = getParam(param, "sortname", optional) c.dir = getParam(param, "sortorder", optional) c.psize = getParam(param, "rp", optional) c.realm = getParam(param, "realm", optional) user = getUserFromParam(param, optional) # check admin authorization # check if we got a realm or resolver, that is ok! checkPolicyPre("admin", "userlist", {"user": user.login, "realm": c.realm}) if c.filter == "": c.filter = "*" log.debug("[userview_flexi] page: %s, filter: %s, sort: %s, dir: %s" % (c.page, c.filter, c.sort, c.dir)) if c.page is None: c.page = 1 if c.psize is None: c.psize = 20 c.userArray = getUserList({qtype: c.filter, "realm": c.realm}, user) c.userNum = len(c.userArray) lines = [] for u in c.userArray: # shorten the useridresolver, to get a better display value resolver_display = "" if "useridresolver" in u: if len(u["useridresolver"].split(".")) > 3: resolver_display = ( u["useridresolver"].split(".")[3] + " (" + u["useridresolver"].split(".")[1] + ")" ) else: resolver_display = u["useridresolver"] lines.append( { "id": u["username"], "cell": [ (u["username"]) if u.has_key("username") else (""), (resolver_display), (u["surname"]) if u.has_key("surname") else (""), (u["givenname"]) if u.has_key("givenname") else (""), (u["email"]) if u.has_key("email") else (""), (u["mobile"]) if u.has_key("mobile") else (""), (u["phone"]) if u.has_key("phone") else (""), (u["userid"]) if u.has_key("userid") else (""), ], } ) # sorting reverse = False sortnames = { "username": 0, "useridresolver": 1, "surname": 2, "givenname": 3, "email": 4, "mobile": 5, "phone": 6, "userid": 7, } if c.dir == "desc": reverse = True lines = sorted( lines, key=lambda user: user["cell"][sortnames[c.sort]], reverse=reverse, cmp=unicode_compare ) # end: sorting # reducing the page if c.page and c.psize: page = int(c.page) psize = int(c.psize) start = psize * (page - 1) end = start + psize lines = lines[start:end] # We need to return 'page', 'total', 'rows' response.content_type = "application/json" res = {"page": int(c.page), "total": c.userNum, "rows": lines} c.audit["success"] = True Session.commit() return json.dumps(res, indent=3) except PolicyException as pe: log.error("[userview_flexi] Error during checking policies: %r" % pe) log.error("[userview_flexi] %s" % traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("[userview_flexi] failed: %r" % e) log.error("[userview_flexi] %s" % traceback.format_exc()) Session.rollback() return sendError(response, e) finally: Session.close() log.debug("[userview_flexi] done")
def create_context(self, request): """ create the request context for all controllers """ linotp_config = getLinotpConfig() self.request_context = {} self.request_context['Config'] = linotp_config self.request_context['Policies'] = getPolicies(config=linotp_config) self.request_context['translate'] = translate request_params = {} try: request_params.update(request.params) except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) self.request_context['Params'] = request_params authUser = None try: authUser = getUserFromRequest(request) except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) self.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) self.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) self.request_context['Client'] = client self.request_context['audit'] = {} defaultRealm = "" try: defaultRealm = getDefaultRealm(linotp_config) except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) self.request_context['defaultRealm'] = defaultRealm realms = None try: realms = getRealms(context=self.request_context) except UnicodeDecodeError as exx: log.error("Faild to decode request parameters %r" % exx) self.request_context['Realms'] = realms return
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 userview_flexi(self): ''' This function is used to fill the flexigrid. Unlike the complex /admin/userlist function, it only returns a simple array of the tokens. ''' param = self.request_params try: c.page = param.get("page") c.filter = param.get("query") qtype = param.get("qtype") c.sort = param.get("sortname") c.dir = param.get("sortorder") c.psize = param.get("rp") c.realm = param.get("realm") user = getUserFromParam(param) # check admin authorization # check if we got a realm or resolver, that is ok! checkPolicyPre('admin', 'userlist', { 'user': user.login, 'realm': c.realm }) if c.filter == "": c.filter = "*" log.debug( "[userview_flexi] page: %s, filter: %s, sort: %s, dir: %s" % (c.page, c.filter, c.sort, c.dir)) if c.page is None: c.page = 1 if c.psize is None: c.psize = 20 c.userArray = getUserList({ qtype: c.filter, 'realm': c.realm }, user) c.userNum = len(c.userArray) lines = [] for u in c.userArray: # shorten the useridresolver, to get a better display value resolver_display = "" if "useridresolver" in u: if len(u['useridresolver'].split(".")) > 3: resolver_display = u['useridresolver'].split(".")[ 3] + " (" + u['useridresolver'].split(".")[1] + ")" else: resolver_display = u['useridresolver'] lines.append({ 'id': u['username'], 'cell': [ (u['username']) if 'username' in u else (""), (resolver_display), (u['surname']) if 'surname' in u else (""), (u['givenname']) if 'givenname' in u else (""), (u['email']) if 'email' in u else (""), (u['mobile']) if 'mobile' in u else (""), (u['phone']) if 'phone' in u else (""), (u['userid']) if 'userid' in u else (""), ] }) # sorting reverse = False sortnames = { 'username': 0, 'useridresolver': 1, 'surname': 2, 'givenname': 3, 'email': 4, 'mobile': 5, 'phone': 6, 'userid': 7 } if c.dir == "desc": reverse = True lines = sorted(lines, key=lambda user: user['cell'][sortnames[c.sort]], reverse=reverse) # end: sorting # reducing the page if c.page and c.psize: page = int(c.page) psize = int(c.psize) start = psize * (page - 1) end = start + psize lines = lines[start:end] # We need to return 'page', 'total', 'rows' res = {"page": int(c.page), "total": c.userNum, "rows": lines} c.audit['success'] = True Session.commit() return sendResult(response, res) except PolicyException as pe: log.exception( "[userview_flexi] Error during checking policies: %r" % pe) Session.rollback() return sendError(response, str(pe), 1) except Exception as e: log.exception("[userview_flexi] failed: %r" % e) Session.rollback() return sendError(response, e) finally: Session.close()
def document_split_at_atsign(self, mock_getFromConfig, mock_getDefaultRealm, mock_getResolversOfUser, mock_getRealms): """ create documentation for the split at @sign behaviour """ table = [] raisedException = None config_id = 0 for test_set in self.test_sets: config_id += 1 config = test_set['config'] mock_getFromConfig.return_value = config['split@sign'] mock_getDefaultRealm.return_value = config['defaultRealm'] mock_getResolversOfUser.return_value = config['resolversOfUser'] mock_getRealms.return_value = config['realms'] table.append('') cparams = json.dumps(config) cc = cparams.replace('{', ' * ').replace(',', ' * ').replace('}', '') panel = ("{panel:title=Configuration|borderColor=blue|" "titleBGColor=#708090|titleColor=white|bgColor=#dcdcdc}") cc = cc.replace("true", 'Ja').replace( "resolversOfUser", "User wird Resolver gefunden").replace( "realms", "Benutzer ist in folgenden Realms") table.append('%s %s' % (panel, cc)) table.append('') # ------------------------------------------------------------- -- run_id = 0 for run in test_set['runs']: run_id += 1 param = run['params'] user = getUserFromParam(param) jparams = json.dumps(param) pp = jparams.replace('{', '|* ').replace(',', ' * ').replace('}', '') result = {'login': user.login, 'realm': user.realm} rparams = json.dumps(result) rr = rparams.replace('{', '|* ').replace(',', ' * ').replace('}', '') table.append('||Parameters: %s||Result: %s|' % (pp, rr)) table.append('{panel}') table.append('') with open('/tmp/split_at_atsign.txt', 'w') as ff: ff.write("\n".join(table).replace(' * ', '\n* ').replace( '[', '- ').replace(']', '')) # ----------------------------------------------------------------- -- if raisedException: raise raisedException # eof #
def userview_flexi(self): ''' This function is used to fill the flexigrid. Unlike the complex /admin/userlist function, it only returns a simple array of the tokens. ''' param = request.params try: #serial = getParam(param,"serial",optional) c.page = getParam(param, "page", optional) c.filter = getParam(param, "query", optional) qtype = getParam(param, "qtype", optional) c.sort = getParam(param, "sortname", optional) c.dir = getParam(param, "sortorder", optional) c.psize = getParam(param, "rp", optional) c.realm = getParam(param, "realm", optional) user = getUserFromParam(param, optional) # check admin authorization # check if we got a realm or resolver, that is ok! checkPolicyPre('admin', 'userlist', { 'user': user.login, 'realm' : c.realm }, context=self.request_context) if c.filter == "": c.filter = "*" log.debug("[userview_flexi] page: %s, filter: %s, sort: %s, dir: %s" % (c.page, c.filter, c.sort, c.dir)) if c.page is None: c.page = 1 if c.psize is None: c.psize = 20 c.userArray = getUserList({ qtype:c.filter, 'realm':c.realm }, user) c.userNum = len(c.userArray) lines = [] for u in c.userArray: # shorten the useridresolver, to get a better display value resolver_display = "" if "useridresolver" in u: if len(u['useridresolver'].split(".")) > 3: resolver_display = u['useridresolver'].split(".")[3] + " (" + u['useridresolver'].split(".")[1] + ")" else: resolver_display = u['useridresolver'] lines.append( { 'id' : u['username'], 'cell': [ (u['username']) if u.has_key('username') else (""), (resolver_display), (u['surname']) if u.has_key('surname') else (""), (u['givenname']) if u.has_key('givenname') else (""), (u['email']) if u.has_key('email') else (""), (u['mobile']) if u.has_key('mobile') else (""), (u['phone']) if u.has_key('phone') else (""), (u['userid']) if u.has_key('userid') else (""), ] } ) # sorting reverse = False sortnames = { 'username' : 0, 'useridresolver' : 1, 'surname' : 2, 'givenname' : 3, 'email' : 4, 'mobile' :5, 'phone' : 6, 'userid' : 7 } if c.dir == "desc": reverse = True lines = sorted(lines, key=lambda user: user['cell'][sortnames[c.sort]], reverse=reverse, cmp=unicode_compare) # end: sorting # reducing the page if c.page and c.psize: page = int(c.page) psize = int(c.psize) start = psize * (page - 1) end = start + psize lines = lines[start:end] # We need to return 'page', 'total', 'rows' response.content_type = 'application/json' res = { "page": int(c.page), "total": c.userNum, "rows": lines } c.audit['success'] = True Session.commit() return sendResult(response, res) except PolicyException as pe: log.exception("[userview_flexi] Error during checking policies: %r" % pe) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.exception("[userview_flexi] failed: %r" % e) Session.rollback() return sendError(response, e) finally: Session.close() log.debug('[userview_flexi] 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 = {} 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 checkstatus(self): """ method: ocra/checkstatus description: Methode zur assynchronen Ueberpruefungen eines Challenge Response Valiadation requests arguments: * transactionid: (required one of - string - (hex)) Dies ist eine Transaktions-ID, die bei der Challenge ausgegeben wurde. * serial: (required one of - string) die Serien Nummer des OCRA Token * user: (required one of - string) die Benutzer eines Tokens required is one of (user,serial,transactionid) returns: A JSON response:: { "version": "LinOTP 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": [ { "serial": SERIENNUMMER1, "transactionid": TRANSACTIONID1, "received_tan": true, "valid_tan": true, "failcount": 0 }, { "serial": SERIENNUMMER1, "transactionid": TRANSACTIONID2, "received_tan": false, "valid_tan": false, "failcount": 0 }, { "serial": SERIENNUMMER2, "transactionid": TRANSACTIONID3, "received_tan": true, "valid_tan": false, "failcount": 2 }, ] }, "id": 0 } exception: """ res = {} description = ('ocra/checkstatus: check the token status - ' 'for assynchronous verification. Missing parameter: ' 'You need to provide one of the parameters ' '"transactionid", "user" or "serial"') try: param = getLowerParams(request.params) log.debug("[checkstatus] check OCRA token status: %r" % param) checkPolicyPre('ocra', "status") transid = param.get('transactionid') user = getUserFromParam(param) serial = param.get('serial') if transid is None and user.is_empty and serial is None: # raise exception log.exception("[ocra/checkstatus] : missing transactionid, user or serial number for token") raise ParameterError("Usage: %s" % description, id=77) tokens = [] serials = set() status = [] if serial is not None: serials.add(serial) # if we have a transaction, get serial from this challenge if transid is not None: ocraChallenge = None try: ocraChallenge = OcraTokenClass.getTransaction(transid) except: pass if ocraChallenge is not None: serials.add(ocraChallenge.tokenserial) # if we have a serial number of token if len(serials) > 0: for serial in serials: tokens.extend(getTokens4UserOrSerial(serial=serial)) # if we have a user if not user.is_empty: try: tokens.extend(getTokens4UserOrSerial(user=user)) except: log.warning("no token or user %r found!" % user) for token in tokens: if token.getType() == 'ocra': challenges = [] if transid is None: serial = token.getSerial() challenges = OcraTokenClass.getTransactions4serial( serial) else: challenges.append(OcraTokenClass.getTransaction( transid)) for challenge in challenges: stat = token.getStatus(challenge.transid) if stat is not None and len(stat) > 0: status.append(stat) res['values'] = status c.audit['success'] = res Session.commit() return sendResult(response, res, 1) except PolicyException as pe: log.exception("[checkstatus] policy failed: %r" % pe) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.exception("[checkstatus] failed: %r" % exx) Session.rollback() return sendResult(response, unicode(exx), 0) finally: Session.close()
def userview_flexi(self): """ This function is used to fill the flexigrid. Unlike the complex /admin/userlist function, it only returns a simple array of the tokens. """ param = self.request_params try: c.page = param.get("page") c.filter = param.get("query") qtype = param.get("qtype") c.sort = param.get("sortname") c.dir = param.get("sortorder") c.psize = param.get("rp") c.realm = param.get("realm") user = getUserFromParam(param) # check admin authorization # check if we got a realm or resolver, that is ok! checkPolicyPre( "admin", "userlist", {"user": user.login, "realm": c.realm} ) if c.filter == "": c.filter = "*" log.debug( "[userview_flexi] page: %s, filter: %s, sort: %s, dir: %s", c.page, c.filter, c.sort, c.dir, ) if c.page is None: c.page = 1 if c.psize is None: c.psize = 20 c.userArray = getUserList( {qtype: c.filter, "realm": c.realm}, user ) c.userNum = len(c.userArray) lines = [] for u in c.userArray: # shorten the useridresolver, to get a better display value resolver_display = "" if "useridresolver" in u: if len(u["useridresolver"].split(".")) > 3: resolver_display = ( u["useridresolver"].split(".")[3] + " (" + u["useridresolver"].split(".")[1] + ")" ) else: resolver_display = u["useridresolver"] lines.append( { "id": u["username"], "cell": [ (u["username"]) if "username" in u else (""), (resolver_display), (u["surname"]) if "surname" in u else (""), (u["givenname"]) if "givenname" in u else (""), (u["email"]) if "email" in u else (""), (u["mobile"]) if "mobile" in u else (""), (u["phone"]) if "phone" in u else (""), (u["userid"]) if "userid" in u else (""), ], } ) # sorting reverse = False sortnames = { "username": 0, "useridresolver": 1, "surname": 2, "givenname": 3, "email": 4, "mobile": 5, "phone": 6, "userid": 7, } if c.dir == "desc": reverse = True lines = sorted( lines, key=lambda user: user["cell"][sortnames[c.sort]], reverse=reverse, ) # end: sorting # reducing the page if c.page and c.psize: page = int(c.page) psize = int(c.psize) start = psize * (page - 1) end = start + psize lines = lines[start:end] # We need to return 'page', 'total', 'rows' res = {"page": int(c.page), "total": c.userNum, "rows": lines} g.audit["success"] = True db.session.commit() return sendResult(response, res) except PolicyException as pe: log.error( "[userview_flexi] Error during checking policies: %r", pe ) db.session.rollback() return sendError(response, pe, 1) except Exception as exx: log.error("[userview_flexi] failed: %r", exx) db.session.rollback() return sendError(response, exx)
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 = getParam(param, 'serial', optional) user = getUserFromParam(param, optional) if user.isEmpty() and serial is None: ## raise exception log.exception("[request] user or serial is required") raise ParameterError("Usage: %s" % description, id=77) message = getParam(param, 'data' , optional) 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)) log.error(error) raise Exception(error) if len(tokens) == 0: error = ('No token found: unable to create challenge for' ' (u:%r,s:%r)!' % (user, serial)) log.error(error) 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 #c.audit['info'] += "%s=%s, " % (k, value) Session.commit() qr = getParam(param, 'qr', optional) 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() log.debug("[request] done")
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 _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 para in options: del options[para] passw = param.get("pass") user = getUserFromParam(param) # support for challenge verification challenge = param.get("challenge") if challenge is not None: options = {} options["challenge"] = challenge g.audit["user"] = user.login realm = user.realm or getDefaultRealm() g.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) vh = ValidationHandler() (ok, opt) = vh.checkUserPass(user, passw, options=options) g.audit.update(request_context.get("audit", {})) g.audit["success"] = ok if ok: # AUTHORIZATION post check check_auth_tokentype(g.audit["serial"], exception=True, user=user) check_auth_serial(g.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"] = g.audit.get("realm") opt["user"] = g.audit.get("user") opt["tokentype"] = g.audit.get("token_type") opt["serial"] = g.audit.get("serial") else: opt["error"] = g.audit.get("action_detail") return (ok, opt)
def checkstatus(self): """ method: ocra/checkstatus description: Methode zur assynchronen Ueberpruefungen eines Challenge Response Valiadation requests arguments: * transactionid: (required one of - string - (hex)) Dies ist eine Transaktions-ID, die bei der Challenge ausgegeben wurde. * serial: (required one of - string) die Serien Nummer des OCRA Token * user: (required one of - string) die Benutzer eines Tokens required is one of (user,serial,transactionid) returns: A JSON response:: { "version": "LinOTP 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": [ { "serial": SERIENNUMMER1, "transactionid": TRANSACTIONID1, "received_tan": true, "valid_tan": true, "failcount": 0 }, { "serial": SERIENNUMMER1, "transactionid": TRANSACTIONID2, "received_tan": false, "valid_tan": false, "failcount": 0 }, { "serial": SERIENNUMMER2, "transactionid": TRANSACTIONID3, "received_tan": true, "valid_tan": false, "failcount": 2 }, ] }, "id": 0 } exception: """ res = {} description = 'ocra/checkstatus: check the token status - for assynchronous verification. Missing parameter: You need to provide one of the parameters "transactionid", "user" or "serial"' try: param = getLowerParams(request.params) log.debug("[checkstatus] check OCRA token status: %r" % param) checkPolicyPre('ocra', "status") transid = getParam(param, 'transactionid' , optional) user = getUserFromParam(param, optional) #user = getParam(param, 'user' ,optional) serial = getParam(param, 'serial' , optional) if transid is None and user.isEmpty() and serial is None: ## raise exception log.exception("[ocra/checkstatus] : missing transactionid, user or serial number for token") raise ParameterError("Usage: %s" % description, id=77) tokens = [] serials = set() status = [] if serial is not None: serials.add(serial) ## if we have a transaction, get serial from this challenge if transid is not None : ocraChallenge = None try: ocraChallenge = OcraTokenClass.getTransaction(transid) except: pass if ocraChallenge is not None: serials.add(ocraChallenge.tokenserial) ## if we have a serial number of token if len(serials) > 0: for serial in serials: tokens.extend(getTokens4UserOrSerial(serial=serial)) ## if we have a user if user.isEmpty() == False: try: tokens.extend(getTokens4UserOrSerial(user=user)) except: log.warning("no token or user %r found!" % user) for token in tokens: if token.getType() == 'ocra': challenges = [] if transid is None: serial = token.getSerial() challenges = OcraTokenClass.getTransactions4serial(serial) else: challenges.append(OcraTokenClass.getTransaction(transid)) for challenge in challenges: stat = token.getStatus(challenge.transid) if stat is not None and len(stat) > 0: status.append(stat) res['values'] = status c.audit['success'] = res Session.commit() return sendResult(response, res, 1) except PolicyException as pe: log.exception("[checkstatus] policy failed: %r" % pe) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.exception("[checkstatus] failed: %r" % exx) Session.rollback() return sendResult(response, unicode(exx), 0) finally: Session.close() log.debug('[ocra/checkstatus] done')
def check_status(self): """ check the status of a transaction - for polling support """ try: param = self.request_params # # we require either state or transactionid as parameter transid = param.get("state", param.get("transactionid", None)) if not transid: raise ParameterError( _( 'Missing required parameter "state" or ' '"transactionid"!' ) ) # # serial is an optional parameter serial = param.get("serial", None) # user is an optional parameter: # if no 'user' in the parameters, the User object will be empty user = getUserFromParam(param) passw = param.get("pass") if passw is None: raise ParameterError(_('Missing required parameter "pass"!')) use_offline = param.get("use_offline", False) va = ValidationHandler() ok, opt = va.check_status( transid=transid, user=user, serial=serial, password=passw, use_offline=use_offline, ) serials = [] types = [] owner = None challenges = Challenges.lookup_challenges(transid=transid) for ch in challenges: tokens = getTokens4UserOrSerial(serial=ch.getTokenSerial()) if not tokens: continue for token in tokens: serials.append(token.getSerial()) types.append(token.getType()) if not owner: owner = get_token_owner(token) if owner: g.audit["user"] = g.audit["user"] or owner.login g.audit["realm"] = g.audit["realm"] or owner.realm g.audit["serial"] = " ".join(serials) g.audit["token_type"] = " ".join(types) g.audit["success"] = ok g.audit["info"] = str(opt) db.session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.error("check_status failed: %r", exx) g.audit["info"] = str(exx) db.session.rollback() return sendResult(response, False, 0)
def getotp(self): ''' This function is used to retrieve the current otp value for a given user or a given serial. If the user has more than one token, the list of the tokens is returend. method: gettoken/getotp arguments: user - username / loginname realm - additional realm to match the user to a useridresolver serial - the serial number of the token curTime - used ONLY for internal testing: datetime.datetime object returns: JSON response ''' getotp_active = config.get("GETOTP_ENABLED") if not getotp_active: return sendError(response, "getotp is not activated.", 0) param = self.request_params ret = {} res = -1 otpval = "" passw = "" serials = [] try: serial = getParam(param, "serial", optional) user = getUserFromParam(param) curTime = getParam(param, "curTime", optional) g.audit['user'] = user.login if "" != user.login: g.audit['realm'] = user.realm or getDefaultRealm() if serial: log.debug("[getotp] retrieving OTP value for token %s", serial) elif user.login: log.debug( "[getotp] retrieving OTP value for token for user " "%s@%s", user.login, user.realm) toks = getTokens4UserOrSerial(user, serial) tokennum = len(toks) if tokennum > 1: log.debug("[getotp] The user has more than one token." "Returning the list of serials") res = -3 for token in toks: serials.append(token.getSerial()) elif 1 == tokennum: serial = toks[0].getSerial() log.debug( "[getotp] retrieving OTP for token %s for user" " %s@%s", serial, user.login, user.realm) else: log.debug("[getotp] no token found for user %s@%s", user.login, user.realm) res = -4 else: res = -5 # if a serial was given or a unique serial could be # received from the given user. if serial: max_count = checkPolicyPre('gettoken', 'max_count', param) log.debug("[getmultiotp] max_count policy: %s", max_count) if max_count <= 0: return sendError( response, "The policy forbids receiving" " OTP values for the token %s in " "this realm" % serial, 1) (res, pin, otpval, passw) = getOtp(serial, curTime=curTime) g.audit['success'] = True if int(res) < 0: ret['result'] = False if -1 == otpval: ret['description'] = "No Token with this serial number" if -2 == otpval: ret['description'] = ("This Token does not support the" " getOtp function") if -3 == otpval: ret['description'] = "The user has more than one token" ret['serials'] = serials if -4 == otpval: ret['description'] = "No Token found for this user" if -5 == otpval: ret['description'] = ("you need to provide a user or " "a serial") else: ret['result'] = True ret['otpval'] = otpval ret['pin'] = pin ret['pass'] = passw db.session.commit() return sendResult(response, ret, 0) except PolicyException as pe: log.exception("[getotp] gettoken/getotp policy failed: %r", pe) db.session.rollback() return sendError(response, str(pe), 1) except Exception as exx: log.exception("[getotp] gettoken/getotp failed: %r", exx) db.session.rollback() return sendError(response, "gettoken/getotp failed: %s" % exx, 0)
def check_s(self): """ This function is used to validate the serial and the otp value/password. If the otppin policy is set, the endpoint /validate/check_s does not work. 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] 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() g.audit["serial"] = serial options["scope"] = {"check_s": True} vh = ValidationHandler() (ok, opt) = vh.checkSerialPass(serial, passw, options=options) g.audit["success"] = ok db.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.error("[check_s] validate/check_s failed: %r", exx) g.audit["info"] = str(exx) db.session.rollback() return sendResult(response, False, id=0, status=False)
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 create_context(self, request, environment): """ create the request context for all controllers """ linotp_config = getLinotpConfig() # make the request id available in the request context request_context['RequestId'] = environment['REQUEST_ID'] # a request local cache to get the user info from the resolver request_context['UserLookup'] = {} # a request local cache to get the resolver from user and realm request_context['UserRealmLookup'] = {} request_context['Config'] = linotp_config request_context['Policies'] = parse_policies(linotp_config) request_context['translate'] = translate request_context['CacheManager'] = environment['beaker.cache'] routes = environment.get('pylons.routes_dict', {}) path = "/%s/%s" % (routes['controller'], routes['action']) request_context['Path'] = path request_context['hsm'] = self.hsm initResolvers() 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) 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'] = {} # ------------------------------------------------------------------ -- # get the current resolvers resolvers = [] try: resolvers = getResolverList(config=linotp_config) except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r" % exx) request_context['Resolvers'] = resolvers # ------------------------------------------------------------------ -- # get the current realms realms = {} try: realms = getRealms() except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r" % exx) request_context['Realms'] = realms # ------------------------------------------------------------------ -- defaultRealm = "" try: defaultRealm = getDefaultRealm(linotp_config) except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r" % exx) request_context['defaultRealm'] = defaultRealm # ------------------------------------------------------------------ -- # load the requesting user from linotp.useridresolver.UserIdResolver import ( ResolverNotAvailable) requestUser = None try: requestUser = getUserFromParam(self.request_params) except UnicodeDecodeError as exx: log.error("Failed to decode request parameters %r", exx) except (ResolverNotAvailable, NoResolverFound) as exx: log.error("Failed to connect to server %r", exx) request_context['RequestUser'] = requestUser # ------------------------------------------------------------------ -- # load the providers from linotp.provider import Provider_types from linotp.provider import getProvider provider = {} for provider_type in Provider_types.keys(): provider[provider_type] = getProvider(provider_type) request_context['Provider'] = provider # ------------------------------------------------------------------ -- # for the setup of encrypted data, we require the hsm is instatiated # and available in the request context if not self.secret_key: init_key_partition(linotp_config, partition=0) # ------------------------------------------------------------------ -- # 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 _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 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'] request_context['Path'] = environment.get("PATH_INFO", "") or "" request_context['hsm'] = self.hsm 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 initResolvers() 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) 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 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 # ------------------------------------------------------------------ -- # for the setup of encrypted data, we require the hsm is instatiated # and available in the request context if not self.secret_key: init_key_partition(linotp_config, partition=0) # ------------------------------------------------------------------ -- # 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 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(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)