def sendXMLResult(response, obj, id=1, opt=None): """ send the result as an xml format """ response.content_type = 'text/xml' res = '<?xml version="1.0" encoding="UTF-8"?>\ <jsonrpc version="%s">\ <result>\ <status>True</status>\ <value>%s</value>\ </result>\ <version>%s</version>\ <id>%s</id>\ </jsonrpc>' % (get_api_version(), obj, get_version(), id) xml_options = "" if opt: xml_options = "\n<options>" + json2xml(opt) + "</options>" xml_object = json2xml(obj) res = """<?xml version="1.0" encoding="UTF-8"?> <jsonrpc version="2.0"> <result> <status>True</status> <value>%s</value> </result> <version>%s</version> <id>%s</id>%s </jsonrpc>""" % (xml_object, get_version(), id, xml_options) return res
def sendResult(response, obj, id=1, opt=None): ''' sendResult - return an json result document :param response: the pylons response object :type response: response object :param obj: simple result object like dict, sting or list :type obj: dict or list or string/unicode :param id: id value, for future versions :type id: int :param opt: optional parameter, which allows to provide more detail :type opt: None or simple type like dict, list or string/unicode :return: json rendered sting result :rtype: string ''' response.content_type = 'application/json' res = { "jsonrpc": "2.0", "result": { "status": True, "value": obj, }, "version": get_version(), "id": id } if opt is not None and len(opt) > 0: res["detail"] = opt return json.dumps(res, indent=3)
def __before__(self, action, **params): log.debug("[__before__::%r] %r" % (action, params)) try: audit.initialize() c.audit['success'] = False c.audit['client'] = get_client(request) c.version = get_version() c.licenseinfo = get_copyright_info() c.polDefs = getPolicyDefinitions() # Session handling for the functions, that show data: # Also exclude custom-style.css, since the CSRF check # will always fail and return a HTTP 401 anyway. # A HTTP 404 makes more sense. if request.path.lower() in [ '/manage/', '/manage', '/manage/logout', '/manage/audittrail', '/manage/policies', '/manage/tokenview', '/manage/userview', '/manage/help', '/manage/custom-style.css' ]: pass else: check_session(request) except Exception as exx: log.exception("[__before__::%r] exception %r" % (action, exx)) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: log.debug("[__before__::%r] done" % (action))
def sendResult(response, obj, id=1, opt=None, status=True): ''' sendResult - return an json result document :param response: the pylons response object :type response: response object :param obj: simple result object like dict, sting or list :type obj: dict or list or string/unicode :param id: id value, for future versions :type id: int :param opt: optional parameter, which allows to provide more detail :type opt: None or simple type like dict, list or string/unicode :return: json rendered sting result :rtype: string ''' response.content_type = 'application/json' res = { "jsonrpc": get_api_version(), "result": { "status": status, "value": obj, }, "version": get_version(), "id": id } if opt is not None and len(opt) > 0: res["detail"] = opt return json.dumps(res, indent=3)
def sendResult(response, obj, id=1, opt=None): ''' sendResult - return an json result document :param response: the pylons response object :type response: response object :param obj: simple result object like dict, sting or list :type obj: dict or list or string/unicode :param id: id value, for future versions :type id: int :param opt: optional parameter, which allows to provide more detail :type opt: None or simple type like dict, list or string/unicode :return: json rendered sting result :rtype: string ''' response.content_type = 'application/json' res = { "jsonrpc": "2.0", "result": { "status": True, "value": obj, }, "version": get_version(), "id": id } # Add the additional data in a more helpful way rather than # dumping it in as a top-level node. if opt is not None and len(opt) > 0: res["result"].update(opt) return json.dumps(res, indent=3)
def __before__(self, **params): """ __before__ is called before every action :param params: list of named arguments :return: -nothing- or in case of an error a Response created by sendError with the context info 'before' """ action = request_context['action'] try: c.audit = request_context['audit'] c.audit['success'] = False c.audit['client'] = get_client(request) c.version = get_version() c.version_ref = base64.encodebytes(c.version.encode())[:6] c.licenseinfo = get_copyright_info() c.polDefs = getPolicyDefinitions() c.display_provider = boolean( request_context['Config'].get('display_provider', True)) # -------------------------------------------------------------- -- # check for support of setting admin password c.admin_can_change_password = False if ('linotpadmin.user' in config and 'linotpadmin.password' in config): c.admin_can_change_password = True # -------------------------------------------------------------- -- # Session handling for the functions, that show data: # Also exclude custom-style.css, since the CSRF check # will always fail and return a HTTP 401 anyway. # A HTTP 404 makes more sense. if request.path.lower() in ['/manage/', '/manage', '/manage/logout', '/manage/audittrail', '/manage/policies', '/manage/tokenview', '/manage/userview', '/manage/help', '/manage/custom-style.css']: pass else: check_session(request) except Exception as exx: log.exception("[__before__::%r] exception %r" % (action, exx)) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: log.debug("[__before__::%r] done" % (action))
def __before__(self, action, **params): log.debug("[__before__::%r] %r" % (action, params)) try: self.set_language() c.version = get_version() c.licenseinfo = get_copyright_info() except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.error("[__before__::%r] webob.exception %r" % (action, acc)) log.error("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: log.error("[__before__::%r] exception %r" % (action, exx)) log.error("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: log.debug("[__before__::%r] done" % (action))
def __before__(self, action, **params): log.debug("[__before__::%r] %r" % (action, params)) try: c.version = get_version() c.licenseinfo = get_copyright_info() except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.error("[__before__::%r] webob.exception %r" % (action, acc)) log.error("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: log.error("[__before__::%r] exception %r" % (action, exx)) log.error("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: log.debug("[__before__::%r] done" % (action))
def sendXMLResult(_response, obj, id=1, opt=None): """ send the result as an xml format """ xml_options = "" if opt: xml_options = "\n<options>" + json2xml(opt) + "</options>" xml_object = json2xml(obj) res = """<?xml version="1.0" encoding="UTF-8"?> <jsonrpc version="2.0"> <result> <status>True</status> <value>%s</value> </result> <version>%s</version> <id>%s</id>%s </jsonrpc>""" % ( xml_object, get_version(), id, xml_options, ) return Response(response=res, status=200, mimetype="text/xml")
def get_pre_context(client): """ get the rendering context before the login is shown, so the rendering of the login page could be controlled if realm_box or mfa_login is defined :param client: the rendering is client dependend, so we need the info :return: context dict, with all rendering attributes """ # check for mfa_login, autoassign and autoenroll in policy definition mfa_login_action = get_selfservice_action_value( action="mfa_login", default=False ) mfa_3_fields_action = get_selfservice_action_value( action="mfa_3_fields", default=False ) autoassignment_action = get_selfservice_action_value( action="autoassignment", default=False ) autoenrollment_action = get_selfservice_action_value( action="autoenrollment", default=False ) footer_text_action = get_selfservice_action_value( action="footer_text", default=None ) imprint_url_action = get_selfservice_action_value( action="imprint_url", default=None ) privacy_notice_url_action = get_selfservice_action_value( action="privacy_notice_url", default=None ) return { "version": get_version(), "copyright": get_copyright_info(), "realms": _get_realms_(), "settings": { "default_realm": getDefaultRealm(), "realm_box": getRealmBox(), "mfa_login": mfa_login_action, "mfa_3_fields": mfa_3_fields_action, "autoassign": autoassignment_action, "autoenroll": autoenrollment_action, "footer_text": footer_text_action, "imprint_url": imprint_url_action, "privacy_notice_url": privacy_notice_url_action, }, }
def sendXMLResult(response, obj, id=1): response.content_type = 'text/xml' res = '<?xml version="1.0" encoding="UTF-8"?>\ <jsonrpc version="2.0">\ <result>\ <status>True</status>\ <value>%s</value>\ </result>\ <version>%s</version>\ <id>%s</id>\ </jsonrpc>' % (obj, get_version(), id) return res
def __before__(self, action,): try: c.version = get_version() c.licenseinfo = get_copyright_info() except Exception as exx: log.exception("[__before__::%r] exception %r" % (action, exx)) Session.rollback() Session.close() return sendError(response, exx, context='before')
def __before__(self, action, **params): try: c.audit = request_context['audit'] c.audit['success'] = False c.audit['client'] = get_client(request) c.version = get_version() c.version_ref = base64.encodestring(c.version)[:6] c.licenseinfo = get_copyright_info() c.polDefs = getPolicyDefinitions() c.display_provider = boolean( request_context['Config'].get('display_provider', True)) # -------------------------------------------------------------- -- # check for support of setting admin password c.admin_can_change_password = False if ('linotpadmin.user' in config and 'linotpadmin.password' in config): c.admin_can_change_password = True # -------------------------------------------------------------- -- # Session handling for the functions, that show data: # Also exclude custom-style.css, since the CSRF check # will always fail and return a HTTP 401 anyway. # A HTTP 404 makes more sense. if request.path.lower() in ['/manage/', '/manage', '/manage/logout', '/manage/audittrail', '/manage/policies', '/manage/tokenview', '/manage/userview', '/manage/help', '/manage/custom-style.css']: pass else: check_session(request) except Exception as exx: log.exception("[__before__::%r] exception %r" % (action, exx)) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: log.debug("[__before__::%r] done" % (action))
def get_pre_context(client): """ get the rendering context before the login is shown, so the rendering of the login page could be controlled if realm_box or mfa_login is defined :param client: the rendering is client dependend, so we need the info :return: context dict, with all rendering attributes """ pre_context = {} pre_context["version"] = get_version() pre_context["licenseinfo"] = get_copyright_info() pre_context["default_realm"] = getDefaultRealm() pre_context["realm_box"] = getRealmBox() pre_context["realms"] = json.dumps(_get_realms_()) # check for mfa_login, autoassign and autoenroll in policy definition pre_context['mfa_login'] = False policy = get_client_policy(client=client, scope='selfservice', action='mfa_login') if policy: pre_context['mfa_login'] = True pre_context['mfa_3_fields'] = False policy = get_client_policy(client=client, scope='selfservice', action='mfa_3_fields') if policy: pre_context['mfa_3_fields'] = True pre_context['autoassign'] = False policy = get_client_policy(client=client, scope='enrollment', action='autoassignment') if policy: pre_context['autoassign'] = True pre_context['autoenroll'] = False policy = get_client_policy(client=client, scope='enrollment', action='autoenrollment') if policy: pre_context['autoenroll'] = True return pre_context
def __before__(self, action, **params): try: c.version = get_version() c.licenseinfo = get_copyright_info() except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.exception("[__before__::%r] webob.exception %r" % (action, acc)) Session.rollback() Session.close() raise acc except Exception as exx: log.exception("[__before__::%r] exception %r" % (action, exx)) Session.rollback() Session.close() return sendError(response, exx, context='before')
def __before__(self, action, **params): log.debug("[__before__]") try: c.version = get_version() c.licenseinfo = get_copyright_info() except Exception as exx: log.error("[__before__::%r] exception %r" % (action, exx)) log.error("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: log.debug("[__before__::%r] done" % (action))
def __before__(self, **params): """ __before__ is called before every action :param params: list of named arguments :return: -nothing- or in case of an error a Response created by sendError with the context info 'before' """ action = request_context["action"] try: c.version = get_version() c.licenseinfo = get_copyright_info() except Exception as exx: log.error("[__before__::%r]", action) db.session.rollback() return sendError(response, exx, context="before")
def __before__(self, action, **params): log.debug("[__before__::%r] %r" % (action, params)) try: audit.initialize() c.audit["success"] = False c.audit["client"] = get_client() c.version = get_version() c.licenseinfo = get_copyright_info() c.polDefs = getPolicyDefinitions() # Session handling for the functions, that show data: # Also exclude custom-style.css, since the CSRF check # will always fail and return a HTTP 401 anyway. # A HTTP 404 makes more sense. if request.path.lower() in [ "/manage/", "/manage", "/manage/logout", "/manage/audittrail", "/manage/policies", "/manage/tokenview", "/manage/userview", "/manage/help", "/manage/custom-style.css", ]: pass else: check_session() except Exception as exx: log.error("[__before__::%r] exception %r" % (action, exx)) log.error("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context="before") finally: log.debug("[__before__::%r] done" % (action))
def sendXMLError(response, exception, id=1): response.content_type = 'text/xml' if not hasattr(exception, "getId"): errId = -311 errDesc = str(exception) else: errId = exception.getId() errDesc = exception.getDescription() res = '<?xml version="1.0" encoding="UTF-8"?>\ <jsonrpc version="2.0">\ <result>\ <status>False</status>\ <error>\ <code>%s</code>\ <message>%s</message>\ </error>\ </result>\ <version>%s</version>\ <id>%s</id>\ </jsonrpc>' % (errId, errDesc, get_version(), id) return res
def get_pre_context(client, context=None): """ get the rendering context before the login is shown, so the rendering of the login page could be controlled if realm_box or otpLogin is defined :param client: the rendering is client dependend, so we need the info :return: context dict, with all rendering attributes """ pre_context = {} pre_context["version"] = get_version() pre_context["licenseinfo"] = get_copyright_info() pre_context["default_realm"] = getDefaultRealm() pre_context["realm_box"] = getRealmBox() pre_context["realms"] = json.dumps(_get_realms_()) """ check for otpLogin, autoassign and autoenroll in policy definition """ pre_context["otpLogin"] = False policy = get_client_policy(client=client, scope="selfservice", action="otpLogin", context=context) if policy: pre_context["otpLogin"] = True pre_context["autoassign"] = False policy = get_client_policy(client=client, scope="enrollment", action="autoassignment", context=context) if policy: pre_context["autoassign"] = True pre_context["autoenroll"] = False policy = get_client_policy(client=client, scope="enrollment", action="autoenrollment", context=context) if policy: pre_context["autoenroll"] = True return pre_context
def get_pre_context(client): """ get the rendering context before the login is shown, so the rendering of the login page could be controlled if realm_box or mfa_login is defined :param client: the rendering is client dependend, so we need the info :return: context dict, with all rendering attributes """ # check for mfa_login, autoassign and autoenroll in policy definition mfa_login_policy = get_client_policy(client=client, scope='selfservice', action='mfa_login') mfa_3_fields_policy = get_client_policy(client=client, scope='selfservice', action='mfa_3_fields') autoassignment_policy = get_client_policy(client=client, scope='enrollment', action='autoassignment') autoenrollment_policy = get_client_policy(client=client, scope='enrollment', action='autoenrollment') return { "version": get_version(), "copyright": get_copyright_info(), "realms": _get_realms_(), "settings": { "default_realm": getDefaultRealm(), "realm_box": getRealmBox(), "mfa_login": bool(mfa_login_policy), "mfa_3_fields": bool(mfa_3_fields_policy), "autoassign": bool(autoassignment_policy), "autoenroll": bool(autoenrollment_policy), }, }
def __before__(self, action, **params): log.debug("[__before__::%r] %r" % (action, params)) try: c.audit = request_context['audit'] c.audit['success'] = False c.audit['client'] = get_client(request) c.version = get_version() c.licenseinfo = get_copyright_info() c.polDefs = getPolicyDefinitions() # Session handling for the functions, that show data: # Also exclude custom-style.css, since the CSRF check # will always fail and return a HTTP 401 anyway. # A HTTP 404 makes more sense. if request.path.lower() in ['/manage/', '/manage', '/manage/logout', '/manage/audittrail', '/manage/policies', '/manage/tokenview', '/manage/userview', '/manage/help', '/manage/custom-style.css']: pass else: check_session(request) except Exception as exx: log.exception("[__before__::%r] exception %r" % (action, exx)) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: log.debug("[__before__::%r] done" % (action))
def sendXMLError(_response, exception, id=1): if not hasattr(exception, "getId"): errId = -311 errDesc = str(exception) else: errId = exception.getId() errDesc = exception.getDescription() res = ( '<?xml version="1.0" encoding="UTF-8"?>\ <jsonrpc version="%s">\ <result>\ <status>False</status>\ <error>\ <code>%s</code>\ <message>%s</message>\ </error>\ </result>\ <version>%s</version>\ <id>%s</id>\ </jsonrpc>' % (get_api_version(), errId, errDesc, get_version(), id) ) return Response(response=res, status=200, mimetype="text/xml")
def sendError(response, exception, id=1, context=None): ''' sendError - return a HTML or JSON error result document Default LinOTP behaviour in case of error is to try to always send a '200 OK' HTTP response that contains an error code and description in the body (JSON data). Some clients prefer a different HTTP status code, because it allows response filtering without parsing the body. If the client sends 'httperror=<INT>' in the request this will be honoured (in case of error) and that HTTP status will be set. If 'httperror' is set without a value (or an invalid value) status 500 will be used. If you would like this to happen only in some error conditions but not all you can set 'linotp.errors' in the LinOTP Config. Then the HTTP status defined by 'httperror' will ONLY be sent when the error that occurs in LinOTP matches one of the errors defined in 'linotp.errors'. In other cases '200 OK' with error code and description in the body will be returned. If 'linotp.errors' is unset all errors will cause responses with HTTP status 'httperror'. For example: Setup 1: * The client sends httperror=777 in the request * linotp.errors=233,567 Case 1.1: An exception is raised in LinOTP that has errId 233. - LinOTP will return a response with HTTP status 777. Case 1.2: An exception is raised with errId 555 - LinOTP will return a response with HTTP status 200. Setup 2: * The client sends httperror (empty) in the request * linotp.errors=233,567 Case 2.1: An exception is raised in LinOTP that has errId 233. - LinOTP will return a response with HTTP status 500. Case 2.2: An exception is raised with errId 555 - LinOTP will return a response with HTTP status 200. Setup 3: * The client sends httperror (empty) in the request * linotp.errors is not set Case 3.1: An exception is raised in LinOTP that has errId 233. - LinOTP will return a response with HTTP status 500. Case 3.2: An exception is raised with errId 555 - LinOTP will return a response with HTTP status 500. Setup 4: * NO httperror in request * linotp.errors=233,567 (or is unset, does not matter) Case 4.1: An exception is raised in LinOTP that has errId 233. - LinOTP will return a response with HTTP status 200. Case 4.2: An exception is raised with errId 555 - LinOTP will return a response with HTTP status 200. remark for 'context' parameter: the 'context' is especially required to catch errors from the _before_ methods. The return of a _before_ must be of type response and must have the attribute response._exception set, to stop further processing, which otherwise will have ugly results!! :param response: the pylon response object :type response: response object :param exception: should be a linotp exception (s. linotp.lib.error.py) :type exception: exception :param id: id value, for future versions :type id: int :param context: default is None or 'before' :type context: string :return: json rendered sting result :rtype: string ''' ret = '' errId = -311 ## handle the different types of exception: ## Exception, LinOtpError, str/unicode if hasattr(exception, '__class__') is True \ and isinstance(exception, Exception): errDesc = unicode(exception) if isinstance(exception, LinotpError): errId = exception.getId() elif type(exception) in [str, unicode]: errDesc = unicode(exception) else: errDesc = u"%r" % exception ## check if we have an additional request parameter 'httperror' ## which triggers the error to be delivered as HTTP Error httperror = _get_httperror_from_params(request) send_custom_http_status = False if httperror is not None: # Client wants custom HTTP status linotp_errors = c.linotpConfig.get('linotp.errors', None) if not linotp_errors: # Send custom HTTP status in every error case send_custom_http_status = True else: # Only send custom HTTP status in defined error cases if unicode(errId) in linotp_errors.split(','): send_custom_http_status = True else: send_custom_http_status = False if send_custom_http_status: # Send HTML response with HTTP status 'httperror' # Always set a reason, when no standard one found (e.g. custom HTTP # code like 444) use 'LinOTP Error' reason = httpErr.get(httperror, 'LinOTP Error') response.content_type = 'text/html' response.status = "%s %s" % (httperror, reason) code = httperror status = "%s %s" % (httperror, reason) desc = '[%s] %d: %s' % (get_version(), errId, errDesc) ret = resp % (code, status, code, status, desc) if context in ['before', 'after']: response._exception = exception response.text = u'' + ret ret = response else: # Send JSON response with HTTP status 200 OK response.content_type = 'application/json' res = { "jsonrpc": get_api_version(), "result": { "status": False, "error": { "code": errId, "message": errDesc, }, }, "version": get_version(), "id": id } ret = json.dumps(res, indent=3) if context in ['before', 'after']: response._exception = exception response.body = ret ret = response return ret
def __before__(self, action): ''' This is the authentication to self service If you want to do ANYTHING with selfservice, you need to be authenticated. The _before_ is executed before any other function in this controller. ''' try: param = request.params audit.initialize() c.audit['success'] = False c.audit['client'] = get_client(request) c.version = get_version() c.licenseinfo = get_copyright_info() self.request_context['Audit'] = audit (auth_type, auth_user) = get_auth_user(request) if not auth_user or auth_type not in ['repoze', 'selftest']: abort(401, "You are not authenticated") (c.user, _foo, c.realm) = auth_user.rpartition('@') self.authUser = User(c.user, c.realm, '') if auth_type == "repoze": # checking the session if (False == check_selfservice_session(request, request.url, request.path, request.cookies, request.params )): c.audit['action'] = request.path[1:] c.audit['info'] = "session expired" audit.log(c.audit) abort(401, "No valid session") c.imprint = get_imprint(c.realm) c.tokenArray = [] c.user = self.authUser.login c.realm = self.authUser.realm c.tokenArray = getTokenForUser(self.authUser) # only the defined actions should be displayed # - remark: the generic actions like enrollTT are allready approved # to have a rendering section and included actions = getSelfserviceActions(self.authUser, context=self.request_context) c.actions = actions for policy in actions: if "=" in policy: (name, val) = policy.split('=') val = val.strip() # try if val is a simple numeric - # w.r.t. javascript evaluation try: nval = int(val) except: nval = val c.__setattr__(name.strip(), nval) c.dynamic_actions = add_dynamic_selfservice_enrollment(config, c.actions) # we require to establish all token local defined # policies to be initialiezd additional_policies = add_dynamic_selfservice_policies(config, actions) for policy in additional_policies: c.__setattr__(policy, -1) c.otplen = -1 c.totp_len = -1 return response except webob.exc.HTTPUnauthorized as acc: # the exception, when an abort() is called if forwarded log.info("[__before__::%r] webob.exception %r" % (action, acc)) log.info("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as e: log.exception("[__before__] failed with error: %r" % e) Session.rollback() Session.close() return sendError(response, e, context='before') finally: log.debug('[__after__] done')
def __before__(self, action, **params): log.debug("[__before__::%r]" % (action)) valid_request = False try: for key, value in params.items(): log.debug("[__before__::%r:%r]" % (key, value)) c.audit = request_context[audit] c.audit['client'] = get_client(request) request_context['Audit'] = audit self.storage = config.get('openid_sql') getCookieExpire = int(config.get("linotpOpenID.CookieExpire", -1)) self.COOKIE_EXPIRE = 3600 if getCookieExpire >= 0: self.COOKIE_EXPIRE = getCookieExpire c.logged_in = False c.login = "" c.version = get_version() c.licenseinfo = get_copyright_info() http_host = request.environ.get("HTTP_HOST") log.debug("[__before__] Doing openid request from host %s" % http_host) if not is_valid_fqdn(http_host, split_port=True): err = "Bad hostname: %s" % http_host audit.log(c.audit) c.audit["action_detail"] = err log.error(err) raise HTTPBadRequest(err) self.BASEURL = request.environ.get("wsgi.url_scheme") + "://" + http_host # check if the browser is logged in login = request.cookies.get(COOKIE_NAME) if login: c.logged_in = True ## default return for the __before__ and __after__ log.debug("[__before__::%r]" % (response)) valid_request = True return response except PolicyException as pex: log.exception("[__before__::%r] policy exception %r" % (action, pex)) return sendError(response, pex, context='before') except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.exception("[__before__::%r] webob.exception %r" % (action, acc)) raise acc except Exception as exx: log.exception("[__before__::%r] exception %r" % (action, exx)) return sendError(response, exx, context='before') finally: if valid_request is False: self.storage.session.rollback() self.storage.session.close() log.debug("[__before__::%r] done" % (action))
def __before__(self, **params): """ __before__ is called before every action This is the authentication to self service. If you want to do ANYTHING with the selfservice, you need to be authenticated. The _before_ is executed before any other function in this controller. :param params: list of named arguments :return: -nothing- or in case of an error a Response created by sendError with the context info 'before' """ action = request_context['action'] self.redirect = None try: c.version = get_version() c.licenseinfo = get_copyright_info() c.version_ref = base64.encodebytes(c.version.encode())[:6] g.audit['success'] = False self.client = get_client(request) g.audit['client'] = self.client # -------------------------------------------------------------- -- # handle requests which dont require authetication if action in ['logout', 'custom_style']: return # -------------------------------------------------------------- -- # get the authenticated user auth_type, auth_user, auth_state = get_auth_user(request) # -------------------------------------------------------------- -- # handle not authenticated requests if not auth_user or auth_type not in ['user_selfservice']: if action in ['login']: return if action in ['index']: self.redirect = True return redirect(url_for('.login')) else: raise Unauthorized('No valid session') # -------------------------------------------------------------- -- # handle authenticated requests # there is only one special case, which is the login that # could be forwarded to the index page if action in ['login']: if auth_state != 'authenticated': return self.redirect = True return redirect(url_for('.index')) # -------------------------------------------------------------- -- # in case of user_selfservice, an unauthenticated request should always go to login if auth_user and auth_type == 'user_selfservice' \ and auth_state != 'authenticated': self.redirect = True return redirect(url_for('.login')) # futher processing with the authenticated user if auth_state != 'authenticated': raise Unauthorized('No valid session') c.user = auth_user.login c.realm = auth_user.realm self.authUser = auth_user # -------------------------------------------------------------- -- # authenticated session verification if auth_type == 'user_selfservice': # checking the session only for not_form_access actions if action not in self.form_access_methods: valid_session = check_session(request, auth_user, self.client) if not valid_session: g.audit['action'] = request.path[1:] g.audit['info'] = "session expired" current_app.audit_obj.log(g.audit) raise Unauthorized('No valid session') # -------------------------------------------------------------- -- c.imprint = get_imprint(c.realm) c.tokenArray = [] c.user = self.authUser.login c.realm = self.authUser.realm # only the defined actions should be displayed # - remark: the generic actions like enrollTT are allready approved # to have a rendering section and included actions = get_selfservice_actions(self.authUser) c.actions = actions for action_name, action_value in actions.items(): if action_value is True: c.__setattr__(action_name, -1) continue c.__setattr__(action_name, action_value) c.dynamic_actions = add_dynamic_selfservice_enrollment(config, c.actions) # we require to establish all token local defined # policies to be initialiezd additional_policies = add_dynamic_selfservice_policies(config, actions) for policy in additional_policies: c.__setattr__(policy, -1) c.otplen = -1 c.totp_len = -1 c.pin_policy = _get_auth_PinPolicy(user=self.authUser) except (flap.HTTPUnauthorized, flap.HTTPForbidden) as acc: # the exception, when an abort() is called if forwarded log.info("[__before__::%r] webob.exception %r" % (action, acc)) db.session.rollback() raise acc except Exception as e: log.exception("[__before__] failed with error: %r" % e) db.session.rollback() return sendError(response, e, context='before')
def __before__(self, action): ''' This is the authentication to self service If you want to do ANYTHING with selfservice, you need to be authenticated. The _before_ is executed before any other function in this controller. ''' try: param = request.params audit.initialize() c.audit['success'] = False c.audit['client'] = get_client() c.version = get_version() c.licenseinfo = get_copyright_info() if isSelfTest(): log.debug("[__before__] Doing selftest!") uuser = getParam(param, "selftest_user", True) if uuser is not None: (c.user, _foo, c.realm) = uuser.rpartition('@') else: c.realm = "" c.user = "******" env = request.environ uuser = env.get('REMOTE_USER') if uuser is not None: (c.user, _foo, c.realm) = uuser.rpartition('@') self.authUser = User(c.user, c.realm, '') log.debug("[__before__] authenticating as %s in realm %s!" % (c.user, c.realm)) else: # Use WebAuth instead of LinOTP auth. identity = request.environ.get('REMOTE_USER') if identity is None: abort(401, "You are not authenticated") c.user = identity # Put their current realm as the first one we find them in. # Doesn't really matter since tokens are realm-independent. realms = getAllUserRealms(User(identity, "", "")) if (realms): c.realm = realms[0] self.authUser = User(c.user, c.realm, '') # Check token expiry. age = int(request.environ.get('WEBAUTH_TOKEN_EXPIRATION')) - time.time() # Set selfservice cookie response.set_cookie('linotp_selfservice', 'REMOTE_USER', max_age = int(age)) # Set userservice auth cookie self.client = get_client() authcookie = create_auth_cookie(config, identity, self.client) response.set_cookie('userauthcookie', authcookie, max_age=360*24) log.debug("[__before__] set the self.authUser to: %s, %s " % (self.authUser.login, self.authUser.realm)) log.debug('[__before__] param for action %s: %s' % (action, param)) # checking the session if (False == check_selfservice_session(request.url, request.path, request.cookies, request.params)): c.audit['action'] = request.path[1:] c.audit['info'] = "session expired" audit.log(c.audit) abort(401, "No valid session") c.imprint = get_imprint(c.realm) c.tokenArray = [] c.user = self.authUser.login c.realm = self.authUser.realm c.tokenArray = getTokenForUser(self.authUser) # only the defined actions should be displayed # - remark: the generic actions like enrollTT are allready approved # to have a rendering section and included actions = getSelfserviceActions(self.authUser) c.actions = actions for policy in actions: if "=" in policy: (name, val) = policy.split('=') val = val.strip() # try if val is a simple numeric - # w.r.t. javascript evaluation try: nval = int(val) except: nval = val c.__setattr__(name.strip(), nval) c.dynamic_actions = add_dynamic_selfservice_enrollment(config, c.actions) # we require to establish all token local defined # policies to be initialiezd additional_policies = add_dynamic_selfservice_policies(config, actions) for policy in additional_policies: c.__setattr__(policy, -1) c.otplen = -1 c.totp_len = -1 return response except webob.exc.HTTPUnauthorized as acc: # the exception, when an abort() is called if forwarded log.info("[__before__::%r] webob.exception %r" % (action, acc)) log.info("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as e: log.error("[__before__] failed with error: %r" % e) log.error("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() return sendError(response, e, context='before') finally: log.debug('[__before__] done')
def sendError(response, exception, id=1, context=None): ''' sendError - return a json error result document remark: the 'context' is especially required to catch errors from the _before_ methods. The return of a _before_ must be of type response and must have the attribute response._exception set, to stop further processing, which otherwise will have ugly results!! :param response: the pylon response object :type response: response object :param exception: should be a linotp exception (s. linotp.lib.error.py) :type exception: exception :param id: id value, for future versions :type id: int :param context: default is None or 'before' :type context: string :return: json rendered sting result :rtype: string ''' ret = '' errId = -311 ## handle the different types of exception: ## Exception, LinOtpError, str/unicode if hasattr(exception, '__class__') == True \ and isinstance(exception, Exception): errDesc = unicode(exception) if isinstance(exception, LinotpError): errId = exception.getId() elif type(exception) in [str, unicode]: errDesc = unicode(exception) else: errDesc = u"%r" % exception HTTP_ERROR = False ## check if we have an additional request parameter 'httperror' ## which triggers the error to be delivered as HTTP Error try: httperror = request.params.get('httperror') except Exception as exx: httperror = "%r" % exx if httperror is not None: ## now lookup in the config, which linotp errors should be shwon as ## HTTP error linotp_errors = c.linotpConfig.get('linotp.errors', None) if linotp_errors is None: HTTP_ERROR = True else: linotp_errors = linotp_errors.split(',') if unicode(errId) in linotp_errors: HTTP_ERROR = True else: HTTP_ERROR = False if HTTP_ERROR is True: ## httperror as param exist but is not defined ## so fallback to 500 - Internal Server Error if len(httperror) == 0: httperror = '500' ## prepare the response to be of text/html response.content_type = 'text/html' response.status = httperror code = httperror status = httpErr.get(httperror, '') desc = '[%s] %d: %s' % (get_version(), errId, errDesc) ret = resp % (code, status, code, status, desc) if context in ['before', 'after']: response._exception = exception response.text = u'' + ret ret = response else: response.content_type = 'application/json' res = { "jsonrpc": "2.0", "result" : {"status": False, "error": { "code" : errId, "message" : errDesc, }, }, "version": get_version(), "id": id } ret = json.dumps(res, indent=3) if context in ['before', 'after']: response._exception = exception response.body = ret ret = response return ret
def __before__(self, **params): """ __before__ is called before every action :param params: list of named arguments :return: -nothing- or in case of an error a Response created by sendError with the context info 'before' """ action = request_context["action"] try: g.audit["success"] = False g.audit["client"] = get_client(request) c.version = get_version() c.version_ref = base64.encodebytes(c.version.encode())[:6] c.licenseinfo = get_copyright_info() c.polDefs = get_policy_definitions() c.display_provider = boolean( request_context["Config"].get("display_provider", True) ) # -------------------------------------------------------------- -- # check for support of setting admin password c.admin_can_change_password = False if ( "linotpadmin.user" in config and "linotpadmin.password" in config ): c.admin_can_change_password = True # -------------------------------------------------------------- -- # Session handling for the functions, that show data: # Also exclude custom-style.css, since the CSRF check # will always fail and return a HTTP 401 anyway. # A HTTP 404 makes more sense. if request.path.lower() in [ "/manage/", "/manage", "/manage/login", "/manage/audittrail", "/manage/policies", "/manage/tokenview", "/manage/userview", "/manage/help", "/manage/custom-style.css", ]: pass else: check_session(request) except Exception as exx: log.error("[__before__::%r] exception %r", action, exx) db.session.rollback() return sendError(response, exx, context="before") finally: log.debug("[__before__::%r] done", action)
def sendResultIterator(obj, id=1, opt=None, rp=None, page=None): ''' sendResultIterator - return an json result document in a streamed mode :param obj: iterator of generator object like dict, string or list :param id: id value, for future versions :param opt: optional parameter, which allows to provide more detail :param rp: results per page :param page: number of page :return: generator of response data (yield) ''' api_version = get_api_version() linotp_version = get_version() res = { "jsonrpc": api_version, "result": { "status": True, "value": "[DATA]", }, "version": linotp_version, "id": id } err = { "jsonrpc": api_version, "result": { "status": False, "error": {}, }, "version": linotp_version, "id": id } start_at = 0 stop_at = 0 if page: if not rp: rp = 16 try: start_at = int(page) * int(rp) stop_at = start_at + int(rp) except ValueError as exx: err['result']['error'] = { "code": 9876, "message": "%r" % exx, } log.exception("failed to convert paging request parameters: %r" % exx) yield json.dumps(err) # finally we signal end of error result raise StopIteration() typ = "%s" % type(obj) if 'generator' not in typ and 'iterator' not in typ: raise Exception('no iterator method for object %r' % obj) res = { "jsonrpc": api_version, "result": { "status": True, "value": "[DATA]", }, "version": linotp_version, "id": id } if page: res['result']['page'] = int(page) if opt is not None and len(opt) > 0: res["detail"] = opt surrounding = json.dumps(res) prefix, postfix = surrounding.split('"[DATA]"') # first return the opening yield prefix + " [" sep = "" counter = 0 for next_one in obj: counter = counter + 1 # are we running in paging mode? if page: if counter >= start_at and counter < stop_at: res = "%s%s\n" % (sep, next_one) sep = ',' yield res if counter >= stop_at: # stop iterating if we reached the last one of the page break else: # no paging - no limit res = "%s%s\n" % (sep, next_one) sep = ',' yield res # we add the amount of queried objects total = '"queried" : %d' % counter postfix = ', %s %s' % (total, postfix) # last return the closing yield "] " + postfix
def sendError(response, exception, id=1, context=None): ''' sendError - return a HTML or JSON error result document Default LinOTP behaviour in case of error is to try to always send a '200 OK' HTTP response that contains an error code and description in the body (JSON data). Some clients prefer a different HTTP status code, because it allows response filtering without parsing the body. If the client sends 'httperror=<INT>' in the request this will be honoured (in case of error) and that HTTP status will be set. If 'httperror' is set without a value (or an invalid value) status 500 will be used. If you would like this to happen only in some error conditions but not all you can set 'linotp.errors' in the LinOTP Config. Then the HTTP status defined by 'httperror' will ONLY be sent when the error that occurs in LinOTP matches one of the errors defined in 'linotp.errors'. In other cases '200 OK' with error code and description in the body will be returned. If 'linotp.errors' is unset all errors will cause responses with HTTP status 'httperror'. For example: Setup 1: * The client sends httperror=777 in the request * linotp.errors=233,567 Case 1.1: An exception is raised in LinOTP that has errId 233. - LinOTP will return a response with HTTP status 777. Case 1.2: An exception is raised with errId 555 - LinOTP will return a response with HTTP status 200. Setup 2: * The client sends httperror (empty) in the request * linotp.errors=233,567 Case 2.1: An exception is raised in LinOTP that has errId 233. - LinOTP will return a response with HTTP status 500. Case 2.2: An exception is raised with errId 555 - LinOTP will return a response with HTTP status 200. Setup 3: * The client sends httperror (empty) in the request * linotp.errors is not set Case 3.1: An exception is raised in LinOTP that has errId 233. - LinOTP will return a response with HTTP status 500. Case 3.2: An exception is raised with errId 555 - LinOTP will return a response with HTTP status 500. Setup 4: * NO httperror in request * linotp.errors=233,567 (or is unset, does not matter) Case 4.1: An exception is raised in LinOTP that has errId 233. - LinOTP will return a response with HTTP status 200. Case 4.2: An exception is raised with errId 555 - LinOTP will return a response with HTTP status 200. remark for 'context' parameter: the 'context' is especially required to catch errors from the _before_ methods. The return of a _before_ must be of type response and must have the attribute response._exception set, to stop further processing, which otherwise will have ugly results!! :param response: the pylon response object :type response: response object :param exception: should be a linotp exception (s. linotp.lib.error.py) :type exception: exception :param id: id value, for future versions :type id: int :param context: default is None or 'before' :type context: string :return: json rendered sting result :rtype: string ''' ret = '' errId = -311 ## handle the different types of exception: ## Exception, LinOtpError, str/unicode if hasattr(exception, '__class__') == True \ and isinstance(exception, Exception): errDesc = unicode(exception) if isinstance(exception, LinotpError): errId = exception.getId() elif type(exception) in [str, unicode]: errDesc = unicode(exception) else: errDesc = u"%r" % exception ## check if we have an additional request parameter 'httperror' ## which triggers the error to be delivered as HTTP Error httperror = _get_httperror_from_params(request) send_custom_http_status = False if httperror is not None: # Client wants custom HTTP status linotp_errors = c.linotpConfig.get('linotp.errors', None) if not linotp_errors: # Send custom HTTP status in every error case send_custom_http_status = True else: # Only send custom HTTP status in defined error cases if unicode(errId) in linotp_errors.split(','): send_custom_http_status = True else: send_custom_http_status = False if send_custom_http_status: # Send HTML response with HTTP status 'httperror' # Always set a reason, when no standard one found (e.g. custom HTTP # code like 444) use 'LinOTP Error' reason = httpErr.get(httperror, 'LinOTP Error') response.content_type = 'text/html' response.status = "%s %s" % (httperror, reason) code = httperror status = "%s %s" % (httperror, reason) desc = '[%s] %d: %s' % (get_version(), errId, errDesc) ret = resp % (code, status, code, status, desc) if context in ['before', 'after']: response._exception = exception response.text = u'' + ret ret = response else: # Send JSON response with HTTP status 200 OK response.content_type = 'application/json' res = { "jsonrpc": "2.0", "result" : {"status": False, "error": { "code" : errId, "message" : errDesc, }, }, "version": get_version(), "id": id } ret = json.dumps(res, indent=3) if context in ['before', 'after']: response._exception = exception response.body = ret ret = response return ret
def __before__(self, action): ''' This is the authentication to self service If you want to do ANYTHING with selfservice, you need to be authenticated. The _before_ is executed before any other function in this controller. ''' try: param = request.params audit.initialize() c.audit['success'] = False c.audit['client'] = get_client() c.version = get_version() c.licenseinfo = get_copyright_info() if isSelfTest(): log.debug("[__before__] Doing selftest!") uuser = getParam(param, "selftest_user", True) if uuser is not None: (c.user, _foo, c.realm) = uuser.rpartition('@') else: c.realm = "" c.user = "******" env = request.environ uuser = env.get('REMOTE_USER') if uuser is not None: (c.user, _foo, c.realm) = uuser.rpartition('@') if c.user in ['--u--']: abort(401, "No valid session") self.authUser = User(c.user, c.realm, '') log.debug("[__before__] authenticating as %s in realm %s!" % (c.user, c.realm)) else: identity = request.environ.get('repoze.who.identity') if identity is None: abort(401, "You are not authenticated") log.debug("[__before__] doing getAuthFromIdentity in action %s" % action) user_id = request.environ.get('repoze.who.identity')\ .get('repoze.who.userid') if type(user_id) == unicode: user_id = user_id.encode(ENCODING) identity = user_id.decode(ENCODING) log.debug("[__before__] getting identity from repoze.who: %r" % identity) (c.user, _foo, c.realm) = identity.rpartition('@') self.authUser = User(c.user, c.realm, '') log.debug("[__before__] set the self.authUser to: %s, %s " % (self.authUser.login, self.authUser.realm)) log.debug('[__before__] param for action %s: %s' % (action, param)) # checking the session if (False == check_selfservice_session(request.url, request.path, request.cookies, request.params )): c.audit['action'] = request.path[1:] c.audit['info'] = "session expired" audit.log(c.audit) abort(401, "No valid session") c.imprint = get_imprint(c.realm) c.tokenArray = [] c.user = self.authUser.login c.realm = self.authUser.realm c.tokenArray = getTokenForUser(self.authUser) # only the defined actions should be displayed # - remark: the generic actions like enrollTT are allready approved # to have a rendering section and included actions = getSelfserviceActions(self.authUser) c.actions = actions for policy in actions: if "=" in policy: (name, val) = policy.split('=') val = val.strip() # try if val is a simple numeric - # w.r.t. javascript evaluation try: nval = int(val) except: nval = val c.__setattr__(name.strip(), nval) c.dynamic_actions = add_dynamic_selfservice_enrollment(config, c.actions) # we require to establish all token local defined # policies to be initialiezd additional_policies = add_dynamic_selfservice_policies(config, actions) for policy in additional_policies: c.__setattr__(policy, -1) c.otplen = -1 c.totp_len = -1 return response except webob.exc.HTTPUnauthorized as acc: # the exception, when an abort() is called if forwarded log.info("[__before__::%r] webob.exception %r" % (action, acc)) log.info("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as e: log.error("[__before__] failed with error: %r" % e) log.error("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() return sendError(response, e, context='before') finally: log.debug('[__after__] done')
def sendResultIterator(obj, id=1, opt=None, rp=None, page=None): ''' sendResultIterator - return an json result document in a streamed mode :param obj: iterator of generator object like dict, string or list :param id: id value, for future versions :param opt: optional parameter, which allows to provide more detail :param rp: results per page :param page: number of page :return: generator of response data (yield) ''' res = {"jsonrpc": "2.0", "result": {"status": True, "value": "[DATA]", }, "version": get_version(), "id": id} err = {"jsonrpc": "2.0", "result": {"status": False, "error": {}, }, "version": get_version(), "id": id } start_at = 0 stop_at = 0 if page: if not rp: rp = 16 try: start_at = int(page) * int(rp) stop_at = start_at + int(rp) except ValueError as exx: err['result']['error'] = { "code": 9876, "message": "%r" % exx, } log.exception("failed to convert paging request parameters: %r" % exx) yield json.dumps(err) # finally we signal end of error result raise StopIteration() typ = "%s" % type(obj) if 'generator' not in typ and 'iterator' not in typ: raise Exception('no iterator method for object %r' % obj) res = {"jsonrpc": "2.0", "result": {"status": True, "value": "[DATA]", }, "version": get_version(), "id": id} if page: res['result']['page'] = int(page) if opt is not None and len(opt) > 0: res["detail"] = opt surrounding = json.dumps(res) prefix, postfix = surrounding.split('"[DATA]"') # first return the opening yield prefix + " [" sep = "" counter = 0 for next_one in obj: counter = counter + 1 # are we running in paging mode? if page: if counter >= start_at and counter < stop_at: res = "%s%s\n" % (sep, next_one) sep = ',' yield res if counter >= stop_at: # stop iterating if we reached the last one of the page break else: # no paging - no limit res = "%s%s\n" % (sep, next_one) sep = ',' yield res log.debug('Result iteration finished!') # we add the amount of queried objects total = '"queried" : %d' % counter postfix = ', %s %s' % (total, postfix) # last return the closing yield "] " + postfix
def __before__(self, action): ''' This is the authentication to self service. If you want to do ANYTHING with the selfservice, you need to be authenticated. The _before_ is executed before any other function in this controller. ''' try: c.audit = request_context['audit'] c.audit['success'] = False c.audit['client'] = get_client(request) c.version = get_version() c.licenseinfo = get_copyright_info() request_context['Audit'] = audit (auth_type, auth_user) = get_auth_user(request) if not auth_user or auth_type not in ['repoze', 'selftest']: abort(401, "You are not authenticated") (c.user, _foo, c.realm) = auth_user.rpartition('@') self.authUser = User(c.user, c.realm, '') if auth_type == "repoze": # checking the session only for not_form_access actions if action not in self.form_access_methods: call_url = "selfservice/%s" % action valid_session = check_selfservice_session( url=call_url, cookies=request.cookies, params=request.params) if not valid_session: c.audit['action'] = request.path[1:] c.audit['info'] = "session expired" audit.log(c.audit) abort(401, "No valid session") c.imprint = get_imprint(c.realm) c.tokenArray = [] c.user = self.authUser.login c.realm = self.authUser.realm # only the defined actions should be displayed # - remark: the generic actions like enrollTT are allready approved # to have a rendering section and included actions = getSelfserviceActions(self.authUser) c.actions = actions for policy in actions: if policy: if "=" not in policy: c.__setattr__(policy, -1) else: (name, val) = policy.split('=') val = val.strip() # try if val is a simple numeric - # w.r.t. javascript evaluation try: nval = int(val) except: nval = val c.__setattr__(name.strip(), nval) c.dynamic_actions = add_dynamic_selfservice_enrollment( config, c.actions) # we require to establish all token local defined # policies to be initialiezd additional_policies = add_dynamic_selfservice_policies( config, actions) for policy in additional_policies: c.__setattr__(policy, -1) c.otplen = -1 c.totp_len = -1 return response except webob.exc.HTTPUnauthorized as acc: # the exception, when an abort() is called if forwarded log.info("[__before__::%r] webob.exception %r" % (action, acc)) log.info("[__before__] %s" % traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as e: log.exception("[__before__] failed with error: %r" % e) Session.rollback() Session.close() return sendError(response, e, context='before') finally: log.debug('[__after__] done')
def __before__(self, action, **params): log.debug("[__before__::%r]" % (action)) valid_request = False try: for key, value in params.items(): log.debug("[__before__::%r:%r]" % (key, value)) audit.initialize() c.audit['client'] = get_client() self.storage = config.get('openid_sql') getCookieExpire = int(config.get("linotpOpenID.CookieExpire", -1)) self.COOKIE_EXPIRE = 3600 if getCookieExpire >= 0: self.COOKIE_EXPIRE = getCookieExpire c.logged_in = False c.login = "" c.version = get_version() c.licenseinfo = get_copyright_info() http_host = request.environ.get("HTTP_HOST") log.debug("[__before__] Doing openid request from host %s" % http_host) if not is_valid_fqdn(http_host, split_port=True): err = "Bad hostname: %s" % http_host audit.log(c.audit) c.audit["action_detail"] = err log.error(err) raise HTTPBadRequest(err) self.BASEURL = request.environ.get( "wsgi.url_scheme") + "://" + http_host # check if the browser is logged in login = request.cookies.get(COOKIE_NAME) if login: c.logged_in = True ## default return for the __before__ and __after__ log.debug("[__before__::%r]" % (response)) valid_request = True return response except PolicyException as pex: log.error("[__before__::%r] policy exception %r" % (action, pex)) log.error("[__before__] %s" % traceback.format_exc()) return sendError(response, pex, context='before') except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.error("[__before__::%r] webob.exception %r" % (action, acc)) log.error("[__before__] %s" % traceback.format_exc()) raise acc except Exception as exx: log.error("[__before__::%r] exception %r" % (action, exx)) log.error("[__before__] %s" % traceback.format_exc()) return sendError(response, exx, context='before') finally: if valid_request is False: self.storage.session.rollback() self.storage.session.close() log.debug("[__before__::%r] done" % (action))
def __before__(self, action): ''' This is the authentication to self service. If you want to do ANYTHING with the selfservice, you need to be authenticated. The _before_ is executed before any other function in this controller. ''' self.redirect = None try: c.version = get_version() c.licenseinfo = get_copyright_info() c.audit = request_context['audit'] c.audit['success'] = False self.client = get_client(request) c.audit['client'] = self.client request_context['Audit'] = audit # -------------------------------------------------------------- -- # handle requests which dont require authetication if action in ['logout', 'custom_style']: return # -------------------------------------------------------------- -- # get the authenticated user auth_type, auth_user, auth_state = get_auth_user(request) # -------------------------------------------------------------- -- # handle not authenticated requests if not auth_user or auth_type not in ['user_selfservice']: if action in ['login']: return if action in ['index']: self.redirect = True redirect(url(controller='selfservice', action='login')) else: abort(403, "No valid session") # -------------------------------------------------------------- -- # handle authenticated requests # there is only one special case, which is the login that # could be forwarded to the index page if action in ['login']: if auth_state != 'authenticated': return self.redirect = True redirect(url(controller='selfservice', action='index')) # -------------------------------------------------------------- -- # in case of user_selfservice, an unauthenticated request should always go to login if auth_user and auth_type is 'user_selfservice' \ and auth_state is not 'authenticated': self.redirect = True redirect(url(controller='selfservice', action='login')) # futher processing with the authenticated user if auth_state != 'authenticated': abort(403, "No valid session") c.user = auth_user.login c.realm = auth_user.realm self.authUser = auth_user # -------------------------------------------------------------- -- # authenticated session verification if auth_type == 'user_selfservice': # checking the session only for not_form_access actions if action not in self.form_access_methods: valid_session = check_session(request, auth_user, self.client) if not valid_session: c.audit['action'] = request.path[1:] c.audit['info'] = "session expired" audit.log(c.audit) abort(403, "No valid session") # -------------------------------------------------------------- -- c.imprint = get_imprint(c.realm) c.tokenArray = [] c.user = self.authUser.login c.realm = self.authUser.realm # only the defined actions should be displayed # - remark: the generic actions like enrollTT are allready approved # to have a rendering section and included actions = getSelfserviceActions(self.authUser) c.actions = actions for policy in actions: if policy: if "=" not in policy: c.__setattr__(policy, -1) else: (name, val) = policy.split('=') val = val.strip() # try if val is a simple numeric - # w.r.t. javascript evaluation try: nval = int(val) except ValueError: nval = val c.__setattr__(name.strip(), nval) c.dynamic_actions = add_dynamic_selfservice_enrollment( config, c.actions) # we require to establish all token local defined # policies to be initialiezd additional_policies = add_dynamic_selfservice_policies( config, actions) for policy in additional_policies: c.__setattr__(policy, -1) c.otplen = -1 c.totp_len = -1 c.pin_policy = _get_auth_PinPolicy(user=self.authUser) return response except (webob.exc.HTTPUnauthorized, webob.exc.HTTPForbidden) as acc: # the exception, when an abort() is called if forwarded log.info("[__before__::%r] webob.exception %r" % (action, acc)) Session.rollback() Session.close() raise acc except HTTPFound as exx: raise exx except Exception as e: log.exception("[__before__] failed with error: %r" % e) Session.rollback() Session.close() return sendError(response, e, context='before')