def update(self, param, reset_failcount=True): ''' update - process the initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing ''' log.debug("[update] begin. Process the initialization parameters: param %r" % (param)) ## Remark: the otpKey is handled in the parent class val = getParam(param, "hashlib", optional) if val is not None: self.hashlibStr = val else: self.hashlibStr = 'sha1' ## check if the key_size id provided ## if not, we could derive it from the hashlib key_size = getParam(param, 'key_size', optional) if key_size is None: param['key_size'] = keylen.get(self.hashlibStr) param['hashlib'] = self.hashlibStr self.addToTokenInfo("hashlib", self.hashlibStr) TokenClass.update(self, param, reset_failcount) log.debug("[update] end. Processing the initialization parameters done.") return
def update(self, param): ## check for the required parameters if (self.hKeyRequired == True): getParam(param, "otpkey", required) TokenClass.update(self, param)
def update(self, param): # cko: changed for backward compat getParam(param, "pin", optional) if not param.has_key('otpkey'): param['genkey'] = 1 TokenClass.update(self, param)
def update(self, param, reset_failcount=True): ''' update - process the initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing ''' log.debug("[update] begin. Process the initialization parameters: param %r" % (param)) ## Remark: the otpKey is handled in the parent class val = getParam(param, "hashlib", optional) if val is not None: self.hashlibStr = val else: self.hashlibStr = 'sha1' ## check if the key_size id provided ## if not, we could derive it from the hashlib key_size = getParam(param, 'key_size', optional) if key_size == None: param['key_size'] = keylen.get(self.hashlibStr) param['hashlib'] = self.hashlibStr self.addToTokenInfo("hashlib", self.hashlibStr) TokenClass.update(self, param, reset_failcount) log.debug("[update] end. Processing the initialization parameters done.") return
def update(self, param): self.radiusServer = getParam(param, "radius.server", required) # if another OTP length would be specified in /admin/init this would # be overwritten by the parent class, which is ok. self.setOtpLen(6) val = getParam(param, "radius.local_checkpin", optional) if val is not None: self.radiusLocal_checkpin = val val = getParam(param, "radius.user", required) if val is not None: self.radiusUser = val val = getParam(param, "radius.secret", required) if val is not None: self.radiusSecret = val if self.radiusSecret == VOID_RADIUS_SECRET: log.warning("Usage of default radius secret is not recomended!!") TokenClass.update(self, param) # We need to write the secret! self.token.setHKey(binascii.hexlify(self.radiusSecret)) self.addToTokenInfo("radius.server", self.radiusServer) self.addToTokenInfo("radius.local_checkpin", self.radiusLocal_checkpin) self.addToTokenInfo("radius.user", self.radiusUser)
def checkid_submit(self): ''' This is called when the user accepts - hit the submit button - that he will login to the consumer ''' param = request.params log.debug("[checkid_submit] params: %s" % param) redirect_token = getParam(param, "redirect_token", required) verify_always = getParam(param, "verify_always", optional) r_url, site, handle = self.storage.get_redirect(redirect_token) self.storage.add_site(site, handle) # The user checked the box, that he wants not be bothered again in the future # the relying party will be added to the trusted root login, token = self._split_cookie() user = self.storage.get_user_by_token(token) c.audit['user'], c.audit['realm'] = user.split('@', 2) c.audit['success'] = True c.audit['action_detail'] = site if "always" == verify_always: log.debug("[checkid_submit] putting into trusted root: %s, %s" % (site, handle)) if "" != user: self.storage.add_trusted_root(user, site) log.debug("[checkid_submit] redirecting to %s" % r_url) redirect(r_url)
def setDefinition(self, param): """ handle name """ self.name = getParam(param, "name", required) # We should have no \. # This only leads to problems. nameExp = "^[A-Za-z0-9_\-]+$" if re.match(nameExp, self.name) is None: e = Exception("non conformant characters in resolver name: " + self.name + " (not in " + nameExp + ")") raise e # handle types self.type = getParam(param, "type", required) resolvertypes = get_resolver_types() if self.type not in resolvertypes: e = Exception("resolver type : %s not in %s" % (self.type, unicode(resolvertypes))) raise e resolvers = getResolverList(filter_resolver_type=self.type) for resolver in resolvers: if self.name.lower() == resolver.lower(): if self.name == resolver: continue e = Exception("resolver with similar name already exists: %s" % (resolver)) raise e resolver_config = get_resolver_classConfig(self.type) if self.type in resolver_config: config = resolver_config.get(self.type).get("config", {}) else: config = resolver_config for k in param: if k != "name" and k != "type": if k.startswith("type.") == True: key = k[len("type.") :] self.types[key] = param.get(k) elif k.startswith("desc.") == True: key = k[len("desc.") :] self.desc[key] = param.get(k) elif "session" == k: # supress session parameter pass else: self.data[k] = param.get(k) if k in config: self.types[k] = config.get(k) else: log.warn( "[setDefinition]: the passed key %r is not a " "parameter for the resolver %r" % (k, self.type) ) # now check if we have for every type def an parameter ok = self._sanityCheck() if ok != True: raise Exception("type definition does not match parameter! %s" % unicode(param)) return
def update(self, param): self.radiusServer = getParam(param, "radius.server", required) # if another OTP length would be specified in /admin/init this would # be overwritten by the parent class, which is ok. self.setOtpLen(6) val = getParam(param, "radius.local_checkpin", optional) if val is not None: self.radiusLocal_checkpin = val val = getParam(param, "radius.user", required) if val is not None: self.radiusUser = val val = getParam(param, "radius.secret", required) if val is not None: self.radiusSecret = val if self.radiusSecret == VOID_RADIUS_SECRET: log.warning("Usage of default radius secret is not recomended!!") TokenClass.update(self, param) # We need to write the secret! self.setOtpKey(binascii.hexlify(self.radiusSecret)) self.addToTokenInfo("radius.server", self.radiusServer) self.addToTokenInfo("radius.local_checkpin", self.radiusLocal_checkpin) self.addToTokenInfo("radius.user", self.radiusUser)
def __after__( self, action, ): ''' ''' param = request.params try: if c.audit['action'] in ['selfservice/index']: if isSelfTest(): log.debug("[__after__] Doing selftest!") suser = getParam(param, "selftest_user", True) if suser is not None: (c.user, _foo, c.realm) = getParam(param, "selftest_user", True)\ .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('@') log.debug("[__after__] authenticating as %s in realm %s!" % (c.user, c.realm)) c.audit['user'] = c.user c.audit['realm'] = c.realm c.audit['success'] = True if 'serial' in param: c.audit['serial'] = param['serial'] c.audit['token_type'] = getTokenType(param['serial']) audit.log(c.audit) return response except webob.exc.HTTPUnauthorized as acc: # the exception, when an abort() is called if forwarded log.exception("[__after__::%r] webob.exception %r" % (action, acc)) Session.rollback() Session.close() raise acc except Exception as e: log.exception("[__after__] failed with error: %r" % e) Session.rollback() Session.close() return sendError(response, e, context='after') finally: log.debug('[__after__] done')
def __after__(self, action,): ''' ''' param = request.params try: if c.audit['action'] in ['selfservice/index']: if isSelfTest(): log.debug("[__after__] Doing selftest!") suser = getParam(param, "selftest_user", True) if suser is not None: (c.user, _foo, c.realm) = getParam(param, "selftest_user", True)\ .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('@') log.debug("[__after__] authenticating as %s in realm %s!" % (c.user, c.realm)) c.audit['user'] = c.user c.audit['realm'] = c.realm c.audit['success'] = True if 'serial' in param: c.audit['serial'] = param['serial'] c.audit['token_type'] = getTokenType(param['serial']) audit.log(c.audit) return response except webob.exc.HTTPUnauthorized as acc: # the exception, when an abort() is called if forwarded log.error("[__after__::%r] webob.exception %r" % (action, acc)) log.error("[__after__] %s" % traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as e: log.error("[__after__] failed with error: %r" % e) log.error("[__after__] %s" % traceback.format_exc()) Session.rollback() Session.close() return sendError(response, e, context='after') finally: log.debug('[__after__] done')
def setDefinition(self, param): ''' handle name ''' self.name = getParam(param, 'name', required) # We should have no \. # This only leads to problems. nameExp = "^[A-Za-z0-9_\-]+$" if re.match(nameExp, self.name) is None: e = Exception("non conformant characters in resolver name: " + self.name + " (not in " + nameExp + ")") raise e # handle types self.type = getParam(param, 'type', required) resolvertypes = get_resolver_types() if self.type not in resolvertypes: e = Exception("resolver type : %s not in %s" % (self.type, unicode(resolvertypes))) raise e if similar_resolver_exists(self.name): raise Exception('resolver with similar name already exists (%s)' % self.name) resolver_config = get_resolver_classConfig(self.type) if self.type in resolver_config: config = resolver_config.get(self.type).get('config', {}) else: config = resolver_config for k in param: if k != 'name' and k != 'type': if k.startswith('type.') == True: key = k[len('type.'):] self.types[key] = param.get(k) elif k.startswith('desc.') == True: key = k[len('desc.'):] self.desc[key] = param.get(k) elif 'session' == k: # supress session parameter pass else: self.data[k] = param.get(k) if k in config: self.types[k] = config.get(k) else: log.warn("[setDefinition]: the passed key %r is not a " "parameter for the resolver %r" % (k, self.type)) # now check if we have for every type def an parameter ok = self._sanityCheck() if ok != True: raise Exception("type definition does not match parameter! %s" % unicode(param)) return
def update(self, param, reset_failcount=False): self.setSyncWindow(0) self.setOtpLen(32) self.setCounterWindow(0) tdesc = getParam(param, "description", optional) if tdesc is not None: self.token.setDescription(tdesc) # requested_phase must be either "registration1" or "registration2" # current_phase is either "registration" or "authentication" requested_phase = getParam(param, "phase", optional) current_phase = self.getFromTokenInfo("phase", None) if requested_phase == "registration1" and current_phase is None: # This initial registration phase triggers a challenge # which is sent to the FIDO U2F compatible client device # Set the optional token pin in this first phase pin = getParam(param, "pin", optional) if pin is not None: TokenClass.setPin(self, pin) # preserve the registration state self.addToTokenInfo("phase", "registration") self.token.LinOtpIsactive = False elif requested_phase == "registration2" and current_phase == "registration": # Check the token pin pin = getParam(param, "pin", optional) if pin is None: pin = "" if check_pin(self, pin) is False: log.error("Wrong token pin!") raise ValueError("Wrong token pin!") # check for set phases which are not "registration1" or "registration2" elif requested_phase != "registration2" and requested_phase is not None: log.error("Wrong phase parameter!") raise Exception("Wrong phase parameter!") # only allow empty phase parameters once the token is registered successfully elif current_phase != "authentication" and requested_phase is None: log.error("Wrong phase parameter!") raise Exception("Wrong phase parameter!") # only allow "registration2" if the token already completed "registration1" elif current_phase != "registration" and requested_phase == "registration2": log.error( "Phase 'registration2' requested but we are not in the correct phase \ to process the request." ) raise Exception( "Phase 'registration2' requested but we are not in the correct phase \ to process the request." ) else: log.error('Unknown "phase" and "current_phase" parameter combination!') raise Exception('Unknown "phase" and "current_phase" parameter combination!')
def setDefinition(self, param): ''' handle name ''' self.name = getParam(param, 'name', required) # We should have no \. # This only leads to problems. nameExp = "^[A-Za-z0-9_\-]+$" if re.match(nameExp, self.name) is None: exx = Exception( "non conformant characters in resolver name: %s " " (not in %s)", self.name, nameExp) raise exx # handle types self.type = getParam(param, 'type', required) resolvertypes = get_resolver_types() if self.type not in resolvertypes: exx = Exception("resolver type : %s not in %s" % (self.type, unicode(resolvertypes))) raise exx resolver_config = get_resolver_class_config(self.type) if self.type in resolver_config: config = resolver_config.get(self.type).get('config', {}) else: config = resolver_config for k in param: if k != 'name' and k != 'type': if k.startswith('type.') is True: key = k[len('type.'):] self.types[key] = param.get(k) elif k.startswith('desc.') is True: key = k[len('desc.'):] self.desc[key] = param.get(k) elif 'session' == k: # supress session parameter pass else: self.data[k] = param.get(k) if k in config: self.types[k] = config.get(k) else: log.warn("[setDefinition]: the passed key %r is not a " "parameter for the resolver %r" % (k, self.type)) # now check if we have for every type def an parameter ok = self._sanityCheck() if ok is not True: raise Exception("type definition does not match parameter! %s" % unicode(param)) return
def update(self, param, reset_failcount=False): self.setSyncWindow(0) self.setOtpLen(32) self.setCounterWindow(0) tdesc = getParam(param, "description", optional) if tdesc is not None: self.token.setDescription(tdesc) # requested_phase must be either "registration1" or "registration2" # current_phase is either "registration" or "authentication" requested_phase = getParam(param, "phase", optional) current_phase = self.getFromTokenInfo('phase', None) if requested_phase == "registration1" and current_phase is None: # This initial registration phase triggers a challenge # which is sent to the FIDO U2F compatible client device # Set the optional token pin in this first phase pin = getParam(param, "pin", optional) if pin is not None: TokenClass.setPin(self, pin) # preserve the registration state self.addToTokenInfo('phase', 'registration') self.token.LinOtpIsactive = False elif requested_phase == "registration2" and current_phase == "registration": # Check the token pin pin = getParam(param, "pin", optional) if pin is None: pin = '' if check_pin(self, pin) is False: log.error("Wrong token pin!") raise ValueError("Wrong token pin!") # check for set phases which are not "registration1" or "registration2" elif requested_phase != "registration2" and requested_phase is not None: log.error('Wrong phase parameter!') raise Exception('Wrong phase parameter!') # only allow empty phase parameters once the token is registered successfully elif current_phase != "authentication" and requested_phase is None: log.error('Wrong phase parameter!') raise Exception('Wrong phase parameter!') # only allow "registration2" if the token already completed "registration1" elif current_phase != "registration" and requested_phase == "registration2": log.error( "Phase 'registration2' requested but we are not in the correct phase \ to process the request.") raise Exception( "Phase 'registration2' requested but we are not in the correct phase \ to process the request.") else: log.error( 'Unknown "phase" and "current_phase" parameter combination!') raise Exception( 'Unknown "phase" and "current_phase" parameter combination!')
def update(self, param): # cko: changed for backward compat getParam(param, "pin", optional) if not param.has_key('otpkey'): param['genkey'] = 1 # mark this spass token as usable exactly once if param.has_key('onetime'): TokenClass.set_count_auth_success_max(self, 1) TokenClass.update(self, param)
def update(self, param): # cko: changed for backward compat getParam(param, "pin", optional) if not param.has_key("otpkey"): param["genkey"] = 1 ## mark this spass token as usable exactly once if param.has_key("onetime"): TokenClass.set_count_auth_success_max(self, 1) TokenClass.update(self, param)
def update(self, param): ## check for the required parameters if (self.hKeyRequired == True): getParam(param, "otpkey", required) TokenClass.update(self, param, reset_failcount=False) for key in ["vasco_appl", "vasco_type", "vasco_auth"]: val = getParam(param, key, optional) if val is not None: self.addToTokenInfo(key, val)
def check_yubikey(self): ''' This function is used to validate the output of a yubikey method: validate/check_yubikey :param pass: The password that consist of the static yubikey prefix and the otp :type pass: string :return: JSON Object returns: JSON response:: { "version": "LinOTP 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": false }, "detail" : { "username": username, "realm": realm }, "id": 0 } ''' param = request.params passw = getParam(param, "pass", required) try: ok = False try: ok, opt = checkYubikeyPass(passw) c.audit['success'] = ok except AuthorizeException as exx: log.warning("[check_yubikey] authorization failed for validate/check_yubikey: %r" % exx) c.audit['success'] = False c.audit['info'] = unicode(exx) ok = False Session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.error("[check_yubikey] validate/check_yubikey failed: %r" % exx) log.error("[check_yubikey] %s" % traceback.format_exc()) c.audit['info'] = unicode(exx) Session.rollback() return sendError(response, u"validate/check_yubikey failed: %s" % unicode(exx), 0) finally: Session.close() log.debug('[check_yubikey] done')
def getUserFromRequest(request, config=None): ''' This function first tries to get the user from * a DigestAuth and otherwise from * basic auth and otherwise from * the client certificate ''' d_auth = {'login': ''} param = request.params try: # Do BasicAuth if 'REMOTE_USER' in request.environ: d_auth['login'] = request.environ['REMOTE_USER'] log.debug( "[getUserFromRequest] BasicAuth: found the " "REMOTE_USER: %r", d_auth) # Do DigestAuth elif 'HTTP_AUTHORIZATION' in request.environ: a_auth = request.environ['HTTP_AUTHORIZATION'].split(",") for field in a_auth: (key, _delimiter, value) = field.partition("=") d_auth[key.lstrip(' ')] = value.strip('"') d_auth['login'] = d_auth.get('Digest username', '') or '' log.debug( "[getUserFromRequest] DigestAuth: found " "this HTTP_AUTHORIZATION: %r", d_auth) # Do SSL Client Cert elif 'SSL_CLIENT_S_DN_CN' in request.environ: d_auth['login'] = request.environ.get('SSL_CLIENT_S_DN_CN', '') log.debug( "[getUserFromRequest] SSLClientCert Auth: found " "this SSL_CLIENT_S_DN_CN: %r", d_auth) # In case of selftest self_test = isSelfTest(config=config) log.debug("[getUserFromRequest] Doing selftest!: %r", self_test) if self_test: log.debug("[getUserFromRequest] Doing selftest!") param = request.params login = getParam(param, "selftest_admin", True) if login: d_auth['login'] = login log.debug( "[getUserFromRequest] Found selfservice user: %r in " "the request.", d_auth) except Exception as exx: log.exception( "[getUserFromRequest] An error occurred when trying" " to fetch the user from the request: %r", exx) return d_auth
def check_yubikey(self): ''' This function is used to validate the output of a yubikey method: validate/check_yubikey :param pass: The password that consist of the static yubikey prefix and the otp :type pass: string :return: JSON Object returns: JSON response:: { "version": "LinOTP 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": false }, "detail" : { "username": username, "realm": realm }, "id": 0 } ''' param = request.params passw = getParam(param, "pass", required) try: ok = False try: vh = ValidationHandler() ok, opt = vh.checkYubikeyPass(passw) c.audit['success'] = ok except AuthorizeException as exx: log.warning( "[check_yubikey] authorization failed for validate/check_yubikey: %r" % exx) c.audit['success'] = False c.audit['info'] = unicode(exx) ok = False Session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("[check_yubikey] validate/check_yubikey failed: %r" % exx) c.audit['info'] = unicode(exx) Session.rollback() return sendResult(response, False, 0) finally: Session.close()
def update(self, param, reset_failcount=True): ''' update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing ''' log.debug("[update] begin. adjust the token class with: param %r" % (param)) # specific - phone phone = getParam(param, "phone", required) self.setPhone(phone) # # in case of the sms token, only the server must know the otpkey # # thus if none is provided, we let create one (in the TokenClass) if not param.has_key('genkey') and not param.has_key('otpkey'): param['genkey'] = 1 HmacTokenClass.update(self, param, reset_failcount) log.debug("[update] end. all token parameters are set.") return
def tokeninfo(self): ''' this returns the contents of /admin/show?serial=xyz in a html format ''' param = request.params try: serial = getParam(param, 'serial', required) filterRealm = "" # check admin authorization res = checkPolicyPre('admin', 'show', param) filterRealm = res['realms'] # check if policies are active at all # If they are not active, we are allowed to SHOW any tokens. pol = getAdminPolicies("show") if not pol['active']: filterRealm = ["*"] log.info("[tokeninfo] admin >%s< may display the following realms: %s" % (res['admin'], filterRealm)) log.info("[tokeninfo] displaying tokens: serial: %s", serial) toks = TokenIterator(User("", "", ""), serial, filterRealm=filterRealm) ### now row by row lines = [] for tok in toks: lines.append(tok) if len(lines) > 0: c.tokeninfo = lines[0] else: c.tokeninfo = {} for k in c.tokeninfo: if "LinOtp.TokenInfo" == k: try: # Try to convert string to Dictionary c.tokeninfo['LinOtp.TokenInfo'] = json.loads(c.tokeninfo['LinOtp.TokenInfo']) except: pass return render('/manage/tokeninfo.mako') except PolicyException as pe: log.error("[tokeninfo] Error during checking policies: %r" % pe) log.error("[tokeninfo] %s" % traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("[tokeninfo] failed! %r" % e) log.error("[tokeninfo] %s" % traceback.format_exc()) Session.rollback() return sendError(response, e) finally: Session.close() log.debug('[tokeninfo] done')
def update(self, param, reset_failcount=True): """ update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing """ LOG.debug("[update] begin. adjust the token class with: param %r" % param) # specific - e-mail self._email_address = getParam(param, self.EMAIL_ADDRESS_KEY, optional=False) ## in case of the e-mail token, only the server must know the otpkey ## thus if none is provided, we let create one (in the TokenClass) if not 'genkey' in param and not 'otpkey' in param: param['genkey'] = 1 HmacTokenClass.update(self, param, reset_failcount) LOG.debug("[update] end. all token parameters are set.") return
def update(self, param, reset_failcount=True): ''' update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing ''' log.debug("[update] begin. adjust the token class with: param %r" % (param)) # specific - phone phone = getParam(param, "phone", required) self.setPhone(phone) ## in case of the sms token, only the server must know the otpkey ## thus if none is provided, we let create one (in the TokenClass) if not param.has_key('genkey') and not param.has_key('otpkey'): param['genkey'] = 1 HmacTokenClass.update(self, param, reset_failcount) log.debug("[update] end. all token parameters are set.") return
def tokeninfo(self): """ this returns the contents of /admin/show?serial=xyz in a html format """ param = request.params try: serial = getParam(param, "serial", required) filterRealm = "" # check admin authorization res = checkPolicyPre("admin", "show", param) filterRealm = res["realms"] # check if policies are active at all # If they are not active, we are allowed to SHOW any tokens. pol = getAdminPolicies("show") if not pol["active"]: filterRealm = ["*"] log.info("[tokeninfo] admin >%s< may display the following realms: %s" % (res["admin"], filterRealm)) log.info("[tokeninfo] displaying tokens: serial: %s", serial) toks = TokenIterator(User("", "", ""), serial, filterRealm=filterRealm) ### now row by row lines = [] for tok in toks: lines.append(tok) if len(lines) > 0: c.tokeninfo = lines[0] else: c.tokeninfo = {} for k in c.tokeninfo: if "LinOtp.TokenInfo" == k: try: # Try to convert string to Dictionary c.tokeninfo["LinOtp.TokenInfo"] = json.loads(c.tokeninfo["LinOtp.TokenInfo"]) except: pass return render("/manage/tokeninfo.mako") except PolicyException as pe: log.error("[tokeninfo] Error during checking policies: %r" % pe) log.error("[tokeninfo] %s" % traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("[tokeninfo] failed! %r" % e) log.error("[tokeninfo] %s" % traceback.format_exc()) Session.rollback() return sendError(response, e) finally: Session.close() log.debug("[tokeninfo] done")
def tokeninfo(self): ''' this returns the contents of /admin/show?serial=xyz in an html format ''' param = request.params try: serial = getParam(param, 'serial', required) filterRealm = "" # check admin authorization res = checkPolicyPre('admin', 'show', param) # check if policies are active at all # If they are not active, we are allowed to SHOW any tokens. filterRealm = ["*"] if res['active'] and res['realms']: filterRealm = res['realms'] log.info("[tokeninfo] admin >%s< may display the following realms:" " %s" % (res['admin'], filterRealm)) log.info("[tokeninfo] displaying tokens: serial: %s", serial) toks = TokenIterator(User("", "", ""), serial, filterRealm=filterRealm) # now row by row lines = [] for tok in toks: lines.append(tok) if len(lines) > 0: c.tokeninfo = lines[0] else: c.tokeninfo = {} for k in c.tokeninfo: if "LinOtp.TokenInfo" == k: try: # Try to convert string to Dictionary c.tokeninfo['LinOtp.TokenInfo'] = json.loads( c.tokeninfo['LinOtp.TokenInfo']) except: pass return render('/manage/tokeninfo.mako') except PolicyException as pe: log.exception("[tokeninfo] Error during checking policies: %r" % pe) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.exception("[tokeninfo] failed! %r" % e) Session.rollback() return sendError(response, e) finally: Session.close() log.debug('[tokeninfo] done')
def getUserFromRequest(request): ''' This function first tries to get the user from * a DigestAuth and otherwise from * basic auth and otherwise from * the client certificate ''' d_auth = {'login': ''} param = request.params try: # Do BasicAuth if request.environ.has_key('REMOTE_USER'): d_auth['login'] = request.environ['REMOTE_USER'] log.debug("[getUserFromRequest] BasicAuth: found the " "REMOTE_USER: %r" % d_auth) # Do DigestAuth elif request.environ.has_key('HTTP_AUTHORIZATION'): a_auth = request.environ['HTTP_AUTHORIZATION'].split(",") for field in a_auth: (key, _delimiter, value) = field.partition("=") d_auth[key.lstrip(' ')] = value.strip('"') if d_auth.has_key('Digest username'): d_auth['login'] = d_auth['Digest username'] log.debug("[getUserFromRequest] DigestAuth: found " "this HTTP_AUTHORIZATION: %r" % d_auth) # Do SSL Client Cert elif request.environ.has_key('SSL_CLIENT_S_DN_CN'): d_auth['login'] = request.environ.get('SSL_CLIENT_S_DN_CN') log.debug("[getUserFromRequest] SSLClientCert Auth: found " "this SSL_CLIENT_S_DN_CN: %r" % d_auth) # In case of selftest log.debug("[getUserFromRequest] Doing selftest!: %r" % isSelfTest()) if isSelfTest(): log.debug("[getUserFromRequest] Doing selftest!") param = request.params d_auth['login'] = getParam(param, "selftest_admin", True) log.debug( "[getUserFromRequest] Found the user: %r in the request." % d_auth) except Exception as e: log.error( "[getUserFromRequest] An error occurred when trying to fetch " "the user from the request: %r" % e) pass return d_auth
def getUserFromParam(param, optionalOrRequired, optional=False, required=False): realm = "" conf = "" if optional: optionalOrRequired = True if required: optionalOrRequired = False log.debug("[getUserFromParam] entering function") user = getParam(param, "user", optionalOrRequired) log.debug("[getUserFromParam] got user <<%r>>" % user) if user is None: user = "" else: splitAtSign = getFromConfig("splitAtSign", "true") if splitAtSign.lower() == "true": (user, realm) = splitUser(user) if "realm" in param: realm = param["realm"] if user != "": if realm is None or realm == "": realm = getDefaultRealm() usr = User(user, realm, "") if "resConf" in param: conf = param["resConf"] # with the short resolvernames, we have to extract the # configuration name from the resolver spec if "(" in conf and ")" in conf: res_conf, resolver_typ = conf.split(" ") conf = res_conf usr.conf = conf else: if len(usr.login) > 0 or len(usr.realm) > 0 or len(usr.conf) > 0: res = getResolversOfUser(usr) usr.saveResolvers(res) if len(res) > 1: log.error("[getUserFromParam] user %r@%r in more than one " "resolver: %r" % (user, realm, res)) raise Exception("The user %s@%s is in more than one resolver:" " %s" % (user, realm, unicode(res))) log.debug("[getUserFromParam] creating user object %r,%r,%r" % (user, realm, conf)) log.debug("[getUserFromParam] created user object %r " % usr) return usr
def check_t(self): param = {} value = {} ok = False opt = None try: param.update(request.params) passw = getParam(param, "pass", required) transid = param.get('state', None) if transid is not None: param['transactionid'] = transid del param['state'] if transid is None: transid = param.get('transactionid', None) if transid is None: raise Exception("missing parameter: state or transactionid!") vh = ValidationHandler() (ok, reply) = vh.check_by_transactionid(transid=transid, passw=passw, options=param) value['value'] = ok value['failcount'] = int(reply.get('failcount', 0)) 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, value, 1, opt=opt) except Exception as exx: log.exception("[check_t] validate/check_t failed: %r" % exx) c.audit['info'] = unicode(exx) Session.rollback() return sendResult(response, False, 0) finally: Session.close() log.debug('[check_t] done')
def check_t(self): param = {} value = {} ok = False opt = {} try: param.update(request.params) passw = getParam(param, "pass", required) transid = param.get('state', None) if transid is not None: param['transactionid'] = transid del param['state'] if transid is None: transid = param.get('transactionid', None) if transid is None: raise Exception("missing parameter: state or transactionid!") vh = ValidationHandler() (ok, opt) = vh.check_by_transactionid(transid=transid, passw=passw, options=param) value['value'] = ok value['failcount'] = int(opt.get('failcount', 0)) 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, value, 1, opt=opt) except Exception as exx: log.exception("[check_t] validate/check_t failed: %r" % exx) c.audit['info'] = unicode(exx) Session.rollback() return sendResult(response, False, 0) finally: Session.close() log.debug('[check_t] done')
def getUserFromRequest(request, config=None): ''' This function first tries to get the user from * a DigestAuth and otherwise from * basic auth and otherwise from * the client certificate ''' d_auth = {'login': ''} param = request.params try: # Do BasicAuth if 'REMOTE_USER' in request.environ: d_auth['login'] = request.environ['REMOTE_USER'] log.debug("[getUserFromRequest] BasicAuth: found the " "REMOTE_USER: %r", d_auth) # Do DigestAuth elif 'HTTP_AUTHORIZATION' in request.environ: a_auth = request.environ['HTTP_AUTHORIZATION'].split(",") for field in a_auth: (key, _delimiter, value) = field.partition("=") d_auth[key.lstrip(' ')] = value.strip('"') d_auth['login'] = d_auth.get('Digest username', '') or '' log.debug("[getUserFromRequest] DigestAuth: found " "this HTTP_AUTHORIZATION: %r", d_auth) # Do SSL Client Cert elif 'SSL_CLIENT_S_DN_CN' in request.environ: d_auth['login'] = request.environ.get('SSL_CLIENT_S_DN_CN', '') log.debug("[getUserFromRequest] SSLClientCert Auth: found " "this SSL_CLIENT_S_DN_CN: %r", d_auth) # In case of selftest self_test = isSelfTest(config=config) log.debug("[getUserFromRequest] Doing selftest!: %r", self_test) if self_test: log.debug("[getUserFromRequest] Doing selftest!") param = request.params login = getParam(param, "selftest_admin", True) if login: d_auth['login'] = login log.debug("[getUserFromRequest] Found selfservice user: %r in " "the request.", d_auth) except Exception as exx: log.exception("[getUserFromRequest] An error occurred when trying" " to fetch the user from the request: %r", exx) return d_auth
def getUserFromRequest(request): ''' This function first tries to get the user from * a DigestAuth and otherwise from * basic auth and otherwise from * the client certificate ''' d_auth = { 'login' : '' } param = request.params try: # Do BasicAuth if request.environ.has_key('REMOTE_USER'): d_auth['login'] = request.environ['REMOTE_USER'] log.debug("[getUserFromRequest] BasicAuth: found the " "REMOTE_USER: %r" % d_auth) # Do DigestAuth elif request.environ.has_key('HTTP_AUTHORIZATION'): a_auth = request.environ['HTTP_AUTHORIZATION'].split(",") for field in a_auth: (key, _delimiter, value) = field.partition("=") d_auth[key.lstrip(' ')] = value.strip('"') if d_auth.has_key('Digest username'): d_auth['login'] = d_auth['Digest username'] log.debug("[getUserFromRequest] DigestAuth: found " "this HTTP_AUTHORIZATION: %r" % d_auth) # Do SSL Client Cert elif request.environ.has_key('SSL_CLIENT_S_DN_CN'): d_auth['login'] = request.environ.get('SSL_CLIENT_S_DN_CN') log.debug("[getUserFromRequest] SSLClientCert Auth: found " "this SSL_CLIENT_S_DN_CN: %r" % d_auth) # In case of selftest log.debug("[getUserFromRequest] Doing selftest!: %r" % isSelfTest()) if isSelfTest(): log.debug("[getUserFromRequest] Doing selftest!") param = request.params d_auth['login'] = getParam(param, "selftest_admin", True) log.debug("[getUserFromRequest] Found the user: %r in the request." % d_auth) except Exception as e: log.exception("[getUserFromRequest] An error occurred when trying to fetch " "the user from the request: %r" % e) pass return d_auth
def getUserFromParam(param, optionalOrRequired, optional=False, required=False): realm = "" # TODO: merge result - could this be removed if optional: optionalOrRequired = True if required: optionalOrRequired = False log.debug("[getUserFromParam] entering function") user = getParam(param, "user", optionalOrRequired) log.debug("[getUserFromParam] got user <<%r>>", user) if user is None: user = "" else: splitAtSign = getFromConfig("splitAtSign", "true") if splitAtSign.lower() == "true": (user, realm) = splitUser(user) if "realm" in param: realm = param["realm"] if user != "": if not realm: realm = getDefaultRealm() usr = User(user, realm, "") resolver_config_id = '' if "resConf" in param: resolver_config_identifier = param["resConf"] # with the short resolvernames, we have to extract the # configuration name from the resolver spec if "(" in resolver_config_identifier and \ ")" in resolver_config_identifier: resolver_config_id, __ = resolver_config_identifier.split(" ") usr.resolver_config_identifier = resolver_config_id else: if len(usr.login) > 0 or \ len(usr.realm) > 0 or \ len(usr.resolver_config_identifier) > 0: res = getResolversOfUser(usr) usr.saveResolvers(res) log.debug("[getUserFromParam] creating user object %r,%r,%r", user, realm, resolver_config_id) log.debug("[getUserFromParam] created user object %r ", usr) return usr
def update(self, param, reset_failcount=True): ''' update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing ''' getParam(param, "otpkey", required) ## motp token specific otpPin = getParam(param, "otppin", required) self.setUserPin(otpPin) TokenClass.update(self, param, reset_failcount) return
def getUserFromParam(param, optionalOrRequired, optional=False, required=False): realm = "" conf = "" if optional: optionalOrRequired = True if required: optionalOrRequired = False log.debug("[getUserFromParam] entering function") user = getParam(param, "user", optionalOrRequired) log.debug("[getUserFromParam] got user <<%r>>" % user) if user is None: user = "" else: splitAtSign = getFromConfig("splitAtSign", "true") if splitAtSign.lower() == "true": (user, realm) = splitUser(user) if "realm" in param: realm = param["realm"] if user != "": if realm is None or realm == "" : realm = getDefaultRealm() usr = User(user, realm, "") if "resConf" in param: conf = param["resConf"] # with the short resolvernames, we have to extract the # configuration name from the resolver spec if "(" in conf and ")" in conf: res_conf, resolver_typ = conf.split(" ") conf = res_conf usr.conf = conf else: if len(usr.login) > 0 or len(usr.realm) > 0 or len(usr.conf) > 0: res = getResolversOfUser(usr) usr.saveResolvers(res) if len(res) > 1: log.error("[getUserFromParam] user %r@%r in more than one " "resolver: %r" % (user, realm, res)) raise Exception("The user %s@%s is in more than one resolver:" " %s" % (user, realm, unicode(res))) log.debug("[getUserFromParam] creating user object %r,%r,%r" % (user, realm, conf)) log.debug("[getUserFromParam] created user object %r " % usr) return usr
def update(self, param, reset_failcount=True): ''' update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing ''' log.debug("[update] begin. adjust the token class with: param %r" % (param)) getParam(param, "otpkey", required) ## motp token specific otpPin = getParam(param, "otppin", required) self.token.setUserPin(otpPin) TokenClass.update(self, param, reset_failcount) log.debug("[update] all token parameters are set.") return
def update(self, param): tokenid = getParam(param, "yubico.tokenid", required) if len(tokenid) < YUBICO_LEN_ID: log.error("[update] The token ID needs to be %i characters long!" % YUBICO_LEN_ID) raise Exception("The YubiKey token ID needs to be %i characters long!" % YUBICO_LEN_ID) if len(tokenid) > YUBICO_LEN_ID: tokenid = tokenid[:YUBICO_LEN_ID] self.tokenid = tokenid self.setOtpLen(44) TokenClass.update(self, param) self.addToTokenInfo("yubico.tokenid", self.tokenid) return
def update(self, param): tokenid = getParam(param, "yubico.tokenid", required) if len(tokenid) < YUBICO_LEN_ID: log.error("[update] The tokenid needs to be %i characters long!" % YUBICO_LEN_ID) raise Exception("The Yubikey token ID needs to be %i characters long!" % YUBICO_LEN_ID) if len(tokenid) > YUBICO_LEN_ID: tokenid = tokenid[:YUBICO_LEN_ID] self.tokenid = tokenid self.setOtpLen(44) TokenClass.update(self, param) self.addToTokenInfo("yubico.tokenid", self.tokenid) return
def update(self, param, reset_failcount=True): ''' update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing ''' _ = context['translate'] log.debug("[update] begin. adjust the token class with: param %r" % (param)) # specific - phone phone = getParam(param, "phone", required) # in scope selfservice - check if edit_sms is allowed # if not allowed to edit, check if the phone is the same # as from the user data if param.get('::scope::', {}).get('selfservice', False): user = param['::scope::']['user'] if not is_phone_editable(user): u_info = getUserDetail(user) u_phone = u_info.get('mobile', u_info.get('phone', None)) if u_phone != phone: raise Exception( _('User is not allowed to ' 'set phone number')) self.setPhone(phone) # in case of the sms token, only the server must know the otpkey # thus if none is provided, we let create one (in the TokenClass) if 'genkey' not in param and 'otpkey' not in param: param['genkey'] = 1 HmacTokenClass.update(self, param, reset_failcount) log.debug("[update] end. all token parameters are set.") return
def update(self, param, reset_failcount=True): ''' update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing ''' _ = context['translate'] log.debug("[update] begin. adjust the token class with: param %r" % (param)) # specific - phone phone = getParam(param, "phone", required) # in scope selfservice - check if edit_sms is allowed # if not allowed to edit, check if the phone is the same # as from the user data if param.get('::scope::', {}).get('selfservice', False): user = param['::scope::']['user'] if not is_phone_editable(user): u_info = getUserDetail(user) u_phone = u_info.get('mobile', u_info.get('phone', None)) if u_phone != phone: raise Exception(_('User is not allowed to ' 'set phone number')) self.setPhone(phone) # in case of the sms token, only the server must know the otpkey # thus if none is provided, we let create one (in the TokenClass) if 'genkey' not in param and 'otpkey' not in param: param['genkey'] = 1 HmacTokenClass.update(self, param, reset_failcount) log.debug("[update] end. all token parameters are set.") return
def update(self, param, reset_failcount=True): """ update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing """ log.debug("[update] begin. adjust the token class with: param %r" % (param)) # specific - phone phone = getParam(param, "phone", required) # in scope selfservice - check if edit_sms is allowed # if not allowed to edit, check if the phone is the same # as from the user data if param.get("::scope::", {}).get("selfservice", False): user = param["::scope::"]["user"] if not is_phone_editable(user): u_info = getUserDetail(user) u_phone = u_info.get("mobile", u_info.get("phone", None)) if u_phone != phone: raise Exception(_("User is not allowed to " "set phone number")) self.setPhone(phone) # in case of the sms token, only the server must know the otpkey # thus if none is provided, we let create one (in the TokenClass) if "genkey" not in param and "otpkey" not in param: param["genkey"] = 1 HmacTokenClass.update(self, param, reset_failcount) log.debug("[update] end. all token parameters are set.") return
def update(self, param): """ second phase of the init process - updates parameters :param param: the request parameters :return: - nothing - """ self.remoteServer = getParam(param, "remote.server", required) # if another OTP length would be specified in /admin/init this would # be overwritten by the parent class, which is ok. self.setOtpLen(6) val = getParam(param, "remote.local_checkpin", optional) if val is not None: self.remoteLocalCheckpin = val val = getParam(param, "remote.serial", optional) if val is not None: self.remoteSerial = val val = getParam(param, "remote.user", optional) if val is not None: self.remoteUser = val val = getParam(param, "remote.realm", optional) if val is not None: self.remoteRealm = val val = getParam(param, "remote.resConf", optional) if val is not None: self.remoteResConf = val TokenClass.update(self, param) self.addToTokenInfo("remote.server", self.remoteServer) self.addToTokenInfo("remote.serial", self.remoteSerial) self.addToTokenInfo("remote.user", self.remoteUser) self.addToTokenInfo("remote.local_checkpin", self.remoteLocalCheckpin) self.addToTokenInfo("remote.realm", self.remoteRealm) self.addToTokenInfo("remote.resConf", self.remoteResConf) return
def getInitDetail(self, params, user=None): """ to complete the token normalisation, the response of the initialisation should be built by the token specific method, the getInitDetails """ response_detail = {} info = self.getInfo() response_detail.update(info) response_detail['serial'] = self.getSerial() # get requested phase requested_phase = getParam(params, "phase", optional=False) if requested_phase == "registration1": # We are in registration phase 1 # We create a 32 bytes otp key (from urandom) # which is used as the registration challenge challenge = base64.urlsafe_b64encode(binascii.unhexlify(self._genOtpKey_(32))) self.addToTokenInfo('challenge', challenge) # save the appId to the TokenInfo # An appId passed as parameter is preferred over an appId defined in a policy appId = '' if 'appid' in params: appId = params.get('appid') else: # No appId passed as parameter - fall back to the policy # Get the appId as specified in the enrollment policy 'u2f_app_id' # for the specific realm # If the token has multiple realms, the appIds are checked for conflicts. # It could be discussed whether the token should use the appId of the default # realm, when the token is not attached to any realms realms = self.token.getRealmNames() for realm in realms: get_policy_params = { 'action': 'u2f_app_id', 'scope': 'enrollment', 'realm': realm } policy_value = getPolicyActionValue(getPolicy(get_policy_params), 'u2f_app_id', String=True ) # Check for appId conflicts if appId and policy_value: if appId != policy_value: log.error("Conflicting appId values in u2f policies.") raise Exception("Conflicting appId values in u2f policies.") appId = policy_value if not appId: log.error("No appId defined.") raise Exception("No appId defined.") self.addToTokenInfo('appId', appId) # create U2F RegisterRequest object and append it to the response as 'message' appId = self._get_app_id() register_request = {'challenge': challenge, 'version': 'U2F_V2', 'appId': appId } response_detail['registerrequest'] = register_request elif requested_phase == "registration2": # We are in registration phase 2 # process the data generated by the u2f compatible token device registerResponse = "" otpkey = None if 'otpkey' in params: otpkey = params.get('otpkey') if otpkey is not None: # otpkey holds the JSON RegisterResponse object as specified by the FIDO Alliance try: registerResponse = json.loads(otpkey) except ValueError as ex: log.error("Invalid JSON format - value error %r", (ex)) raise Exception('Invalid JSON format') try: registrationData = registerResponse['registrationData'] clientData = registerResponse['clientData'] except AttributeError as ex: log.error( "Couldn't find keyword in JSON object - attribute error %r ", (ex)) raise Exception("Couldn't find keyword in JSON object") # registrationData and clientData are urlsafe base64 encoded # correct padding errors (length should be multiples of 4) # fill up the registrationData with '=' to the correct padding registrationData = registrationData + \ ('=' * (4 - (len(registrationData) % 4))) clientData = clientData + ('=' * (4 - (len(clientData) % 4))) registrationData = base64.urlsafe_b64decode( registrationData.encode('ascii')) clientData = base64.urlsafe_b64decode(clientData.encode('ascii')) # parse the raw registrationData according to the specification (userPublicKey, keyHandle, X509cert, signature) = \ self._parseRegistrationData(registrationData) # check the received clientData object if not self._checkClientData( clientData, 'registration', self.getFromTokenInfo('challenge', None)): raise ValueError("Received invalid clientData object. Aborting...") # prepare the applicationParameter and challengeParameter needed for # verification of the registration signature appId = self._get_app_id() applicationParameter = sha256(appId).digest() challengeParameter = sha256(clientData).digest() # verify the registration signature self._validateRegistrationSignature(applicationParameter, challengeParameter, keyHandle, userPublicKey, X509cert, signature ) # save the key handle and the user public key in the Tokeninfo field for # future use self.addToTokenInfo('keyHandle', base64.urlsafe_b64encode(keyHandle)) self.addToTokenInfo('publicKey', base64.urlsafe_b64encode(userPublicKey)) self.addToTokenInfo('counter', '0') self.addToTokenInfo('phase', 'authentication') # remove the registration challenge from the token info self.removeFromTokenInfo('challenge') # Activate the token self.token.LinOtpIsactive = True else: log.error("No otpkey set!") raise ValueError("No otpkey set") else: log.error("Unsupported phase: %s", requested_phase) raise Exception("Unsupported phase: %s", requested_phase) return response_detail
def getDefinition(self, param): self.name = getParam(param, 'resolver', required) return getResolverInfo(self.name)
def getmultiotp(self): ''' This function is used to retrieve multiple otp values 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/getmultiotp arguments: serial - the serial number of the token count - number of otp values to return 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 = {} try: serial = getParam(param, "serial", required) count = int(getParam(param, "count", required)) curTime = getParam(param, "curTime", optional) view = getParam(param, "view", optional) r1 = checkPolicyPre('admin', 'getotp', param) log.debug("[getmultiotp] admin-getotp returned %s" % r1) max_count = checkPolicyPre('gettoken', 'max_count', param) log.debug("[getmultiotp] checkpolicypre returned %s" % max_count) if count > max_count: count = max_count log.debug("[getmultiotp] retrieving OTP value for token %s" % serial) ret = get_multi_otp(serial, count=int(count), curTime=curTime) ret["serial"] = serial c.audit['success'] = True Session.commit() if view: c.ret = ret return render('/manage/multiotp_view.mako') else: 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("[getmultiotp] gettoken/getmultiotp failed: %r" % e) log.error("[getmultiotp] %s" % traceback.format_exc()) Session.rollback() return sendError(response, "gettoken/getmultiotp failed: %s" % unicode(e), 0) finally: Session.close() log.debug("[getmultiotp] done")
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 getmultiotp(self): ''' This function is used to retrieve multiple otp values 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/getmultiotp arguments: serial - the serial number of the token count - number of otp values to return 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 = {} try: serial = getParam(param, "serial", required) count = int(getParam(param, "count", required)) curTime = getParam(param, "curTime", optional) view = getParam(param, "view", optional) r1 = checkPolicyPre('admin', 'getotp', param) log.debug("[getmultiotp] admin-getotp policy: %s", r1) max_count = checkPolicyPre('gettoken', 'max_count', param) log.debug("[getmultiotp] maxcount policy: %s", max_count) if count > max_count: count = max_count log.debug("[getmultiotp] retrieving OTP value for token %s", serial) ret = get_multi_otp(serial, count=int(count), curTime=curTime) ret["serial"] = serial g.audit['success'] = True db.session.commit() if view: c.ret = ret return render('/manage/multiotp_view.mako').decode('utf-8') else: 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("[getmultiotp] gettoken/getmultiotp failed: %r", exx) db.session.rollback() return sendError(response, "gettoken/getmultiotp failed: %r" % exx, 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 load_form(self): ''' This shows the enrollment form for a requested token type. implicit parameters are: :param type: token type :param scope: defines the rendering scope :return: rendered html of the requested token ''' res = '' param = {} try: param.update(request.params) act = getParam(param, "type", required) try: (tok, section, scope) = act.split('.') except Exception: return res if section != 'selfservice': return res g = config['pylons.app_globals'] tokenclasses = copy.deepcopy(g.tokenclasses) if tok in tokenclasses: tclass = tokenclasses.get(tok) tclt = newToken(tclass) if hasattr(tclt, 'getClassInfo'): sections = tclt.getClassInfo(section, {}) if scope in sections.keys(): section = sections.get(scope) page = section.get('page') c.scope = page.get('scope') c.authUser = self.authUser html = page.get('html') res = render(os.path.sep + html) res = remove_empty_lines(res) Session.commit() return res except CompileException as exx: log.exception("[load_form] compile error while processing %r.%r:" % (tok, scope)) log.error("[load_form] %r" % exx) Session.rollback() raise Exception(exx) except Exception as exx: Session.rollback() error = ('error (%r) accessing form data for: tok:%r, scope:%r' ', section:%r' % (exx, tok, scope, section)) log.exception(error) return '<pre>%s</pre>' % error finally: Session.close() log.debug('[load_form] done')
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 = getParam(param, "pass", optional) user = getUserFromParam(param, optional) # support for ocra application challenge verification challenge = getParam(param, "challenge", optional) if challenge is not None: options = {} options['challenge'] = challenge c.audit['user'] = user.login realm = user.realm or getDefaultRealm() c.audit['realm'] = realm # AUTHORIZATION Pre Check # we need to overwrite the user.realm in case the # user does not exist in the original realm (setrealm-policy) user.realm = set_realm(user.login, realm, exception=True) check_user_authorization(user.login, user.realm, exception=True) if isSelfTest() is True: initTime = getParam(param, "init", optional) if initTime is not None: if options is None: options = {} options['initTime'] = initTime vh = ValidationHandler() (ok, opt) = vh.checkUserPass(user, passw, options=options) c.audit.update(request_context.get('audit')) c.audit['success'] = ok if ok: # AUTHORIZATION post check check_auth_tokentype(c.audit['serial'], exception=True, user=user) check_auth_serial(c.audit['serial'], exception=True, user=user) # add additional details if is_auth_return(ok, user=user): if opt is None: opt = {} if ok: opt['realm'] = c.audit.get('realm') opt['user'] = c.audit.get('user') opt['tokentype'] = c.audit.get('token_type') opt['serial'] = c.audit.get('serial') else: opt['error'] = c.audit.get('action_detail') return (ok, opt)
def 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 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')