def update(self, param, reset_failcount=True): tdesc = param.get("description") if tdesc is not None: self.token.setDescription(tdesc) # key_size as parameter overrules a prevoiusly set # value e.g. in hashlib in the upper classes key_size = param.get("keysize") if key_size is None: key_size = 20 ## # process the otpkey: # if otpkey given - take this # if not given # if genkey == 1 : create one # if required and otpkey is None: # raise param Exception, that we require an otpkey ## otpKey = param.get("otpkey") genkey = int(param.get("genkey", 0)) if genkey not in [0, 1]: raise Exception("TokenClass supports only genkey in " "range [0,1] : %r" % genkey) if genkey == 1 and otpKey is not None: raise ParameterError('[ParameterError] You may either specify' 'genkey or otpkey, but not both!', id=344) if otpKey is not None: self.setOtpKey(otpKey, reset_failcount=reset_failcount) else: if genkey == 1: otpKey = self._genOtpKey_() # otpKey still None?? - raise the exception if otpKey is None: if self.hKeyRequired is True: try: otpKey = param["otpkey"] except KeyError: raise ParameterError("Missing parameter: 'otpkey'") if otpKey is not None: self.addToInfo('otpkey', otpKey) self.setOtpKey(otpKey) pin = param.get("pin") if pin is not None: self.setPin(pin, param=param) otplen = param.get('otplen', None) if otplen: self.setOtpLen(otplen) self.resetTokenInfo() return
def update(self, param): try: self.radiusServer = param["radius.server"] except KeyError: raise ParameterError("Missing parameter: 'radius.server'") # 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 = param.get("radius.local_checkpin") if val is not None: self.radiusLocal_checkpin = val try: self.radiusUser = param["radius.user"] except KeyError: raise ParameterError("Missing parameter: 'radius.user'") try: self.radiusSecret = param["radius.secret"] except KeyError: raise ParameterError("Missing parameter: 'radius.secret'") 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 reject_transaction(self): """ rejects a transaction. needs the mandatory url query parameters: * transactionid: unique id for the transaction * signature: signature for the rejection """ try: param = self.request_params.copy() # -------------------------------------------------------------- -- # check the parameters if 'signature' not in param: raise ParameterError("Missing parameter: 'signature'!") if 'transactionid' not in param: raise ParameterError("Missing parameter: 'transactionid'!") # -------------------------------------------------------------- -- # start the processing passw = {'reject': param['signature']} transid = param['transactionid'] vh = ValidationHandler() ok, _opt = vh.check_by_transactionid(transid=transid, passw=passw, options=param) # -------------------------------------------------------------- -- # finish the result if 'serial' in _opt: g.audit['serial'] = _opt['serial'] if 'token_type' in _opt: g.audit['token_type'] = _opt['token_type'] g.audit['info'] = 'reject transaction: %r' % ok g.audit['success'] = ok db.session.commit() return sendResult(response, ok) except Exception as exx: log.exception("validate/reject_transaction failed: %r" % exx) g.audit['info'] = "%r" % exx db.session.rollback() return sendResult(response, False, 0)
def update(self, param, reset_failcount=True): ''' update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing ''' if 'otpkey' not in param: raise ParameterError("Missing parameter: 'otpkey'") # motp token specific try: otpPin = param['otppin'] except KeyError: raise ParameterError("Missing parameter: 'otppin'") self.setUserPin(otpPin) TokenClass.update(self, param, reset_failcount) return
def accept_transaction(self): """ confirms a transaction. needs the mandatory url query parameters: * transactionid: unique id for the transaction * signature: signature for the confirmation """ try: param = self.request_params.copy() # -------------------------------------------------------------- -- # check the parameters if "signature" not in param: raise ParameterError("Missing parameter: 'signature'!") if "transactionid" not in param: raise ParameterError("Missing parameter: 'transactionid'!") # -------------------------------------------------------------- -- # start the processing passw = {"accept": param["signature"]} transid = param["transactionid"] vh = ValidationHandler() ok, _opt = vh.check_by_transactionid( transid=transid, passw=passw, options=param ) # -------------------------------------------------------------- -- # finish the result if "serial" in _opt: g.audit["serial"] = _opt["serial"] if "token_type" in _opt: g.audit["token_type"] = _opt["token_type"] g.audit["info"] = "accept transaction: %r" % ok g.audit["success"] = ok db.session.commit() return sendResult(response, ok) except Exception as exx: log.error("validate/accept_transaction failed: %r", exx) g.audit["info"] = "%r" % exx db.session.rollback() return sendResult(response, False, 0)
def accept_transaction(self): """ confirms a transaction. needs the mandatory url query parameters: * transactionid: unique id for the transaction * signature: signature for the confirmation """ try: param = {} param.update(request.params) # -------------------------------------------------------------- -- # check the parameters if 'signature' not in param: raise ParameterError("Missing parameter: 'signature'!") if 'transactionid' not in param: raise ParameterError("Missing parameter: 'transactionid'!") # -------------------------------------------------------------- -- # start the processing passw = {'accept': param['signature']} transid = param['transactionid'] vh = ValidationHandler() ok, _opt = vh.check_by_transactionid(transid=transid, passw=passw, options=param) # -------------------------------------------------------------- -- # finish the result c.audit['info'] = 'accept transaction: %r' % ok c.audit['success'] = ok Session.commit() return sendResult(response, ok) except Exception as exx: log.exception("validate/accept_transaction failed: %r" % exx) c.audit['info'] = "%r" % exx Session.rollback() return sendResult(response, False, 0) finally: Session.close()
def check_status(self): """ check the status of a transaction - for polling support """ try: param = {} param.update(request.params) # # we require either state or transactionid as parameter transid = param.get('state', param.get('transactionid', None)) if not transid: raise ParameterError(_('Missing required parameter "state" or ' '"transactionid"!')) # # serial is an optional parameter serial = param.get('serial', None) # # but user is an required parameter if "user" not in param: raise ParameterError(_('Missing required parameter "serial"' ' or "user"!')) user = getUserFromParam(param) passw = param.get('pass', None) if passw is None: raise ParameterError(_('Missing required parameter "pass"!')) use_offline = param.get('use_offline', False) va = ValidationHandler() ok, opt = va.check_status(transid=transid, user=user, serial=serial, password=passw, use_offline=use_offline) c.audit['success'] = ok c.audit['info'] = unicode(opt) Session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("check_status failed: %r" % exx) c.audit['info'] = unicode(exx) Session.rollback() return sendResult(response, False, 0) finally: Session.close()
def check_status(self): """ check the status of a transaction - for polling support """ try: param = self.request_params # # we require either state or transactionid as parameter transid = param.get('state', param.get('transactionid', None)) if not transid: raise ParameterError( _('Missing required parameter "state" or ' '"transactionid"!')) # # serial is an optional parameter serial = param.get('serial', None) # user is an optional parameter: # if no 'user' in the parameters, the User object will be empty user = getUserFromParam(param) passw = param.get('pass') if passw is None: raise ParameterError(_('Missing required parameter "pass"!')) use_offline = param.get('use_offline', False) va = ValidationHandler() ok, opt = va.check_status(transid=transid, user=user, serial=serial, password=passw, use_offline=use_offline) g.audit['success'] = ok g.audit['info'] = str(opt) db.session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("check_status failed: %r" % exx) g.audit['info'] = str(exx) db.session.rollback() return sendResult(response, False, 0)
def 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 } ''' try: try: passw = self.request_params['pass'] except KeyError: raise ParameterError("Missing parameter: 'pass'") ok = False try: vh = ValidationHandler() ok, opt = vh.checkYubikeyPass(passw) g.audit['success'] = ok except AuthorizeException as exx: log.warning( "[check_yubikey] authorization failed for validate/check_yubikey: %r" % exx) g.audit['success'] = False g.audit['info'] = str(exx) ok = False db.session.commit() return sendResult(response, ok, 0, opt=opt) except Exception as exx: log.exception("[check_yubikey] validate/check_yubikey failed: %r" % exx) g.audit['info'] = str(exx) db.session.rollback() return sendResult(response, False, 0)
def tokeninfo(self): ''' this returns the contents of /admin/show?serial=xyz in an html format ''' param = self.request_params try: try: serial = param['serial'] except KeyError: raise ParameterError("Missing parameter: 'serial'") 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').decode('utf-8') except PolicyException as pe: log.exception("[tokeninfo] Error during checking policies: %r" % pe) db.session.rollback() return sendError(response, str(pe), 1) except Exception as e: log.exception("[tokeninfo] failed! %r" % e) db.session.rollback() return sendError(response, e)
def autosms(self): ''' This function is used to test the autosms policy method: testing/autosms arguments: user - username / loginname realm - additional realm to match the user to a useridresolver returns: JSON response ''' try: if "user" not in self.request_params: raise ParameterError("Missing parameter: 'user'") ok = get_auth_AutoSMSPolicy() Session.commit() return sendResult(response, ok, 0) except Exception as exx: log.exception("[autosms] validate/check failed: %r", exx) Session.rollback() return sendError(response, ("validate/check failed: %r", exx), 0) finally: Session.close()
def getParam(param, which, optional): if param.has_key(which): return param[which] else: if (optional is False): raise ParameterError("Missing parameter: %r" % which, id=905) return
def update(self, param, reset_fail_count=True): """ token initialization with user parameters :param param: dict of initialization parameters :param reset_fail_count : boolean if the fail count should be reset :return: nothing """ # ------------------------------------------------------------------ -- # set the required phone / mobile number if 'phone' not in param: raise ParameterError("Missing parameter: 'phone'") self.set_phone(param['phone']) # ------------------------------------------------------------------ -- # lower layer should generate the token seed and # use the sha256 for the hmac operations param['genkey'] = 1 param['hashlib'] = 'sha256' # ------------------------------------------------------------------ -- # call update method of parent class HmacTokenClass.update(self, param, reset_fail_count)
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 = '' tok = None section = None scope = None try: try: act = self.request_params["type"] except KeyError: raise ParameterError("Missing parameter: 'type'", id=905) try: (tok, section, scope) = act.split('.') except Exception: return res if section != 'selfservice': return res if tok in tokenclass_registry: tclt = tokenclass_registry.get(tok) if hasattr(tclt, 'getClassInfo'): sections = tclt.getClassInfo(section, {}) if scope in list(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).decode() res = remove_empty_lines(res) db.session.commit() return res except CompileException as exx: log.exception("[load_form] compile error while processing %r.%r:" "Exeption was %r" % (tok, scope, exx)) db.session.rollback() raise exx except Exception as exx: db.session.rollback() error = ('error (%r) accessing form data for: tok:%r, scope:%r' ', section:%r' % (exx, tok, scope, section)) log.exception(error) return "<h1>{}</h1><pre>{} {}</pre>".format( _("Failed to load form"), _("Error"), exx)
def checkid_submit(self): ''' This is called when the user accepts - hit the submit button - that he will login to the consumer ''' log.debug("[checkid_submit] params: %s" % self.request_params) try: redirect_token = self.request_params["redirect_token"] except KeyError: raise ParameterError("Missing parameter: 'redirect_token'", id=905) verify_always = self.request_params.get("verify_always") 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 check_t(self): param = {} value = {} ok = False opt = {} try: param.update(request.params) if 'pass' not in param: raise ParameterError("Missing parameter: 'pass'") passw = param['pass'] 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()
def update(self, param): # check for the required parameters if (self.hKeyRequired is True): if "otpkey" not in param: raise ParameterError("Missing parameter: 'otpkey'", id=905) TokenClass.update(self, param)
def check_t(self): param = self.request_params.copy() value = {} ok = False opt = {} try: if "pass" not in param: raise ParameterError("Missing parameter: 'pass'") passw = param["pass"] 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)) g.audit["success"] = ok db.session.commit() qr = param.get("qr", None) if qr and opt and "message" in opt: try: dataobj = opt.get("message") param["alt"] = "%s" % opt if "transactionid" in opt: param["transactionid"] = opt["transactionid"] return sendQRImageResult(response, dataobj, param) except Exception as exc: log.warning("failed to send QRImage: %r ", exc) return sendQRImageResult(response, opt, param) else: return sendResult(response, value, 1, opt=opt) except Exception as exx: log.error("[check_t] validate/check_t failed: %r", exx) g.audit["info"] = str(exx) db.session.rollback() return sendResult(response, False, 0)
def update(self, param, reset_failcount=True): # check for the required parameters if self.hKeyRequired is True: if "otpkey" not in param: raise ParameterError("Missing parameter: 'otpkey'") TokenClass.update(self, param, reset_failcount=False) for key in ["vasco_appl", "vasco_type", "vasco_auth"]: val = param.get(key) if val is not None: self.addToTokenInfo(key, val)
def checkSerialPass(self, serial, passw, options=None, user=None): """ This function checks the otp for a given serial :attention: the parameter user must be set, as the pin policy==1 will verify the user pin """ token_type = options.get("token_type", None) tokenList = getTokens4UserOrSerial(None, serial, token_type=token_type, read_for_update=True) if passw is None: # other than zero or one token should not happen, as serial is # unique if len(tokenList) == 1: theToken = tokenList[0] tok = theToken.token realms = tok.getRealmNames() if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo( tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass, ) user = User(login=userInfo.get("username"), realm=realm) user.info = userInfo if theToken.is_challenge_request(passw, user, options=options): (res, opt) = Challenges.create_challenge(theToken, options) res = False else: raise ParameterError("Missing parameter: pass", id=905) else: raise Exception("No token found: " "unable to create challenge for %s" % serial) else: (res, opt) = self.checkTokenList(tokenList, passw, user=user, options=options) return (res, opt)
def checkSerialPass(self, serial, passw, options=None, user=None): """ This function checks the otp for a given serial :attention: the parameter user must be set, as the pin policy==1 will verify the user pin """ log.debug('checking for serial %r' % serial) tokenList = linotp.lib.token.getTokens4UserOrSerial(None, serial) if passw is None: # other than zero or one token should not happen, as serial is # unique if len(tokenList) == 1: theToken = tokenList[0] tok = theToken.token realms = tok.getRealmNames() if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo(tok.LinOtpUserid, tok.LinOtpIdResolver, tok.LinOtpIdResClass) user = User(login=userInfo.get('username'), realm=realm) user.info = userInfo if theToken.is_challenge_request(passw, user, options=options): (res, opt) = Challenges.create_challenge(theToken, options) res = False else: raise ParameterError('Missing parameter: pass', id=905) else: raise Exception('No token found: ' 'unable to create challenge for %s' % serial) else: log.debug('checking len(pass)=%r for serial %r' % (len(passw), serial)) (res, opt) = self.checkTokenList(tokenList, passw, user=user, options=options) return (res, opt)
def update(self, param): """ second phase of the init process - updates parameters :param param: the request parameters :return: - nothing - """ try: self.remoteServer = param["remote.server"] except KeyError: raise ParameterError("Missing parameter: 'remote.server'") # 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 = param.get("remote.local_checkpin", optional) if val is not None: self.remoteLocalCheckpin = val val = param.get("remote.serial") if val is not None: self.remoteSerial = val val = param.get("remote.user") if val is not None: self.remoteUser = val val = param.get("remote.realm") if val is not None: self.remoteRealm = val val = param.get("remote.resConf") 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 update(self, param): """ update - the api, which is called during the token enrollment we have to make sure that the otpkey, which carries our password is encoded as utf-8 to not break the storing :raises: otpkey contains the password and is required therefore otherewise raises ParameterError """ if "otpkey" not in param: raise ParameterError("Missing Parameter 'otpkey'!") TokenClass.update(self, param) TokenClass.setOtpLen(self, len(param["otpkey"]))
def autosms(self): ''' This function is used to test the autosms policy method: testing/autosms arguments: user - username / loginname realm - additional realm to match the user to a useridresolver returns: JSON response ''' param = request.params try: if isSelfTest() is False: Session.rollback() return sendError( response, "The testing controller can only be used in SelfTest mode!", 0) if "user" not in param: raise ParameterError("Missing parameter: 'user'") ok = get_auth_AutoSMSPolicy() Session.commit() return sendResult(response, ok, 0) except Exception as e: log.exception("[autosms] validate/check failed: %r", e) Session.rollback() return sendError(response, "validate/check failed:" + unicode(e), 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 ''' _ = context['translate'] # specific - phone try: phone = param['phone'] except KeyError: raise ParameterError("Missing parameter: 'phone'") # 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) return
def update(self, param, reset_failcount=True): """ update - process initialization parameters :param param: dict of initialization parameters :type param: dict :return: nothing """ # specific - phone try: phone = param["phone"] except KeyError: raise ParameterError("Missing parameter: 'phone'") # 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) return
def update(self, param): try: tokenid = param['yubico.tokenid'] except KeyError: raise ParameterError("Missing parameter: 'yubico.tokenid'") if len(tokenid) < 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 getParam(param, which, optional=True): """ getParam() input: - param (hash set): the set, which contains all parameters - which (lteral): the entry lookup - optional (boolean): defines if this parameter is optional or not - an exception is thrown if the parameter is required - otherwise: nothing done! return: - the value (literal) of the parameter if exists or nothing in case the parameter is optional, otherwise throw an exception """ ret = None if param.has_key(which): ret = param[which] else: if (optional == False): raise ParameterError("Missing parameter: %r" % which, id=905) return ret
def update(self, param, reset_failcount=True): # key_size as parameter overrules a prevoiusly set # value e.g. in hashlib in the upper classes key_size = param.get("keysize") if key_size is None: key_size = 20 ## # process the otpkey (aka seed): # if otpkey given - take this # if not given # if genkey == 1 : create one # if required and otpkey is None: # raise param Exception, that we require an otpkey ## otpKey = param.get("otpkey") genkey = int(param.get("genkey", 0)) if genkey not in [0, 1]: raise Exception("TokenClass supports only genkey in " "range [0,1] : %r" % genkey) if genkey == 1 and otpKey is not None: raise ParameterError( "[ParameterError] You may either specify" "genkey or otpkey, but not both!", id=344, ) if otpKey is None and genkey == 1: otpKey = self._genOtpKey_() # otpKey still None?? - raise the exception if otpKey is None and self.hKeyRequired is True: try: otpKey = param["otpkey"] except KeyError: raise ParameterError("Missing parameter: 'otpkey'") if otpKey is not None: self.validate_seed(otpKey) self.addToInfo("otpkey", otpKey) self.setOtpKey(otpKey, reset_failcount=reset_failcount) pin = param.get("pin") if pin is not None: self.setPin(pin, param=param) otplen = param.get("otplen", None) if otplen: self.setOtpLen(otplen) # ----------------------------------------------------------------- -- # handle definition of usage scope scope = None if "scope" in param: scope = json.loads(param.get("scope", {})) elif "rollout" in param: scope = {"path": ["userservice"]} if scope: self.addToTokenInfo("scope", scope) if not param.get("description"): path = scope.get("path", []) if set(path) & set(["userservice", "validate"]): param["description"] = "rollout token" if param.get("description"): self.token.setDescription(param.get("description")) # ----------------------------------------------------------------- -- self.resetTokenInfo() return
def checkUserPass(self, user, passw, options=None): """ :param user: the to be identified user :param passw: the identification pass :param options: optional parameters, which are provided to the token checkOTP / checkPass :return: tuple of True/False and optional information """ # the upper layer will catch / at least should ;-) opt = None serial = None resolverClass = None uid = None user_exists = False if user is not None and not user.is_empty: # the upper layer will catch / at least should try: (uid, _resolver, resolverClass) = getUserId( user, check_existance=True) user_exists = True except Exception as _exx: pass_on = context.get('Config').get( 'linotp.PassOnUserNotFound', False) if pass_on and 'true' == pass_on.lower(): g.audit['action_detail'] = ( 'authenticated by PassOnUserNotFound') return (True, opt) else: g.audit['action_detail'] = 'User not found' return (False, opt) # if we have an user, check if we forward the request to another server if user_exists and get_auth_forward_on_no_token(user) is False: servers = get_auth_forward(user) if servers: res, opt = ForwardServerPolicy.do_request(servers, env, user, passw, options) return res, opt # ------------------------------------------------------------------ -- th = TokenHandler() # ------------------------------------------------------------------ -- # auto asignement with otp only if user has no active token auto_assign_otp_return = th.auto_assign_otp_only( otp=passw, user=user, options=options) if auto_assign_otp_return is True: return (True, None) # ------------------------------------------------------------------ -- token_type = None if options: token_type = options.get('token_type', None) # ------------------------------------------------------------------ -- # if there is a serial provided in the parameters, it overwrites the # token selection by user query_user = user if options and 'serial' in options and options['serial']: serial = options['serial'] query_user = None # ------------------------------------------------------------------ -- tokenList = getTokens4UserOrSerial( query_user, serial, token_type=token_type, read_for_update=True ) if len(tokenList) == 0: g.audit['action_detail'] = 'User has no tokens assigned' # here we check if we should to autoassign and try to do it auto_assign_return = th.auto_assignToken(passw, user) if auto_assign_return is True: # We can not check the token, as the OTP value is already used! # but we will auth the user.... return (True, opt) auto_enroll_return, opt = th.auto_enrollToken(passw, user, options=options) if auto_enroll_return is True: # we always have to return a false, as # we have a challenge tiggered return (False, opt) pass_on = context.get('Config').get('linotp.PassOnUserNoToken', False) if pass_on and 'true' == pass_on.lower(): g.audit['action_detail'] = 'authenticated by PassOnUserNoToken' return (True, opt) # Check if there is an authentication policy passthru if get_auth_passthru(user): log.debug('user %r has no token. Checking for ' 'passthru in realm %r' % (user.login, user.realm)) y = getResolverObject(resolverClass) g.audit['action_detail'] = 'Authenticated against Resolver' if y.checkPass(uid, passw): return (True, opt) # Check alternatively if there is an authentication # policy passOnNoToken elif get_auth_passOnNoToken(user): log.info('user %r has not token. PassOnNoToken' ' set - authenticated!') g.audit['action_detail'] = ( 'Authenticated by passOnNoToken policy') return (True, opt) # if we have an user, check if we forward the request to another server elif get_auth_forward_on_no_token(user) is True: servers = get_auth_forward(user) if servers: res, opt = ForwardServerPolicy.do_request( servers, env, user, passw, options) return res, opt return False, opt if passw is None: raise ParameterError("Missing parameter:pass", id=905) (res, opt) = self.checkTokenList( tokenList, passw, user, options=options) return (res, opt)