class MachineController(BaseController): @log_with(log) def __before__(self, action, **params): ''' ''' try: c.audit['success'] = False c.audit['client'] = get_client() self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), tokenrealms=request.params.get('serial'), token_type_list=get_token_type_list()) self.set_language() self.before_identity_check(action) Session.commit() return request except webob.exc.HTTPUnauthorized as acc: # the exception, when an abort() is called if forwarded log.info("%r: webob.exception %r" % (action, acc)) log.info(traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: log.error("exception %r" % (action, exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: pass @log_with(log) def __after__(self, action, **params): ''' ''' params = {} try: params.update(request.params) c.audit['administrator'] = getUserFromRequest(request).get("login") if 'serial' in params: c.audit['serial'] = request.params['serial'] c.audit['token_type'] = getTokenType(params.get('serial')) self.audit.log(c.audit) Session.commit() return request except Exception as e: log.error("unable to create a session cookie: %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendError(response, e, context='after') finally: Session.close() @log_with(log) def create(self, action, **params): ''' Create a new client machine entry :param name: the unique name of the machine (required). Can be the FQDN. :param desc: description of the machine :param ip: The IP address of the machine :param decommission: A date when the machine will not be valid anymore :return: True or False if the creation was successful. ''' try: res = False param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'create') param.update(request.params) machine_name = getParam(param, "name", required) ip = getParam(param, "ip", optional) desc = getParam(param, "desc", optional) decommission = getParam(param, "decommission", optional) machine = create_machine(machine_name, ip=ip, desc=desc, decommission=decommission) if machine: res = True Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def delete(self, action, **params): ''' Delete an existing client machine entry :param name: the unique name of the machine :return: value is either true (success) or false (fail) ''' try: res = {} param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'delete') param.update(request.params) machine_name = getParam(param, "name", required) res = delete_machine(machine_name) Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def show(self, action, **params): ''' Returns a list of the client machines. :param name: Optional parameter to only show this single machine :return: JSON details ''' try: res = {} param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'show') param.update(request.params) machine_name = getParam(param, "name", optional) res = show_machine(machine_name) Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def addtoken(self, action, **params): ''' Add a token and a application to a machine :param name: Name of the machine :param serial: serial number of the token :param application: name of the application ''' try: res = False param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'addtoken') param.update(request.params) machine_name = getParam(param, "name", required) serial = getParam(param, "serial", required) application = getParam(param, "application", required) if application.lower() not in config.get("applications").keys(): log.error("Unknown application %r. Available applications: " "%r" % (application, config.get("applications").keys())) raise Exception("Unkown application!") mt = addtoken(machine_name, serial, application) if mt: res = True Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def deltoken(self, action, **params): ''' delete a token and a application from a machine :param name: Name of the machine :param serial: serial number of the token :param application: name of the application ''' try: res = False param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'deltoken') param.update(request.params) machine_name = getParam(param, "name", required) serial = getParam(param, "serial", required) application = getParam(param, "application", required) res = deltoken(machine_name, serial, application) Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) @log_with(log) def showtoken(self, action, **params): ''' show a token and a application from a machine :param name: Name of the machine :param serial: serial number of the token :param application: name of the application :param flexi: if set to 1, we do return flexigrid input ''' try: res = False param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'showtoken') param.update(request.params) machine_name = getParam(param, "name", optional) serial = getParam(param, "serial", optional) application = getParam(param, "application", optional) # if set, this should be returned for flexigrid flexi = getParam(param, "flexi", optional) res = showtoken(machine_name, serial, application, flexi=flexi, params=param) Session.commit() c.audit["success"] = True if flexi: response.content_type = 'application/json' return json.dumps(res, indent=3) else: return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def gettokenapps(self, action, **params): ''' returns the apps and the authentication information for the given machine. If an application is given only the authentication item for this application is returned. otherwise the application items for all applications are returned. TODO: Authenticate the client machine :param name: the machine name - otherwise the machine is identified by the IP :type name: string, optional :param application: the name of the application :type application: sting, optional :param serial: THe serial number of the token ''' try: res = False param = {} self.Policy.checkPolicyPre('machine', 'gettokenapps') param.update(request.params) machine_name = getParam(param, "name", optional) application = getParam(param, "application", optional) serial = getParam(param, "serial", optional) challenge = None if isSelfTest(): challenge = getParam(param, "challenge", optional) client_ip = get_client() if application: if application not in config.get("applications").keys(): log.error("Unknown application %r. Available applications: " "%r" % (application, config.get("applications").keys())) application_module = config.get("applications").get(application) res = get_token_apps(machine=machine_name, application=application, application_module=application_module, serial=serial, client_ip=client_ip, challenge=challenge) Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def getapplications(self, action, **params): ''' Returns a list of available applications ''' try: return sendResult(response, config.get("applications").keys()) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close()
def search(self, action, **params): ''' This functions searches within the audit trail It returns the audit information for the given search pattern method: audit/search arguments: key, value pairs as search patterns. * outform - optional: if set to "csv", than the token list will be given in CSV or: Usually the key=values will be locally AND concatenated. it a parameter or=true is passed, the filters will be OR concatenated. The Flexigrid provides us the following parameters: ('page', u'1'), ('rp', u'100'), ('sortname', u'number'), ('sortorder', u'asc'), ('query', u''), ('qtype', u'serial')] returns: JSON response or csv format ''' param = {} try: param.update(request.params) output_format = getParam(param, "outform", optional) Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), token_type_list=get_token_type_list()) Policy.checkPolicyPre('audit', 'view', {}) # remove the param outform (and other parameters that should not # be used for search! search_params = {} for p in param: if p not in ["outform"]: search_params[p] = param[p] log.debug("search params %r" % search_params) audit_iter = None if output_format == "csv": filename = "privacyidea-audit.csv" response.content_type = "application/force-download" response.headers['Content-' 'disposition'] = ('attachment; filename=%s' % filename) audit_iter = CSVAuditIterator(search_params) else: response.content_type = 'application/json' audit_iter = JSONAuditIterator(search_params) c.audit['success'] = True Session.commit() return audit_iter except PolicyException as pe: log.error("gettoken/getotp policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("audit/search failed: %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendError(response, "audit/search failed: %s" % unicode(e), 0) finally: Session.close()
class SystemController(BaseController): ''' The privacyidea.controllers are the implementation of the web-API to talk to the privacyIDEA server. The SystemController is used to configure the privacyIDEA server. The functions of the SystemController are invoked like this https://server/system/<functionname> The functions are described below in more detail. ''' @log_with(log) def __before__(self, action, **params): ''' __before__ is called before every action so we can check the authorization (fixed?) :param action: name of the to be called action :param params: the list of http parameters :return: return response :rtype: pylon response ''' try: c.audit['success'] = False c.audit['client'] = get_client() self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), token_type_list = get_token_type_list()) self.before_identity_check(action) # check authorization if action not in ["_add_dynamic_tokens", 'setupSecurityModule',]: self.Policy.checkPolicyPre('system', action) ## default return for the __before__ and __after__ return response except PolicyException as pex: log.error("%r: policy exception %r" % (action, pex)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, pex, context='before') except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.error("%r: webob.exception %r" % (action, acc)) log.error(traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: log.error("%r: exception %r" % (action, exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: pass @log_with(log) def __after__(self, action, **params): ''' __after is called after every action :return: return the response :rtype: pylons response ''' try: c.audit['administrator'] = getUserFromRequest(request).get("login") self.audit.log(c.audit) ## default return for the __before__ and __after__ return response except Exception as exx: log.error("exception %r" % (exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='after') finally: pass ######################################################## def setDefault(self): """ method: system/set description: define default settings for tokens. These default settings are used when new tokens are generated. The default settings will not affect already enrolled tokens. arguments: DefaultMaxFailCount - Default value for the maximum allowed authentication failures DefaultSyncWindow - Default value for the synchronization window DefaultCountWindow - Default value for the coutner window DefaultOtpLen - Default value for the OTP value length -- usuall 6 or 8 DefaultResetFailCount - Default value, if the FailCounter should be reset on successful authentication [True|False] returns: a json result with a boolean "result": true exception: if an error occurs an exception is serialized and returned """ res = {} count = 0 description = "setDefault: parameters are\ DefaultMaxFailCount\ DefaultSyncWindow\ DefaultCountWindow\ DefaultOtpLen\ DefaultResetFailCount\ " keys = [ "DefaultMaxFailCount", "DefaultSyncWindow", "DefaultCountWindow", "DefaultOtpLen", "DefaultResetFailCount"] ### config settings from here try: param = getLowerParams(request.params) for k in keys: if param.has_key(k.lower()): value = getParam(param, k.lower(), required) ret = storeConfig(k, value) des = "set " + k res[des] = ret count = count + 1 c.audit['success'] = count c.audit['info'] += "%s=%s, " % (k, value) if count == 0 : log.warning("Failed saving config. Could not find any known parameter. %s" % description) raise ParameterError("Usage: %s" % description, id=77) Session.commit() return sendResult(response, res) except Exception as exx: log.error('commit failed: %r' % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## def setConfig(self): """ set a configuration key or a set of configuration entries parameter could either be in the form key=..&value=.. or as a set of generic keyname=value pairs. *remark: In case of key-value pairs the type information could be provided by an additional parameter with same keyname with the postfix ".type". Value could then be 'password' to trigger the storing of the value in an encrypted form :param key: configuration entry name :param value: configuration value :param type: type of the value: int or string/text or password password will trigger to store the encrypted value :param description: additional information for this config entry * or :param key-value pairs: pair of &keyname=value pairs :return: a json result with a boolean "result": true """ res = {} param = {} try: param.update(request.params) if "key" in param: key = param.get("key") val = param.get("value", None) typ = param.get("type", None) des = param.get("description", None) if val is None: raise ParameterError("Required parameters: value") ret = storeConfig(key, val, typ, des) string = "setConfig %s" % key res[string] = ret c.audit['success'] = True c.audit['info'] = "%s=%s" % (key, val) else: ## we gather all key value pairs in the conf dict conf = {} for key in remove_session_from_param(param): val = param.get(key, '') or '' Key = key if not key.startswith('privacyidea'): Key = 'privacyidea.' + key conf[Key] = val string = "setConfig " + key + ":" + val res[string] = True c.audit['success'] = True c.audit['info'] += "%s=%s, " % (key, val) updateConfig(conf) Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error saving config: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def delConfig(self, action, **params): """ delete a configuration key * if an error occurs an exception is serializedsetConfig and returned :param key: configuration key name :returns: a json result with the deleted value """ res = {} try: param = getLowerParams(request.params) key = getParam(param, "key", required) ret = removeFromConfig(key) string = "delConfig " + key res[string] = ret c.audit['success'] = ret c.audit['info'] = key Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error deleting config: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## ######################################################## @log_with(log) def getConfig(self, action, **params): """ retrieve value of a defined configuration key, or if no key is given, the complete configuration is returned if an error occurs an exception is serialized and returned * remark: the assumption is, that the access to system/getConfig is only allowed to privileged users :param key: generic configuration entry name (optional) :return: a json result with key value or all key + value pairs """ res = {} param = {} try: param.update(remove_session_from_param(request.params)) ## if there is no parameter, we return them all if len(param) == 0: conf = get_privacyIDEA_config() keys = conf.keys() keys.sort() for key in keys: if key.startswith("encprivacyidea."): continue if key.startswith("privacyidea."): Key = key[len("privacyidea."):] typ = type(conf.get(key)).__name__ if typ == 'datetime': res[Key] = unicode(conf.get(key)) else: res[Key] = conf.get(key) ## as we return the decrypted values, we could do this in place ## and display the value under the original key for key in keys: if key.startswith("encprivacyidea."): Key = key[len("encprivacyidea."):] res[Key] = conf.get(key) c.audit['success'] = True c.audit['info'] = "complete config" else: key = getParam(param, "key", required) ret = getFromConfig(key) string = "getConfig " + key res[string] = ret c.audit['success'] = ret c.audit['info'] = "config key %s" % key Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error getting config: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def getRealms(self, action, **params): ''' method: system/getRealms description: returns all realm definitinos as a json result. arguments: returns: a json result with a list of Realms exception: if an error occurs an exception is serialized and returned Either the admin has the policy scope=system, action=read or he is rights in scope=admin for some realms. If he does not have the system-read-right, then he will only see the realms, he is admin of. ''' ### config settings from here try: param = getLowerParams(request.params) res = getRealms() c.audit['success'] = True # If the admin is not allowed to see all realms, (policy scope=system, action=read) # the realms, where he has no administrative rights need, to be stripped. polPost = self.Policy.checkPolicyPost('system', 'getRealms', { 'realms' : res }) res = polPost['realms'] Session.commit() return sendResult(response, res, 1) except PolicyException as pex: log.error("policy exception: %r" % pex) log.error(traceback.format_exc()) Session.rollback() return sendError(response, pex) except Exception as exx: log.error("error getting realms: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def setResolver(self, action, **params): """ method: system/setResolver description: creates or updates a useridresolver arguments: name - the name of the resolver type - the type of the resolver [ldapsersolver, sqlresolver] LDAP: LDAPURI LDAPBASE BINDDN BINDPW TIMEOUT SIZELIMIT LOGINNAMEATTRIBUTE LDAPSEARCHFILTER LDAPFILTER USERINFO NOREFERRALS - True|False SQL: Database Driver Server Port User Password Table Map returns: a json result with the found value exception: if an error occurs an exception is serialized and returned """ res = {} param = {} try: param.update(request.params) res = defineResolver(param) Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error saving config: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def getResolvers(self, action, **params): """ method: system/getResolvers descriptions: returns a json list of all useridresolvers arguments: returns: a json result with a list of all available resolvers exception: if an error occurs an exception is serialized and returned """ res = {} try: res = getResolverList() c.audit['success'] = True Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error getting resolvers: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def delResolver(self, action, **params): """ method: system/delResolver description: this function deletes an existing resolver All config keys of this resolver get deleted arguments: resolver - the name of the resolver to delete. returns: success state exception: if an error occurs an exception is serialized and returned """ res = {} try: param = getLowerParams(request.params) resolver = getParam(param, "resolver", required) ### only delete a resolver, if it is not used by any realm found = False fRealms = [] realms = getRealms() for realm in realms: info = realms.get(realm) reso = info.get('useridresolver') for idRes in reso: if resolver == get_resolver_name(idRes): fRealms.append(realm) found = True if found == True: c.audit['failed'] = res err = 'Resolver %r still in use by the realms: %r' % \ (resolver, fRealms) c.audit['info'] = err raise Exception('%r !' % err) res = deleteResolver(resolver) c.audit['success'] = res c.audit['info'] = resolver Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error deleting resolver: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def getResolver(self, action, **params): """ method: system/getResolver description: this function retrieves the definition of the resolver arguments: resolver - the name of the resolver returns: a json result with the configuration of a specified resolver exception: if an error occurs an exception is serialized and returned """ res = {} try: param = getLowerParams(request.params) resolver = getParam(param, "resolver", required) if (len(resolver) == 0): raise Exception ("[getResolver] missing resolver name") res = getResolverInfo(resolver) c.audit['success'] = True c.audit['info'] = resolver Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error getting resolver: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() @log_with(log) def get_resolver_list(self, action, **params): res = {} try: from privacyidea.config.environment import get_resolver_list as getlist list = getlist() res['resolverlist'] = [l for l in list] res['resolvertypes'] = [l.split(".")[-1] for l in list] return sendResult(response, res, 1) except Exception as exx: Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def setDefaultRealm(self, action, **params): """ method: system/setDefaultRealm description: this function sets the given realm to the default realm arguments: realm - the name of the realm, that should be the default realm returns: a json result with a list of Realms exception: if an error occurs an exception is serialized and returned """ res = False try: param = getLowerParams(request.params) defRealm = getParam(param, "realm", optional) if defRealm is None: defRealm = "" defRealm = defRealm.lower().strip() res = setDefaultRealm(defRealm) if res == False and defRealm != "" : c.audit['info'] = "The realm %s does not exist" % defRealm c.audit['success'] = True c.audit['info'] = defRealm Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("setting default realm failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def getDefaultRealm(self, action, **params): """ method: system/getDefaultRealm description: this function returns the default realm arguments: ./. returns: a json description of the default realm exception: if an error occurs an exception is serialized and returned """ res = False try: defRealm = getDefaultRealm() res = getRealms(defRealm) c.audit['success'] = True c.audit['info'] = defRealm Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("return default realm failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def setRealm(self, action, **params): """ method: system/setRealm description: this function is used to define a realm with the given useridresolvers arguments: realm - name of the realm resolvers - comma seperated list of resolvers, that should be in this realm returns: a json result with a list of Realms exception: if an error occurs an exception is serialized and returned """ res = False err = "" realm = "" param = {} try: param.update(request.params) realm = getParam(param, "realm", required) resolvers = getParam(param, "resolvers", required) realm_resolvers = [] for resolver in resolvers.split(','): # check resolver returns the correct resolver description (res, realm_resolver) = checkResolverType(resolver) if res is False: raise Exception("Error in resolver %r please check the" " logfile!" % resolver) realm_resolvers.append(realm_resolver) resolvers = ",".join(realm_resolvers) res = setRealm(realm, resolvers) c.audit['success'] = res c.audit['info'] = "realm: %r, resolvers: %r" % (realm, resolvers) Session.commit() return sendResult(response, res, 1) except Exception as exx: err = ("Failed to set realm with %r " % param) log.error("%r %r" % (err, exx)) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def delRealm(self, action, **params): """ method: system/delRealm description: this function deletes the given realm arguments: realm - the name of the realm to be deleted returns: a json result if deleting the realm was successful exception: if an error occurs an exception is serialized and returned """ res = {} try: param = request.params realm = getParam(param, "realm", required) ## we test if before delete there has been a default ## if yes - check after delete, if still one there ## and set the last available to default defRealm = getDefaultRealm() hadDefRealmBefore = False if defRealm != "": hadDefRealmBefore = True ## now test if realm is defined if isRealmDefined(realm) == True: if realm.lower() == defRealm.lower(): setDefaultRealm("") # this is a remnant of linotp 2.0 if realm == "_default_": # pragma: no cover realmConfig = "useridresolver" else: realmConfig = "useridresolver.group." + realm res["delRealm"] = {"result":removeFromConfig(realmConfig, iCase=True)} ret = deleteRealm(realm) if hadDefRealmBefore == True: defRealm = getDefaultRealm() if defRealm == "": realms = getRealms() if len(realms) == 1: for k in realms: setDefaultRealm(k) c.audit['success'] = ret c.audit['info'] = realm Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error deleting realm: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def setPolicy(self, action, **params): """ method: system/setPolicy description: Stores a policy that define ACL or behaviour of several different actions in privacyIDEA. The policy is stored as configuration values like this: Policy.<NAME>.action Policy.<NAME>.scope Policy.<NAME>.realm arguments: name: name of the policy action: which action may be executed scope: selfservice realm: This polcy holds for this realm user: (optional) This polcy binds to this user time: (optional) on which time does this policy hold client: (optional) for which requesting client this should be returns: a json result with success or error exception: if an error occurs an exception is serialized and returned """ res = {} param = {} try: param.update(remove_session_from_param(request.params)) name = getParam(param, "name", required) # check that the name does not contain a . if not re.match('^[a-zA-Z0-9_]*$', name): raise Exception (_("The name of the policy may only contain the characters a-zA-Z0-9_")) if not name: raise Exception (_("The name of the policy must not be empty")) action = getParam(param, "action", required) scope = getParam(param, "scope", required) realm = getParam(param, "realm", required) user = getParam(param, "user", optional) time = getParam(param, "time", optional) client = getParam(param, "client", optional) active = getParam(param, "active", optional) p_param = { 'name': name, 'action' : action, 'scope' : scope, 'realm' : realm, 'user' : user, 'time' : time, 'client': client, 'active' : active} c.audit['action_detail'] = unicode(param) if len(name) > 0 and len(action) > 0: log.debug("saving policy %r" % p_param) ret = setPolicy(p_param) log.debug("policy %s successfully saved." % name) string = "setPolicy " + name res[string] = ret c.audit['success'] = True Session.commit() else: log.error("failed: policy with empty name or action %r" % p_param) string = "setPolicy <%r>" % name res[string] = False c.audit['success'] = False raise Exception('setPolicy failed: name and action required!') return sendResult(response, res, 1) except Exception as exx: log.error("error saving policy: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def policies_flexi(self, action, **params): ''' This function is used to fill the policies tab Unlike the complex /system/getPolcies function, it only returns a simple array of the tokens. ''' pol = {} try: param = getLowerParams(request.params) name = getParam(param, "name", optional) realm = getParam(param, "realm", optional) scope = getParam(param, "scope", optional) sortname = getParam(param, "sortname", optional) sortorder = getParam(param, "sortorder", optional) log.debug("retrieving policy name: %s, realm: %s, scope: %s, sort:%s by %s" % (name, realm, scope, sortorder, sortname)) pols = self.Policy.getPolicy({'name':name, 'realm':realm, 'scope': scope}, display_inactive=True) lines = [] for pol in pols: lines.append( { 'id' : pol, 'cell': [ 1 if pols[pol].get('active', "True") == "True" else 0, pol, pols[pol].get('user', ""), pols[pol].get('scope', ""), escape(pols[pol].get('action', "") or ""), pols[pol].get('realm', ""), pols[pol].get('client', ""), pols[pol].get('time', "") ] } ) # sorting reverse = False sortnames = { 'active': 0, 'name' : 1, 'user' : 2, 'scope' : 3, 'action' : 4, 'realm' : 5, 'client':6, 'time' : 7 } if sortorder == "desc": reverse = True lines = sorted(lines, key=lambda policy: policy['cell'][sortnames[sortname]] , reverse=reverse) # end: sorting # We need to return 'page', 'total', 'rows' res = { "page": 1, "total": len(lines), "rows": lines } c.audit['success'] = True c.audit['info'] = "name = %s, realm = %s, scope = %s" % (name, realm, scope) Session.commit() response.content_type = 'application/json' return json.dumps(res, indent=3) except Exception as exx: log.error("error in policy flexi: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def getPolicyDef(self, action, **params): ''' method: system/getPolicyDef description: This is a helper function that returns the POSSIBLE policy definitions, that can be used to define your policies. arguments: scope - optional - if given, the function will only return policy definitions for the given scope. returns: the policy definitions of - allowed scopes - allowed actions in scopes - type of actions exception: if an error occurs an exception is serialized and returned ''' pol = {} try: param = getLowerParams(request.params) log.debug("getting policy definitions: %r" % param) scope = getParam(param, "scope", optional) pol = get_policy_definitions(scope) dynpol = self._add_dynamic_tokens(scope) pol.update(dynpol) c.audit['success'] = True c.audit['info'] = scope Session.commit() return sendResult(response, pol, 1) except Exception as exx: log.error("error getting policy definitions: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################### @log_with(log) def _add_dynamic_tokens(self, scope): ''' add the policy description of the dynamic token :param scope: scope of the policy definition :type scope: string :return: policy dict :rtype: dict ''' pol = {} glo = config['pylons.app_globals'] tokenclasses = glo.tokenclasses for tok in tokenclasses.keys(): tclass = tokenclasses.get(tok) tclass_object = newToken(tclass) if hasattr(tclass_object, 'getClassInfo'): ## check if we have a policy in the definition try: policy = tclass_object.getClassInfo('policy', ret=None) if policy is not None and policy.has_key(scope): scope_policy = policy.get(scope) pol.update(scope_policy) except Exception as exx: log.info('no policy for tokentype %r found (%r)' % (tok, exx)) return pol ######################################################### @log_with(log) def importPolicy(self, action, **params): ''' method: system/importPolicy description: This function is used to import policies from a file. arguments: file - mandatory: The policy file in the POST request ''' sendResultMethod = sendResult sendErrorMethod = sendError res = True try: policy_file = request.POST['file'] fileString = "" log.debug("loading policy file to server using POST request. File: %s" % policy_file) # In case of form post requests, it is a "instance" of FieldStorage # i.e. the Filename is selected in the browser and the data is transferred # in an iframe. see: http://jquery.malsup.com/form/#sample4 # if type(policy_file).__name__ == 'instance': log.debug("Field storage file: %s", policy_file) fileString = policy_file.value sendResultMethod = sendXMLResult sendErrorMethod = sendXMLError else: fileString = policy_file log.debug("fileString: %s", fileString) if fileString == "": log.error("Error loading/importing policy file. file empty!") return sendErrorMethod(response, "Error loading policy. File empty!") # the contents of filestring needs to be parsed and stored as policies. from configobj import ConfigObj policies = ConfigObj(fileString.split('\n'), encoding="UTF-8") log.info("read the following policies: %s" % policies) res = len(policies) for policy_name in policies.keys(): ret = setPolicy({ 'name': policy_name, 'action' : policies[policy_name].get('action', ""), 'scope' : policies[policy_name].get('scope', ""), 'realm' : policies[policy_name].get('realm', ""), 'user' : policies[policy_name].get('user', ""), 'time' : policies[policy_name].get('time', ""), 'client': policies[policy_name].get('client', "")}) log.debug("import policy %s: %s" % (policy_name, ret)) c.audit['info'] = "Policies imported from file %s" % policy_file c.audit['success'] = 1 Session.commit() return sendResultMethod(response, res) except Exception as exx: log.error("failed! %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendErrorMethod(response, exx) finally: Session.close() ############################################################ @log_with(log) def checkPolicy(self, action, **params): ''' method: system/checkPolicy description: this function checks if a the given parameter will trigger a policy or not. arguments: * user - the name of the user * realm - the realm * scope - the scope * action * client - the client IP returns: a json result like this: value : { "allowed" : "true", "policy" : <Name der Policy, die das erlaubt hat> } value : { "allowed" : "false", "info" : <sowas wie die Fehlermeldung> } ''' res = {} try: param = getLowerParams(request.params) user = getParam(param, "user", required) realm = getParam(param, "realm", required) scope = getParam(param, "scope", required) action = getParam(param, "action", required) client = getParam(param, "client", required) pol = {} if scope in ["admin", "system", "license"]: pol = self.Policy.getPolicy({"scope":scope}) if len(pol) > 0: # Policy active for this scope! pol = self.Policy.getPolicy({"user":user, "realm":realm, "scope":scope, "action":action, "client":client}) res["allowed"] = len(pol) > 0 res["policy"] = pol if len(pol) > 0: c.audit['info'] = "allowed by policy %s" % pol.keys() else: # No policy active for this scope c.audit['info'] = "allowed since no policies in scope %s" % scope res["allowed"] = True res["policy"] = "No policies in scope %s" % scope else: log.debug("checking policy for client %s, scope %s, action %s, realm %s and user %s" % (client, scope, action, realm, user)) pol = self.Policy.get_client_policy(client, scope, action, realm, user) res["allowed"] = len(pol) > 0 res["policy"] = pol if len(pol) > 0: c.audit['info'] = "allowed by policy %s" % pol.keys() c.audit['action_detail'] = "action = %s, realm = %s, scope = %s"\ % (action, realm, scope) c.audit['success'] = True Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error checking policy: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ########################################################################## @log_with(log) def getPolicy(self, action, **params): """ method: system/getPolicy description: this function is used to retrieve the policies that you defined. arguments: * realm - (optional) will return all policies in the given realm * name - (optional) will only return the policy with the given name * scope - (optional) will only return the policies within the given scope * export - (optional) The filename needs to be specified as the third part of the URL like /system/getPolicy/policy.cfg. It will then be exported to this file. * display_inactive - (optional) if set, then also inactive policies will be displayed returns: a json result with the configuration of the specified policies exception: if an error occurs an exception is serialized and returned """ pol = {} param = getLowerParams(request.params) export = None ### config settings from here try: name = getParam(param, "name", optional) realm = getParam(param, "realm", optional) scope = getParam(param, "scope", optional) display_inactive = getParam(param, "display_inactive", optional) if display_inactive: display_inactive = True route_dict = request.environ.get('pylons.routes_dict') export = route_dict.get('id') log.debug("retrieving policy name: %s, realm: %s, scope: %s" % (name, realm, scope)) pol = {} if name != None: for nam in name.split(','): poli = self.Policy.getPolicy({'name':nam, 'realm':realm, 'scope': scope}, display_inactive=display_inactive) pol.update(poli) else: pol = self.Policy.getPolicy({'name':name, 'realm':realm, 'scope': scope}, display_inactive=display_inactive) c.audit['success'] = True c.audit['info'] = "name = %s, realm = %s, scope = %s" \ % (name, realm, scope) Session.commit() if export: filename = self.Policy.create_policy_export_file(pol, export) wsgi_app = FileApp(filename) return wsgi_app(request.environ, self.start_response) else: return sendResult(response, pol, 1) except Exception as exx: log.error("error getting policy: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def delPolicy(self, action, **params): """ method: system/delPolicy description: this function deletes the policy with the given name arguments: name - the policy with the given name returns: a json result about the delete success exception: if an error occurs an exception is serialized and returned """ res = {} try: param = getLowerParams(request.params) name = getParam(param, "name", required) log.debug("trying to delete policy %s" % name) ret = deletePolicy(name) res["delPolicy"] = {"result": ret} c.audit['success'] = ret c.audit['info'] = name Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("error deleting policy: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close() ######################################################## @log_with(log) def setupSecurityModule(self, action, **params): res = {} try: params = getLowerParams(request.params) hsm_id = params.get('hsm_id', None) from privacyidea.lib.config import getGlobalObject glo = getGlobalObject() sep = glo.security_provider ## for test purpose we switch to an errHSM if isSelfTest(): if params.get('__hsmexception__') == '__ON__': hsm = c.hsm.get('obj') hsm_id = sep.activeOne if type(hsm).__name__ == 'DefaultSecurityModule': hsm_id = sep.setupModule('err', params) if params.get('__hsmexception__') == '__OFF__': hsm = c.hsm.get('obj') hsm_id = sep.activeOne if type(hsm).__name__ == 'ErrSecurityModule': hsm_id = sep.setupModule('default', params) if hsm_id is None: hsm_id = sep.activeOne hsm = c.hsm.get('obj') error = c.hsm.get('error') if hsm is None or len(error) != 0: raise Exception ('current activeSecurityModule >%r< is not initialized::%s:: - Please check your security module configuration and connection!' % (hsm_id, error)) ready = hsm.isReady() res['setupSecurityModule'] = {'activeSecurityModule': hsm_id , 'connected' : ready } ret = ready else: if hsm_id != sep.activeOne: raise Exception ('current activeSecurityModule >%r< could only be changed through the configuration!' % sep.activeOne) ret = sep.setupModule(hsm_id, config=params) hsm = c.hsm.get('obj') ready = hsm.isReady() res['setupSecurityModule'] = {'activeSecurityModule': hsm_id , 'connected' : ready , 'result' : ret} c.audit['success'] = ret Session.commit() return sendResult(response, res, 1) except Exception as exx: log.error("setup failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, exx) finally: Session.close()
class OcraController(BaseController): ''' The OcraController implements challenges/response tokens according to RFC 6287 ''' @log_with(log) def __before__(self, action, **params): ''' Here we see, what action is to be called and check the authorization ''' try: c.audit['success'] = False c.audit['client'] = get_client() self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), token_type_list = get_token_type_list()) if action != "check_t": self.before_identity_check(action) return response except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.error("%r webob.exception %r" % (action, acc)) log.error(traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: log.error("%r exception %r" % (action, exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: pass @log_with(log) def __after__(self, action, **params): c.audit['administrator'] = getUserFromRequest(request).get("login") self.audit.log(c.audit) return response ######################################################## @log_with(log) def request(self, action, **params): """ method: orcra/request description: request a challenge for a user or for a serial number (token). arguments: * serial: (required - string) Serial number of the token, for which a challenge should be generated (either serial or user is required) * user: (required - string) The user for whose token a challenge should be generated If the user has more than one token, an error is returend. (either serial or user is required) * data: (required - String: URLendoced) These are the display data, that can be used to generate the challenge remark: the app will report a wrong qrcode, if the policy {'authentication' : qrtanurl=https://localhost } is not defined !! returns: A JSON respone:: { "version": "privacyIDEA 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": false, }, "detail": { "transactionid" : TRANSAKTIONSID, "data" : DATAOBJECT, } } * transactionid: This is the transaction ID, that is used later for verifying the Return code /TAN. * data: This is an object (URL) which can be used to generate a QR-Coide to be displayed to the QRTAN App exception: """ res = {} description = 'ocra/request: request a challenge for a given user or token (serial). You must either provide a parameter "user" or a parameter "serial".' dataobj = "" try: param = getLowerParams(request.params) self.Policy.checkPolicyPre('ocra', "request") serial = getParam(param, 'serial', optional) user = getUserFromParam(param, optional) if user.isEmpty() and serial is None: ## raise exception log.error("user or serial is required") raise ParameterError("Usage: %s" % description, id=77) message = getParam(param, 'data' , optional) if message is None: message = '' ## ocra token tokens = getTokens4UserOrSerial(user, serial) if len(tokens) > 1 : error = ('More than one token found: unable to create challenge ' 'for (u:%r,s:%r)!' % (user, serial)) log.error(error) raise Exception(error) if len(tokens) == 0: error = ('No token found: unable to create challenge for' ' (u:%r,s:%r)!' % (user, serial)) log.error(error) raise Exception(error) ocra = tokens[0] (transId, challenge, res, url) = ocra.challenge(message) u = urlencode({'u':str(url.encode("utf-8"))}) uInfo = {'tr': transId, 'ch' : challenge, 'me': str(message.encode("utf-8")), 'u': u[2:]} detail = {"transactionid" : transId, 'challenge' : challenge, 'message' : str(message.encode("utf-8")), 'url' : str(url.encode("utf-8")), } ## create the app_url from the data''' dataobj = 'lseqr://req?%s' % (str(urlencode(uInfo))) ## append the signature to the url ''' signature = {'si' : ocra.signData(dataobj)} uInfo['si'] = signature dataobj = '%s&%s' % (dataobj, str(urlencode(signature))) detail["data"] = dataobj c.audit['success'] = res #c.audit['info'] += "%s=%s, " % (k, value) Session.commit() qr = getParam(param, 'qr', optional) if qr is not None: param['alt'] = detail return sendQRImageResult(response, dataobj, param) else: return sendResult(response, res, 1, opt=detail) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx)) finally: Session.close() ## https://privacyideaserver/ocra/check_t?transactionid=TRANSACTIONID&pass=TAN @log_with(log) def check_t(self, action, **params): """ method: orcra/check_t description: verify the response of the ocra token arguments: * transactionid: (required - string) Dies ist eine Transaktions-ID, die bei der Challenge ausgegeben wurde. * pass: (required - string) die response, die der OCRA Token auf Grund der Challenge berechnet hat returns: A JSON response:: { "version": "privacyIDEA 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": { "failcount" : 3, "result": false } }, "id": 0 } exception: """ res = {} description = 'ocra/check_t: validate a token request.' try: param = getLowerParams(request.params) #checkPolicyPre('ocra', "check_t" ) passw = getParam(param, 'pass' , optional) if passw is None: ## raise exception''' log.error("missing pass ") raise ParameterError("Usage: %s Missing parameter 'pass'." % description, id=77) transid = getParam(param, 'transactionid', optional) if transid is None: ## raise exception''' log.error("missing transactionid, user or serial number of token") raise ParameterError("Usage: %s Missing parameter 'transactionid'." % description, id=77) ## if we have a transaction, get serial from this challenge value = {} ocraChallenge = OcraTokenClass.getTransaction(transid) if ocraChallenge is not None: serial = ocraChallenge.tokenserial tokens = getTokens4UserOrSerial(serial=serial) if len(tokens) == 0 or len(tokens) > 1: raise Exception('tokenmismatch for token serial: %s' % (unicode(serial))) theToken = tokens[0] tok = theToken.token desc = tok.get() realms = desc.get('privacyIDEA.RealmNames') if realms is None or len(realms) == 0: realm = getDefaultRealm() elif len(realms) > 0: realm = realms[0] userInfo = getUserInfo(tok.privacyIDEAUserid, tok.privacyIDEAIdResolver, tok.privacyIDEAIdResClass) user = User(login=userInfo.get('username'), realm=realm) (ok, opt) = checkSerialPass(serial, passw, user=user, options={'transactionid':transid}) failcount = theToken.getFailCount() value['result'] = ok value['failcount'] = int(failcount) else: ## no challenge found for this transid value['result'] = False value['failure'] = 'No challenge for transaction %r found'\ % transid c.audit['success'] = res #c.audit['info'] += "%s=%s, " % (k, value) Session.commit() return sendResult(response, value, 1) except Exception as e : log.error("failed: %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendResult(response, unicode(e), 0) finally: Session.close() ''' https://privacyideaserver/ocra/checkstatus?transactionid=TRANSACTIONID https://privacyideaserver/ocra/checkstatus?serial=SERIENNUMMER https://privacyideaserver/ocra/checkstatus?user=BENUTZER ''' @log_with(log) def checkstatus(self, action, **params): """ method: orcra/checkstatus description: Methode zur assynchronen Ueberpruefungen eines Challenge Response Valiadation requests arguments: * transactionid: (required one of - string - (hex)) Dies ist eine Transaktions-ID, die bei der Challenge ausgegeben wurde. * serial: (required one of - string) die Serien Nummer des OCRA Token * user: (required one of - string) die Benutzer eines Tokens required is one of (user,serial,transactionid) returns: A JSON response:: { "version": "privacyIDEA 2.4", "jsonrpc": "2.0", "result": { "status": true, "value": [ { "serial": SERIENNUMMER1, "transactionid": TRANSACTIONID1, "received_tan": true, "valid_tan": true, "failcount": 0 }, { "serial": SERIENNUMMER1, "transactionid": TRANSACTIONID2, "received_tan": false, "valid_tan": false, "failcount": 0 }, { "serial": SERIENNUMMER2, "transactionid": TRANSACTIONID3, "received_tan": true, "valid_tan": false, "failcount": 2 }, ] }, "id": 0 } exception: """ res = {} description = 'ocra/checkstatus: check the token status - for assynchronous verification. Missing parameter: You need to provide one of the parameters "transactionid", "user" or "serial"' try: param = getLowerParams(request.params) self.Policy.checkPolicyPre('ocra', "status") transid = getParam(param, 'transactionid' , optional) user = getUserFromParam(param, optional) #user = getParam(param, 'user' ,optional) serial = getParam(param, 'serial' , optional) if transid is None and user.isEmpty() and serial is None: ## raise exception log.error("missing transactionid, user or serial number for token") raise ParameterError("Usage: %s" % description, id=77) tokens = [] serials = set() status = [] if serial is not None: serials.add(serial) ## if we have a transaction, get serial from this challenge if transid is not None : ocraChallenge = None try: ocraChallenge = OcraTokenClass.getTransaction(transid) except: pass if ocraChallenge is not None: serials.add(ocraChallenge.tokenserial) ## if we have a serial number of token if len(serials) > 0: for serial in serials: tokens.extend(getTokens4UserOrSerial(serial=serial)) ## if we have a user if user.isEmpty() == False: try: tokens.extend(getTokens4UserOrSerial(user=user)) except: log.warning("no token or user %r found!" % user) for token in tokens: if token.getType() == 'ocra': challenges = [] if transid is None: serial = token.getSerial() challenges = OcraTokenClass.getTransactions4serial(serial) else: challenges.append(OcraTokenClass.getTransaction(transid)) for challenge in challenges: stat = token.getStatus(challenge.transid) if stat is not None and len(stat) > 0: status.append(stat) res['values'] = status c.audit['success'] = res Session.commit() return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendResult(response, unicode(exx), 0) finally: Session.close() @log_with(log) def getActivationCode(self, action, **params): ''' method: orcra/getActivationCode description: returns an valid example activcation code arguments: ./. returns: JSON with "activationcode": "JZXW4ZI=2A" ''' from privacyidea.lib.crypto import createActivationCode res = {} #description = 'ocra/getActivationCode' try: params = getLowerParams(request.params) self.Policy.checkPolicyPre('ocra', "activationcode") ac = str(params.get('activationcode')) activationCode = createActivationCode(acode=ac) res = {'activationcode':activationCode} Session.commit() return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def calculateOtp(self, action, **params): ''' ''' from privacyidea.lib.crypto import kdf2 from privacyidea.lib.ocra import OcraSuite from datetime import datetime from urlparse import urlparse from urlparse import parse_qs res = {} #description = 'ocra/calculateOtp: calculate the first otp from the given init2 response ' try: params = getLowerParams(request.params) self.Policy.checkPolicyPre('ocra', "calcOTP") sharedsecret = params.get('sharedsecret') activationcode = params.get('activationcode') nonce = params.get('nonce') ocrasuite = params.get('ocrasuite') challenge = params.get('challenge') counter = params.get('counter') ocrapin = params.get('ocrapin') nonce3 = params.get('no') ocrasuite3 = params.get('os') #serial3 = params.get('se') challenge = params.get('challenge') counter = params.get('counter') ocrapin = params.get('ocrapin') init1 = params.get('init1') init2 = params.get('init2') ## parse init1 ''' if init1 is not None: ## now parse the appurl for the ocrasuite ''' uri = urlparse(init1.replace('lseqr://', 'http://')) qs = uri.query qdict = parse_qs(qs) ocrasuite2 = qdict.get('os', None) if ocrasuite2 is not None and len(ocrasuite2) > 0: ocrasuite2 = ocrasuite2[0] if ocrasuite is None: ocrasuite = ocrasuite2 sharedsecret2 = qdict.get('sh', None) if sharedsecret2 is not None and len(sharedsecret2) > 0: sharedsecret2 = sharedsecret2[0] if sharedsecret is None: sharedsecret = sharedsecret2 ## parse init1 if init2 is not None: ## now parse the appurl for the ocrasuite uri = urlparse(init2.replace('lseqr://', 'http://')) qs = uri.query qdict = parse_qs(qs) challenge2 = qdict.get('ch', None) if challenge2 is not None and len(challenge2) > 0: challenge2 = challenge2[0] if challenge is None: challenge = challenge2 nonce2 = qdict.get('no', None) if nonce2 is not None and len(nonce2) > 0: nonce2 = nonce2[0] if nonce is None: nonce = nonce2 if ocrapin is None: ocrapin = '' if counter is None: counter = 0 if nonce3 is not None: nonce = unicode(nonce3) if ocrasuite3 is not None: ocrasuite = unicode(ocrasuite3) ## now we have all in place for the key derivation to create the new key ## sharedsecret, activationcode and nonce key_len = 20 if ocrasuite.find('-SHA256'): key_len = 32 elif ocrasuite.find('-SHA512'): key_len = 64 if sharedsecret is not None: sharedsecret = unicode(sharedsecret) if nonce is not None: nonce = unicode(nonce) if activationcode is not None: activationcode = unicode(activationcode) newkey = kdf2(sharedsecret, nonce, activationcode, len=key_len) ## hnewkey = binascii.hexlify(newkey) ocra = OcraSuite(ocrasuite) param = {} param['C'] = int(counter) param['Q'] = unicode(challenge) param['P'] = unicode(ocrapin) param['S'] = '' if ocra.T is not None: ## Default value for G is 1M, i.e., time-step size is one minute and the ## T represents the number of minutes since epoch time [UT]. now = datetime.now() stime = now.strftime("%s") itime = int(stime) param['T'] = itime data = ocra.combineData(**param) otp = ocra.compute(data, newkey) res = {'otp':otp} Session.commit() return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, pe) except Exception as e: log.error("failed: %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(e), 0) finally: Session.close()
class GettokenController(BaseController): ''' The privacyidea.controllers are the implementation of the web-API to talk to the privacyIDEA server. The ValidateController is used to validate the username with its given OTP value. The Tagespasswort Token uses this controller to retrieve the current OTP value of the Token and be able to set it in the application The functions of the GettokenController are invoked like this https://server/gettoken/<functionname> The functions are described below in more detail. ''' @log_with(log) def __before__(self, action, **params): try: c.audit['client'] = get_client() if request.params.get('serial'): tokentype = getTokenType(request.params.get('serial')) else: tokentype = None self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), tokentype = tokentype, token_type_list = get_token_type_list()) self.before_identity_check(action) except Exception as exx: log.error("%r exception %r" % (action, exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: pass @log_with(log) def __after__(self, action, **params): c.audit['administrator'] = getUserFromRequest(request).get("login") if request.params.has_key('serial'): c.audit['serial'] = request.params['serial'] c.audit['token_type'] = getTokenType(request.params['serial']) self.audit.log(c.audit) @log_with(log) def getmultiotp(self, action, **params): ''' 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 :param serial: the serial number of the token :param count: number of otp values to return :param curTime: used ONLY for internal testing: datetime.datetime object :type curTime: datetime object :param timestamp: the unix time :type timestamp: int :return: JSON response ''' getotp_active = config.get("privacyideaGetotp.active") if "True" != getotp_active: return sendError(response, "getotp is not activated.", 0) param = request.params ret = {} try: serial = getParam(param, "serial", required) tokenrealms = getTokenRealms(serial) count = int(getParam(param, "count", required)) curTime = getParam(param, "curTime", optional) timestamp = getParam(param, "timestamp", optional) view = getParam(param, "view", optional) r1 = self.Policy.checkPolicyPre('admin', 'getotp', param, tokenrealms = tokenrealms) log.debug("admin-getotp returned %s" % r1) max_count = self.Policy.checkPolicyPre('gettoken', 'max_count', param, tokenrealms = tokenrealms) log.debug("checkpolicypre returned %s" % max_count) if count > max_count: count = max_count log.debug("retrieving OTP value for token %s" % serial) ret = get_multi_otp(serial, count=int(count), curTime=curTime, timestamp=timestamp) 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("gettoken/getotp policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("gettoken/getmultiotp failed: %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendError(response, "gettoken/getmultiotp failed: %s" % unicode(e), 0) finally: Session.close() @log_with(log) def getotp(self, action, **params): ''' This function is used to retrieve the current otp value for a given user or a given serial If the user has more than one token, the list of the tokens is returend. method: gettoken/getotp arguments: user - username / loginname realm - additional realm to match the user to a useridresolver serial - the serial number of the token curTime - used ONY for internal testing: datetime.datetime object returns: JSON response ''' getotp_active = config.get("privacyideaGetotp.active") if "True" != getotp_active: return sendError(response, "getotp is not activated.", 0) param = request.params ret = {} res = -1 otpval = "" passw = "" serials = [] try: serial = getParam(param, "serial", optional) user = getUserFromParam(param, optional) curTime = getParam(param, "curTime", optional) c.audit['user'] = user.login if "" != user.login: c.audit['realm'] = user.realm or getDefaultRealm() if serial: log.debug("retrieving OTP value for token %s" % serial) elif user.login: log.debug("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("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("retrieving OTP for token %s for user %s@%s" % (serial, user.login, user.realm)) else: log.debug("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: tokenrealms = getTokenRealms(serial) max_count = self.Policy.checkPolicyPre('gettoken', 'max_count', param, tokenrealms = tokenrealms) log.debug("checkpolicypre returned %s" % max_count) if max_count <= 0: return sendError(response, "The policy forbids receiving OTP values for the token %s in this realm" % serial , 1) (res, pin, otpval, passw) = getOtp(serial, curTime=curTime) c.audit['success'] = True if int(res) < 0: ret['result'] = False if -1 == otpval: ret['description'] = "No Token with this serial number" if -2 == otpval: ret['description'] = "This Token does not support the getOtp function" if -3 == otpval: ret['description'] = "The user has more than one token" ret['serials'] = serials if -4 == otpval: ret['description'] = "No Token found for this user" if -5 == otpval: ret['description'] = "you need to provide a user or a serial" else: ret['result'] = True ret['otpval'] = otpval ret['pin'] = pin ret['pass'] = passw Session.commit() return sendResult(response, ret , 0) except PolicyException as pe: log.error("gettoken/getotp policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("gettoken/getotp failed: %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendError(response, "gettoken/getotp failed: %s" % unicode(e), 0) finally: Session.close()
class MachineController(BaseController): @log_with(log) def __before__(self, action, **params): ''' ''' try: c.audit['success'] = False c.audit['client'] = get_client() self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), tokenrealms=request.params.get('serial'), token_type_list=get_token_type_list()) self.set_language() self.before_identity_check(action) Session.commit() return request except webob.exc.HTTPUnauthorized as acc: # the exception, when an abort() is called if forwarded log.info("%r: webob.exception %r" % (action, acc)) log.info(traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: # pragma: no cover log.error("exception %r" % (action, exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: pass @log_with(log) def __after__(self, action, **params): ''' ''' params = {} try: params.update(request.params) c.audit['administrator'] = getUserFromRequest(request).get("login") if 'serial' in params: c.audit['serial'] = request.params['serial'] c.audit['token_type'] = getTokenType(params.get('serial')) self.audit.log(c.audit) Session.commit() return request except Exception as e: # pragma: no cover log.error("unable to create a session cookie: %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendError(response, e, context='after') finally: Session.close() @log_with(log) def create(self, action, **params): ''' Create a new client machine entry :param name: the unique name of the machine (required). Can be the FQDN. :param desc: description of the machine :param ip: The IP address of the machine (required) :param decommission: A date when the machine will not be valid anymore :return: True or False if the creation was successful. ''' try: res = False param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'create') param.update(request.params) machine_name = getParam(param, "name", required) ip = getParam(param, "ip", required) desc = getParam(param, "desc", optional) decommission = getParam(param, "decommission", optional) machine = create_machine(machine_name, ip=ip, desc=desc, decommission=decommission) if machine: res = True Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def delete(self, action, **params): ''' Delete an existing client machine entry :param name: the unique name of the machine :return: value is either true (success) or false (fail) ''' try: res = {} param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'delete') param.update(request.params) machine_name = getParam(param, "name", required) res = delete_machine(machine_name) Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def show(self, action, **params): ''' Returns a list of the client machines. :param name: Optional parameter to only show this single machine :return: JSON details ''' try: res = {} param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'show') param.update(request.params) machine_name = getParam(param, "name", optional) res = show_machine(machine_name) Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def addtoken(self, action, **params): ''' Add a token and a application to a machine :param name: Name of the machine :param serial: serial number of the token :param application: name of the application :param option_*: parameter is passed as additional option to the machinetoken to be stored in machine_t_options table. In case of LUKS application this can be "option_slot" ''' try: res = False param = {} options = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'addtoken') param.update(request.params) machine_name = getParam(param, "name", required) serial = getParam(param, "serial", required) application = getParam(param, "application", required) if application.lower() not in config.get("applications").keys(): log.error("Unknown application %r. Available applications: " "%r" % (application, config.get("applications").keys())) raise Exception("Unkown application!") for p in param.keys(): if p.startswith("option_"): options[p] = param.get(p) mt = addtoken(machine_name, serial, application, options=options) if mt: res = True Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def addoption(self, action, **params): ''' Add an option to a machinetoken definition :param mtid: id of the machine token definition :param name: machine_name :param serial: serial number of the token :param application: application :param option_*: name of the option. In case of LUKS application this can be "option_slot" You either need to provide the machine-token-id (mtid) directly or you need to provide the tuple (name, serial, application) ''' try: num = -1 param = {} options = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'addtoken') param.update(request.params) mtid = getParam(param, "mtid", optional) machine_name = getParam(param, "name", optional) serial = getParam(param, "serial", optional) application = getParam(param, "application", optional) if not (mtid or (machine_name and serial and application)): raise ParameterError("You need to specify either mtid or" "the tuple name, serial, application", id=201) for p in param.keys(): if p.startswith("option_"): options[p] = param.get(p) num = addoption(mtid, name=machine_name, serial=serial, application=application, options=options) Session.commit() c.audit["success"] = True return sendResult(response, num, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def deloption(self, action, **params): ''' Delete an option from a machinetoken definition :param mtid: id of the machine token definition :param name: machine_name :param serial: serial number of the token :param application: application :param key: key of the option to delete You either need to provide the machine-token-id (mtid) directly or you need to provide the tuple (name, serial, application) ''' try: num = -1 param = {} options = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'deltoken') param.update(request.params) mtid = getParam(param, "mtid", optional) machine_name = getParam(param, "name", optional) serial = getParam(param, "serial", optional) option_key = getParam(param, "key", required) application = getParam(param, "application", optional) if not (mtid or (machine_name and serial and application)): raise ParameterError("You need to specify either mtid or" "the tuple name, serial, application", id=201) num = deloption(mtid, name=machine_name, serial=serial, application=application, key=option_key) Session.commit() c.audit["success"] = True return sendResult(response, num, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def deltoken(self, action, **params): ''' delete a token and a application from a machine :param name: Name of the machine :param serial: serial number of the token :param application: name of the application ''' try: res = False param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'deltoken') param.update(request.params) machine_name = getParam(param, "name", required) serial = getParam(param, "serial", required) application = getParam(param, "application", required) res = deltoken(machine_name, serial, application) Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def showtoken(self, action, **params): ''' show a token and a application from a machine This function is used in the flexigrid management :param name: Name of the machine :param serial: serial number of the token :param application: name of the application :param flexi: if set to 1, we do return flexigrid input ''' try: res = False param = {} # check machine authorization self.Policy.checkPolicyPre('machine', 'showtoken') param.update(request.params) machine_name = getParam(param, "name", optional) serial = getParam(param, "serial", optional) application = getParam(param, "application", optional) # if set, this should be returned for flexigrid flexi = getParam(param, "flexi", optional) res = showtoken(machine_name, serial, application, flexi=flexi, params=param) Session.commit() c.audit["success"] = True if flexi: response.content_type = 'application/json' return json.dumps(res, indent=3) else: return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def gettokenapps(self, action, **params): ''' returns the apps and the authentication information for the given machine. If an application is given only the authentication item for this application is returned. otherwise the application items for all applications are returned. TODO: Authenticate the client machine :param name: the machine name - otherwise the machine is identified by the IP :type name: string, optional :param application: the name of the application. If the application is given the response will also conatin the auth_item :type application: string, optional :param serial: The serial number of the token :return: dictionary with machine and authentication information {"total": 2, "machines": { 1 : {"application": "luks", "auth_item": {"challenge": "hex...", "response":: "hex..."}, "id": 1, "ip": 10.0.0.1, "machine_id": 1, "machinename": "computerABC", "serial": "<serialnumber of token>", "token_id": 1 }, 2 : ... } } ''' try: res = False param = {} self.Policy.checkPolicyPre('machine', 'gettokenapps') param.update(request.params) machine_name = getParam(param, "name", optional) application = getParam(param, "application", optional) serial = getParam(param, "serial", optional) # In case of LUKS and Yubikey we need the client to # pass the challenge as the challenge is the Password challenge = getParam(param, "challenge", optional) client_ip = get_client() if application: if application not in config.get("applications").keys(): log.error("Unknown application %r. Available applications:" "%r" % (application, config.get("applications").keys())) application_module = config.get("applications").get(application) res = get_token_apps(machine=machine_name, application=application, application_module=application_module, serial=serial, client_ip=client_ip, challenge=challenge) Session.commit() c.audit["success"] = True return sendResult(response, res, 1) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close() @log_with(log) def getapplications(self, action, **params): ''' Returns a list of available applications ''' try: return sendResult(response, config.get("applications").keys()) except PolicyException as pe: log.error("policy failed: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe)) except Exception as exx: # pragma: no cover log.error("failed: %r" % exx) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(exx), 0) finally: Session.close()
class ManageController(BaseController): @log_with(log) def __before__(self, action, **params): try: c.audit['success'] = False c.audit['client'] = get_client() self.set_language() c.version = get_version() c.licenseinfo = get_copyright_info() self.Policy = PolicyClass(request, config, c, get_privacyIDEA_config(), token_type_list = get_token_type_list()) c.polDefs = get_policy_definitions() self.before_identity_check(action) c.tokenArray = [] c.user = self.authUser.login c.realm = self.authUser.realm except webob.exc.HTTPUnauthorized as acc: ## the exception, when an abort() is called if forwarded log.info("%r webob.exception %r" % (action, acc)) log.info(traceback.format_exc()) Session.rollback() Session.close() raise acc except Exception as exx: log.error("exception %r" % (action, exx)) log.error(traceback.format_exc()) Session.rollback() Session.close() return sendError(response, exx, context='before') finally: pass @log_with(log) def __after__(self, action, **params): if c.audit['action'] in [ 'manage/tokenview_flexi', 'manage/userview_flexi' ]: c.audit['administrator'] = getUserFromRequest(request).get("login") if request.params.has_key('serial'): c.audit['serial'] = request.params['serial'] c.audit['token_type'] = getTokenType(request.params['serial']) self.audit.log(c.audit) @log_with(log) def index(self, action, **params): ''' This is the main function of the management web UI ''' try: c.title = "privacyIDEA Management" admin_user = getUserFromRequest(request) if admin_user.has_key('login'): c.admin = admin_user['login'] log.debug("importers: %s" % IMPORT_TEXT) c.importers = IMPORT_TEXT ## add render info for token type config confs = _getTokenTypeConfig('config') token_config_tab = {} token_config_div = {} for conf in confs: tab = '' div = '' try: #loc = conf +'_token_settings' tab = confs.get(conf).get('title') #tab = '<li ><a href=#'+loc+'>'+tab+'</a></li>' div = Template(confs.get(conf).get('html')).render() #div = +div+'</div>' except Exception as e: log.debug('no config info for token type %s (%r)' % (conf, e)) if tab is not None and div is not None and len(tab) > 0 and len(div) > 0: token_config_tab[conf] = tab token_config_div[conf] = div c.token_config_tab = token_config_tab c.token_config_div = token_config_div ## add the enrollment fragments from the token definition ## tab: <option value="ocra">${_("OCRA - challenge/response Token")}</option> ## div: "<div id='"+ tt + "'>"+enroll+"</div>" enrolls = _getTokenTypeConfig('init') token_enroll_tab = {} token_enroll_div = {} for conf in enrolls: tab = '' div = '' try: tab = enrolls.get(conf).get('title') div = enrolls.get(conf).get('html') except Exception as e: log.debug('no enrollment info for token type %s (%r)' % (conf, e)) if tab is not None and div is not None and len(tab) > 0 and len(div) > 0: token_enroll_tab[conf] = tab token_enroll_div[conf] = div c.token_enroll_tab = token_enroll_tab c.token_enroll_div = token_enroll_div c.tokentypes = _getTokenTypes() http_host = request.environ.get("HTTP_HOST") url_scheme = request.environ.get("wsgi.url_scheme") c.logout_url = "%s://%s/account/logout" % (url_scheme, http_host) Session.commit() ren = render('/manage/start.mako') return ren except PolicyException as pe: log.error("Error during checking policies: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as ex: log.error("failed! %r" % ex) log.error(traceback.format_exc()) Session.rollback() return sendError(response, ex) finally: Session.close() ##### TODO: CKO: remove it. It is not used # # def tokentype(self): # ''' # ''' # c.title = 'TokenTypeInfo' # g = config['pylons.app_globals'] # tokens = g.tokenclasses # ttinfo = [] # ttinfo.extend(tokens.keys()) # for tok in tokens: # tclass = tokens.get(tok) # tclass_object = newToken(tclass) # if hasattr(tclass_object, 'getClassType'): # ii = tclass_object.getClassType() # ttinfo.append(ii) # # c.tokeninfo = ttinfo # # return render('/manage/tokentypeinfo.mako') def policies(self): ''' This is the template for the policies TAB ''' c.title = "privacyIDEA Management - Policies" return render('/manage/policies.mako') def machines(self): ''' This is the template for the policies TAB ''' c.title = "privacyIDEA Management - Machines" return render('/manage/machines.mako') def audittrail(self): ''' This is the template for the audit trail TAB ''' c.title = "privacyIDEA Management - Audit Trail" return render('/manage/audit.mako') def tokenview(self): ''' This is the template for the token TAB ''' c.title = "privacyIDEA Management" c.tokenArray = [] return render('/manage/tokenview.mako') def userview(self): ''' This is the template for the token TAB ''' c.title = "privacyIDEA Management" c.tokenArray = [] return render('/manage/userview.mako') def custom_style(self): ''' If this action was called, the user hasn't created a custom-style.css yet. To avoid hitting the debug console over and over, we serve an empty file. ''' response.headers['Content-type'] = 'text/css' return '' @log_with(log) def tokenview_flexi(self, action, **params): ''' This function is used to fill the flexigrid. Unlike the complex /admin/show function, it only returns a simple array of the tokens. ''' param = request.params try: #serial = getParam(param,"serial",optional) c.page = getParam(param, "page", optional) c.filter = getParam(param, "query", optional) c.qtype = getParam(param, "qtype", optional) c.sort = getParam(param, "sortname", optional) c.dir = getParam(param, "sortorder", optional) c.psize = getParam(param, "rp", optional) filter_all = None filter_realm = None user = User() if c.qtype == "loginname": if "@" in c.filter: (login, realm) = c.filter.split("@") user = User(login, realm) else: user = User(c.filter) elif c.qtype == "all": filter_all = c.filter elif c.qtype == "realm": filter_realm = c.filter # check admin authorization res = self.Policy.checkPolicyPre('admin', 'show', param , user=user) filterRealm = res['realms'] # check if policies are active at all # If they are not active, we are allowed to SHOW any tokens. pol = self.Policy.getAdminPolicies("show") # If there are no admin policies, we are allowed to see all realms if not pol['active']: filterRealm = ["*"] # check if we only want to see ONE realm or see all realms we are allowerd to see. if filter_realm: if filter_realm in filterRealm or '*' in filterRealm: filterRealm = [filter_realm] log.debug("admin >%s< may display the following realms: %s" % (pol['admin'], pol['realms'])) log.debug("page: %s, filter: %s, sort: %s, dir: %s" % (c.page, c.filter, c.sort, c.dir)) if c.page is None: c.page = 1 if c.psize is None: c.psize = 20 log.debug("calling TokenIterator for user=%s@%s, filter=%s, filterRealm=%s" % (user.login, user.realm, filter_all, filterRealm)) c.tokenArray = TokenIterator(user, None, c.page , c.psize, filter_all, c.sort, c.dir, filterRealm=filterRealm) c.resultset = c.tokenArray.getResultSetInfo() # If we have chosen a page to big! lines = [] for tok in c.tokenArray: lines.append( { 'id' : tok['privacyIDEA.TokenSerialnumber'], 'cell': [ tok['privacyIDEA.TokenSerialnumber'], tok['privacyIDEA.Isactive'], tok['User.username'], tok['privacyIDEA.RealmNames'], tok['privacyIDEA.TokenType'], tok['privacyIDEA.FailCount'], tok['privacyIDEA.TokenDesc'], tok['privacyIDEA.MaxFail'], tok['privacyIDEA.OtpLen'], tok['privacyIDEA.CountWindow'], tok['privacyIDEA.SyncWindow'], tok['privacyIDEA.Userid'], tok['privacyIDEA.IdResolver'], ] } ) # We need to return 'page', 'total', 'rows' response.content_type = 'application/json' res = { "page": int(c.page), "total": c.resultset['tokens'], "rows": lines } c.audit['success'] = True Session.commit() return json.dumps(res, indent=3) except PolicyException as pe: log.error("Error during checking policies: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("failed: %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendError(response, e) finally: Session.close() @log_with(log) def userview_flexi(self, action, **params): ''' This function is used to fill the flexigrid. Unlike the complex /admin/userlist function, it only returns a simple array of the tokens. ''' param = request.params try: #serial = getParam(param,"serial",optional) c.page = getParam(param, "page", optional) c.filter = getParam(param, "query", optional) qtype = getParam(param, "qtype", optional) c.sort = getParam(param, "sortname", optional) c.dir = getParam(param, "sortorder", optional) c.psize = getParam(param, "rp", optional) c.realm = getParam(param, "realm", optional) user = getUserFromParam(param, optional) # check admin authorization # check if we got a realm or resolver, that is ok! self.Policy.checkPolicyPre('admin', 'userlist', { 'user': "******", 'realm' : c.realm }) if c.filter == "": c.filter = "*" log.debug("page: %s, filter: %s, sort: %s, dir: %s" % (c.page, c.filter, c.sort, c.dir)) if c.page is None: c.page = 1 if c.psize is None: c.psize = 20 c.userArray = getUserList({ qtype:c.filter, 'realm':c.realm }, user) c.userNum = len(c.userArray) lines = [] for u in c.userArray: # shorten the useridresolver, to get a better display value resolver_display = "" if "useridresolver" in u: if len(u['useridresolver'].split(".")) > 3: resolver_display = u['useridresolver'].split(".")[-1] + " (" + u['useridresolver'].split(".")[-3] + ")" else: resolver_display = u['useridresolver'] lines.append( { 'id' : u['username'], 'cell': [ (u['username']) if u.has_key('username') else (""), (resolver_display), (u['surname']) if u.has_key('surname') else (""), (u['givenname']) if u.has_key('givenname') else (""), (u['email']) if u.has_key('email') else (""), (u['mobile']) if u.has_key('mobile') else (""), (u['phone']) if u.has_key('phone') else (""), (u['userid']) if u.has_key('userid') else (""), ] } ) # sorting reverse = False sortnames = { 'username' : 0, 'useridresolver' : 1, 'surname' : 2, 'givenname' : 3, 'email' : 4, 'mobile' :5, 'phone' : 6, 'userid' : 7 } if c.dir == "desc": reverse = True lines = sorted(lines, key=lambda user: user['cell'][sortnames[c.sort]] , reverse=reverse) # end: sorting # reducing the page if c.page and c.psize: page = int(c.page) psize = int(c.psize) start = psize * (page - 1) end = start + psize lines = lines[start:end] # We need to return 'page', 'total', 'rows' response.content_type = 'application/json' res = { "page": int(c.page), "total": c.userNum, "rows": lines } c.audit['success'] = True Session.commit() return json.dumps(res, indent=3) except PolicyException as pe: log.error("Error during checking policies: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("failed: %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendError(response, e) finally: Session.close() @log_with(log) def tokeninfo(self, action, **params): ''' 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 = self.Policy.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 = self.Policy.getAdminPolicies("show") if not pol['active']: filterRealm = ["*"] log.info("admin >%s< may display the following realms: %s" % (res['admin'], filterRealm)) log.info("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 "privacyIDEA.TokenInfo" == k: try: # Try to convert string to Dictionary c.tokeninfo['privacyIDEA.TokenInfo'] = json.loads(c.tokeninfo['privacyIDEA.TokenInfo']) except: pass return render('/manage/tokeninfo.mako') except PolicyException as pe: log.error("Error during checking policies: %r" % pe) log.error(traceback.format_exc()) Session.rollback() return sendError(response, unicode(pe), 1) except Exception as e: log.error("failed! %r" % e) log.error(traceback.format_exc()) Session.rollback() return sendError(response, e) finally: Session.close()