예제 #1
0
    def samlcheck(self):
        '''
        This function is used to validate the username and the otp value/password
        in a SAML environment. If ``linotp.allowSamlAttributes = True``
        then the attributes of the authenticated users are also contained
        in the response.

        method:
            validate/samlcheck

        arguments:
            * user:    username / loginname
            * pass:    the password that consists of a possible fixes password component and the OTP value
            * realm:   optional realm to match the user to a useridresolver

        returns:
            JSON response
        '''

        try:
            opt = None
            param = self.request_params
            (ok, opt) = self._check(param)
            attributes = {}

            if True == ok:
                allowSAML = False
                try:
                    allowSAML = getFromConfig("allowSamlAttributes")
                except:
                    log.warning("[samlcheck] Calling controller samlcheck. But allowSamlAttributes is False.")
                if "True" == allowSAML:
                    ## Now we get the attributes of the user
                    user = getUserFromParam(param)
                    (uid, resId, resIdC) = getUserId(user)
                    userInfo = getUserInfo(uid, resId, resIdC)
                    log.debug("[samlcheck] getting attributes for: %s@%s"
                              % (user.login, user.realm))

                    res = userInfo
                    for key in ['username',
                                'surname',
                                'mobile',
                                'phone',
                                'givenname',
                                'email']:
                        if key in res:
                            attributes[key] = res[key]

            Session.commit()
            return sendResult(response, { 'auth': ok, 'attributes' : attributes } , 0, opt)

        except Exception as exx:
            log.exception("[samlcheck] validate/check failed: %r" % exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
예제 #2
0
파일: validate.py 프로젝트: gsnbng/LinOTP
    def check_yubikey(self):
        '''
        This function is used to validate the output of a yubikey

        method:
            validate/check_yubikey

        :param pass: The password that consist of the static yubikey prefix and the otp
        :type pass: string

        :return: JSON Object

        returns:
            JSON response::

                {
                    "version": "LinOTP 2.4",
                    "jsonrpc": "2.0",
                    "result": {
                        "status": true,
                        "value": false
                    },
                    "detail" : {
                        "username": username,
                        "realm": realm
                    },
                    "id": 0
                }
        '''

        param = request.params
        passw = getParam(param, "pass", required)
        try:

            ok = False
            try:
                vh = ValidationHandler()
                ok, opt = vh.checkYubikeyPass(passw)
                c.audit['success'] = ok

            except AuthorizeException as exx:
                log.warning("[check_yubikey] authorization failed for validate/check_yubikey: %r"
                            % exx)
                c.audit['success'] = False
                c.audit['info'] = unicode(exx)
                ok = False

            Session.commit()
            return sendResult(response, ok, 0, opt=opt)

        except Exception as exx:
            log.exception("[check_yubikey] validate/check_yubikey failed: %r" % exx)
            c.audit['info'] = unicode(exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
            log.debug('[check_yubikey] done')
예제 #3
0
파일: validate.py 프로젝트: gsnbng/LinOTP
    def pair(self):

        try:

            params = dict(**request.params)
            enc_response = params.get('pairing_response')
            if enc_response is None:
                raise Exception('Parameter missing')

            dec_response = decrypt_pairing_response(enc_response)

            if not dec_response.serial:
                raise ValidateError('Pairing responses with no serial attached '
                                    'are currently not implemented.')

            serial = dec_response.serial
            user_public_key = dec_response.user_public_key
            user_token_id = dec_response.user_token_id
            user = dec_response.user_login

            user = getUserFromParam(params, optional)

            # TODO: pairing policy
            tokens = getTokens4UserOrSerial(None, serial)

            if not tokens:
                raise Exception('Invalid serial in pairing response')

            if len(tokens) > 1:
                raise Exception('Multiple tokens found. Pairing not possible')

            token = tokens[0]

            if token.type != 'qr':
                raise Exception('Pairing is only implemented for the qrtoken')

            token.ensure_state('pairing_url_sent')
            token.addToTokenInfo('user_token_id', user_token_id)
            b64_user_public_key = b64encode(user_public_key)
            token.addToTokenInfo('user_public_key', b64_user_public_key)

            params['serial'] = serial
            params['user_public_key'] = user_public_key
            params['user_token_id'] = user_token_id
            params['user'] = user
            params['content_type'] = CONTENT_TYPE_PAIRING
            params['data'] = serial

            token.change_state('pairing_response_received')
            Session.commit()
            return sendResult(response, False)

        except Exception:
            Session.rollback()
            return sendResult(response, False, 0, status=False)

        finally:
            Session.close()
예제 #4
0
    def check_t(self):

        param = self.request_params.copy()
        value = {}
        ok = False
        opt = {}

        try:
            if 'pass' not in param:
                raise ParameterError("Missing parameter: 'pass'")

            passw = param['pass']

            transid = param.get('state', None)
            if transid is not None:
                param['transactionid'] = transid
                del param['state']

            if transid is None:
                transid = param.get('transactionid', None)

            if transid is None:
                raise Exception("missing parameter: state or transactionid!")

            vh = ValidationHandler()
            (ok, opt) = vh.check_by_transactionid(transid=transid,
                                                  passw=passw,
                                                  options=param)

            value['value'] = ok
            value['failcount'] = int(opt.get('failcount', 0))

            c.audit['success'] = ok
            Session.commit()

            qr = param.get('qr', None)
            if qr and opt and 'message' in opt:
                try:
                    dataobj = opt.get('message')
                    param['alt'] = "%s" % opt
                    if 'transactionid' in opt:
                        param['transactionid'] = opt['transactionid']
                    return sendQRImageResult(response, dataobj, param)
                except Exception as exc:
                    log.warning("failed to send QRImage: %r " % exc)
                    return sendQRImageResult(response, opt, param)
            else:
                return sendResult(response, value, 1, opt=opt)

        except Exception as exx:
            log.exception("[check_t] validate/check_t failed: %r" % exx)
            c.audit['info'] = unicode(exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
예제 #5
0
    def check_status(self):
        """
        check the status of a transaction - for polling support
        """

        try:

            param = self.request_params

            #
            # we require either state or transactionid as parameter

            transid = param.get('state', param.get('transactionid', None))
            if not transid:
                raise ParameterError(_('Missing required parameter "state" or '
                                     '"transactionid"!'))

            #
            # serial is an optional parameter

            serial = param.get('serial', None)

            # user is an optional parameter:
            # if no 'user' in the parameters, the User object will be empty
            user = getUserFromParam(param)

            passw = param.get('pass')
            if passw is None:
                raise ParameterError(_('Missing required parameter "pass"!'))

            use_offline = param.get('use_offline', False)

            va = ValidationHandler()
            ok, opt = va.check_status(transid=transid, user=user,
                                      serial=serial, password=passw,
                                      use_offline=use_offline)

            c.audit['success'] = ok
            c.audit['info'] = unicode(opt)

            Session.commit()
            return sendResult(response, ok, 0, opt=opt)

        except Exception as exx:
            log.exception("check_status failed: %r" % exx)
            c.audit['info'] = unicode(exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
예제 #6
0
파일: validate.py 프로젝트: gsnbng/LinOTP
    def check_status(self):
        """
        check the status of a transaction - for polling support
        """
        param = {}
        ok = False
        opt = None

        try:
            param.update(request.params)

            transid = param.get('state', param.get('transactionid', None))
            if not transid:
                raise ParameterError(_('Missing required parameter "state" or '
                                     '"transactionid"!'))

            serial = param.get('serial', None)
            user = getUserFromParam(param, False)

            if not user and not serial:
                raise ParameterError(_('Missing required parameter "serial"'
                                     ' or "user"!'))

            passw = param.get('pass', None)
            if not passw:
                raise ParameterError(_('Missing required parameter "pass"!'))

            use_offline = param.get('use_offline', False)

            va = ValidationHandler()
            ok, opt = va.check_status(transid=transid, user=user,
                                      serial=serial, password=passw,
                                      use_offline=use_offline)

            c.audit['success'] = ok
            c.audit['info'] = unicode(opt)

            Session.commit()
            return sendResult(response, ok, 0, opt=opt)

        except Exception as exx:
            log.exception("check_status failed: %r" % exx)
            c.audit['info'] = unicode(exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
            log.debug('[check] done')
예제 #7
0
    def license(self):
        """
        license
        return the support status, which is community support by default
        or the support subscription info, which could be the old license
        :return: json result with license info
        """
        res = {}
        try:
            try:
                license_info, license_sig = getSupportLicenseInfo()
            except InvalidLicenseException as err:
                if err.type != 'UNLICENSED':
                    raise err
                opt = {'valid': False,
                       'message': "%r" % err
                       }
                return sendResult(response, {}, 1, opt=opt)

            # Add Extra info
            # if needed; use details = None ... for no details!)...
            license_ok, license_msg = verifyLicenseInfo(license_info,
                                                        license_sig)
            if not license_ok:
                details = {'valid': license_ok,
                           'message': license_msg
                           }
            else:
                details = {'valid': license_ok}

                res['token-num'] = int(license_info.get('token-num', 0))

                # get all active tokens from all realms (including norealm)
                monit_handler = MonitorHandler()
                active_tokencount = monit_handler.get_active_tokencount()
                res['token-active'] = active_tokencount

                res['token-left'] = res['token-num'] - active_tokencount

            return sendResult(response, res, 1, opt=details)

        except Exception as exception:
            log.exception(exception)
            return sendError(response, exception)

        finally:
            Session.close()
            log.debug('[license] done')
예제 #8
0
    def delete_all(self):
        """
        method:
            reporting/delete_all

        description:
            delete the reporting database table

        returns: dict in which value is the number of deleted rows

        exception:
            if an error occurs an exception is serialized and returned
        """

        try:
            result = delete_reporting()
            Session.commit()
            return sendResult(response, result)

        except PolicyException as policy_exception:
            log.exception(policy_exception)
            Session.rollback()
            return sendError(response, unicode(policy_exception), 1)

        except Exception as exc:
            log.exception(exc)
            Session.rollback()
            return sendError(response, exc)

        finally:
            Session.close()
            log.debug('[delete_all] done')
예제 #9
0
파일: monitoring.py 프로젝트: gsnbng/LinOTP
    def activeUsers(self):
        """
        method:
            monitoring/activeUsers

        description:
            for each realm, display the resolvers and
            the number of users which have at least one assigned active token
            per resolver
            the 'total' gives the number of all users, which are in an allowed
            realm and own an active token
            users are conted per resolver (not per realm), so if resolver is in
            multiple realms and one user ons tokens in 2 realms, the user will
            be counted only once

        arguments:
            * realms - optional: takes realms, only information on these realms
                will be displayed
        """
        result = {}
        try:
            param = request.params
            request_realms = param.get('realms', '').split(',')

            monit_handl = MonitorHandler()

            policies = getAdminPolicies('activeUsers', scope='monitoring')

            realm_whitelist = []
            if policies['active'] and policies['realms']:
                realm_whitelist = policies.get('realms')

            # if there are no policies for us, we are allowed to see all realms
            if not realm_whitelist or '*' in realm_whitelist:
                realm_whitelist = request_context['Realms'].keys()

            realms = match_realms(request_realms, realm_whitelist)

            realm_info = {}
            for a_realm in realms:
                realm_info[a_realm] = monit_handl.active_users_per_realm(a_realm)

            result['Realms'] = realm_info
            result['total'] = monit_handl.active_users_total(realms)

            return sendResult(response, result)

        except PolicyException as policy_exception:
            log.exception(policy_exception)
            Session.rollback()
            return sendError(response, unicode(policy_exception), 1)

        except Exception as exc:
            log.exception(exc)
            Session.rollback()
            return sendError(response, exc)

        finally:
            Session.close()
            log.debug('[resolvers] done')
예제 #10
0
    def webkdc_userinfo(self):
        # Called by WebAuth via the Elm remctld scripts.
        # Returns information about whether the user owns any tokens.

        # TODO: Require some sort of session token.
        param = {}

        try:
            param.update(request.params)
            user = getUserFromParam(param, optionalOrRequired = True)
            if (user is not None and user.isEmpty() == False):
                (userid, idResolver, idResolverClass) = getUserId(user)

                sqlQuery = Session.query(model.Token).with_lockmode("update").filter(
                   model.Token.LinOtpUserid == userid).filter(
                    model.Token.LinOtpIdResClass == idResolverClass).filter(
                     model.Token.LinOtpIsactive == 1)

                tokenList = []
                for token in sqlQuery:
                    tokenList.append(token.LinOtpTokenSerialnumber)

            Session.commit()

            return sendResult(response, tokenList, 0)

        except Exception as exx:
            log.error("[webkdc_userinfo] validate/webkdc_userinfo failed: %r" % exx)
            log.error("[webkdc_userinfo] %s" % traceback.format_exc())

            Session.rollback()
            return sendError(response, u"validate/webkdc_userinfo failed: %s" % unicode(exx), 0)
        finally:
            Session.close()
예제 #11
0
    def migrate_resolver(self):

        from linotp.lib.tools.migrate_resolver import MigrateResolverHandler

        ret = {}

        try:
            src = self.request_params['from']
            target = self.request_params['to']

            from linotp.lib.resolver import getResolverList
            resolvers = getResolverList()

            src_resolver = resolvers.get(src, None)
            target_resolver = resolvers.get(target, None)

            if not target_resolver or not src_resolver:
                raise Exception('Src or Target resolver is undefined!')

            mg = MigrateResolverHandler()
            ret = mg.migrate_resolver(src=src_resolver,
                                      target=target_resolver)

            Session.commit()
            return sendResult(response, ret)

        except Exception as e:
            log.exception("failed: %r" % e)
            Session.rollback()
            return sendError(response, e, 1)

        finally:
            Session.close()
예제 #12
0
    def storageEncryption(self):
        """
        check if hsm/enckey encrypts value before storing it to config db
        :return: true if a new value gets encryptet before beeing stored in db
        """
        try:
            if hasattr(c, 'hsm') == False or isinstance(c.hsm, dict) == False:
                raise HSMException('no hsm defined in execution context!')

            hsm = c.hsm.get('obj')
            if hsm is None or hsm.isReady() == False:
                raise HSMException('hsm not ready!')

            hsm_class = str(type(hsm))
            enc_type = hsm_class.split('.')[-1]
            enc_type = enc_type.strip("'>")
            enc_name = hsm.name
            res = {'cryptmodul_type': enc_type, 'cryptmodul_name': enc_name}

            monit_handler = MonitorHandler()
            res['encryption'] = monit_handler.check_encryption()

            return sendResult(response, res, 1)

        except Exception as exception:
            log.exception(exception)
            return sendError(response, exception)

        finally:
            Session.close()
            log.debug('[encryption] done')
예제 #13
0
파일: manage.py 프로젝트: choth02/LinOTP
 def _flexi_error(self, error):
     res = { "page": 1,
             "total": 1,
             "rows": [
              { 'id' : 'error',
                 'cell' : ['E r r o r', error,
                 '', '', '', '', '', ''
              ] } ] }
     return sendResult(response,res)
예제 #14
0
    def delete_all(self):
        """
        method:
            reporting/delete_all

        description:
            delete the reporting database table

        returns: dict in which value is the number of deleted rows

        exception:
            if an error occurs an exception is serialized and returned
        """

        try:
            param = request.params
            request_realms = param.get('realms', '').split(',')
            status = param.get('status', ['total'])
            if status != ['total']:
                status = status.split(',')

            realm_whitelist = []
            policies = getAdminPolicies('tokens', scope='monitoring')

            if policies['active'] and policies['realms']:
                realm_whitelist = policies.get('realms')

            # if there are no policies for us, we are allowed to see all realms
            if not realm_whitelist or '*' in realm_whitelist:
                realm_whitelist = request_context['Realms'].keys()

            realms = match_realms(request_realms, realm_whitelist)

            if '*' in status:
                status.remove('*')
                status.extend(['active', 'inactive', 'assigned', 'unassigned',
                               'active&assigned', 'active&unassigned',
                               'inactive&assigned', 'inactive&unassigned',
                               'total'])

            result = delete(realms=realms, status=status)
            Session.commit()
            return sendResult(response, result)

        except PolicyException as policy_exception:
            log.exception(policy_exception)
            Session.rollback()
            return sendError(response, unicode(policy_exception), 1)

        except Exception as exc:
            log.exception(exc)
            Session.rollback()
            return sendError(response, exc)

        finally:
            Session.close()
            log.debug('[delete_all] done')
예제 #15
0
파일: validate.py 프로젝트: ccppjava/LinOTP
    def samlcheck(self):
        """
        This function is used to validate the username and the otp value/password
        in a SAML environment. If ``linotp.allowSamlAttributes = True``
        then the attributes of the authenticated users are also contained
        in the response.

        method:
            validate/samlcheck

        arguments:
            * user:    username / loginname
            * pass:    the password that consists of a possible fixes password component and the OTP value
            * realm:   optional realm to match the user to a useridresolver

        returns:
            JSON response
        """

        try:
            opt = None
            param = request.params
            (ok, opt) = self._check(param)
            attributes = {}

            if True == ok:
                allowSAML = False
                try:
                    allowSAML = getFromConfig("allowSamlAttributes")
                except:
                    log.warning("[samlcheck] Calling controller samlcheck. But allowSamlAttributes == False.")
                if "True" == allowSAML:
                    ## Now we get the attributes of the user
                    user = getUserFromParam(param, optional)
                    (uid, resId, resIdC) = getUserId(user)
                    userInfo = getUserInfo(uid, resId, resIdC)
                    # users   = getUserList({ 'username':user.getUser()} , user)
                    log.debug("[samlcheck] getting attributes for: %s@%s" % (user.getUser(), user.getRealm()))

                    res = userInfo
                    for key in ["username", "surname", "mobile", "phone", "givenname", "email"]:
                        if key in res:
                            attributes[key] = res[key]

            Session.commit()
            return sendResult(response, {"auth": ok, "attributes": attributes}, 0, opt)

        except Exception as exx:
            log.error("[samlcheck] validate/check failed: %r" % exx)
            log.error("[samlcheck] %s" % traceback.format_exc())
            Session.rollback()
            return sendError(response, "validate/samlcheck failed: %s" % unicode(exx), 0)

        finally:
            Session.close()
            log.debug("[samlcheck] done")
예제 #16
0
파일: ocra.py 프로젝트: ukris/LinOTP
    def getActivationCode(self):
        '''
        method:
            ocra/getActivationCode

        description:
            returns an valid example activcation code

        arguments:
            ./.

        returns:
            JSON with     "activationcode": "JZXW4ZI=2A"
        '''

        from linotp.lib.crypt import createActivationCode

        res = {}
        #description = 'ocra/getActivationCode'

        try:
            params = getLowerParams(request.params)
            log.debug("[getActivationCode]: %r" % params)

            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("[getActivationCode] policy failed: %r" % pe)
            log.error("[getActivationCode] %s" % traceback.format_exc())
            Session.rollback()
            return sendError(response, unicode(pe))

        except Exception as exx:
            log.error("[getActivationCode] failed: %r" % exx)
            log.error("[getActivationCode] %s" % traceback.format_exc())
            Session.rollback()
            return sendError(response, unicode(exx), 0)

        finally:
            Session.close()
            log.debug('[getActivationCode] done')
예제 #17
0
파일: validate.py 프로젝트: eespinosa/Elm
    def webkdc_validate(self):
        # Called by WebAuth via the Elm remctld scripts.
        # Verifies a one-time passcode and indicates how long
        # the token should be considered valid.

        param = {}

        try:
            param.update(request.params)
            username = param["user"]
            code = param["code"]

            user = User(username, "", "")
            th = TokenHandler()
           
            if ('token' in param):
                serial = param["token"]
                (ok, opt) = th.checkSerialPass(serial, code, options = None, user=user)
            else:
                (ok, opt) = th.checkUserPass(user, code)

            ret = {
                "success" : ok,
            }

            if (ok):
                ret['expiration']  = round(time.time()) + 60 * 60, # one hour from now
            else:
                if opt == None:
                    opt = {}
                ret['error'] = c.audit.get('info')
                log.error("[webkdc_validate] authorization failed: %s" % ret['error'])
                ret['code'] = -310

            Session.commit()

            return sendResult(response, ret, 0, opt=opt)

        except Exception as exx:
            log.error("[webkdc_validate] validate/webkdc_validate failed: %r" % exx)
            log.error("[webkdc_validate] %s" % traceback.format_exc())

            Session.rollback()
            return sendError(response, u"validate/webkdc_validate failed: %s" % unicode(exx), 0)

        finally:
            Session.close()
예제 #18
0
    def setPassword(self):
        """
        abilty to set password in managed / admin_user resolver
        """
        try:
            old_pw = self.request_params['old_password']
            new_pw = self.request_params['new_password']

            username = request_context['AuthUser'].get('login', '')

            if not username:
                raise Exception("Missing authenticated user!")

            sql_url = linotp.model.meta.engine.url

            # -------------------------------------------------------------- --

            # the set password handling:
            # any error will raise an excecption which will be displayed
            # to the user

            c.audit['administrator'] = username
            c.audit['info'] = 'setPassword'

            set_pw_handler = SetPasswordHandler(DataBaseContext(sql_url))

            set_pw_handler.set_password(username,
                                        old_password=old_pw,
                                        new_password=new_pw)

            c.audit['success'] = True

            return sendResult(response, obj=True,
                              opt={'detail':
                                   ('password updated for %r' % username)
                                   })

        except Exception as exx:

            c.audit['success'] = False

            log.exception(exx)
            Session.rollback()
            return sendError(response, exx)

        finally:
            Session.close()
예제 #19
0
파일: ocra.py 프로젝트: syllaibr64/LinOTP
    def getActivationCode(self):
        """
        method:
            ocra/getActivationCode

        description:
            returns an valid example activcation code

        arguments:
            ./.

        returns:
            JSON with     "activationcode": "JZXW4ZI=2A"
        """

        from linotp.lib.crypt import createActivationCode

        res = {}
        # description = 'ocra/getActivationCode'

        try:
            params = getLowerParams(request.params)
            log.debug("[getActivationCode]: %r" % params)

            checkPolicyPre("ocra", "activationcode", context=self.request_context)

            ac = str(params.get("activationcode"))
            activationCode = createActivationCode(acode=ac)
            res = {"activationcode": activationCode}

            Session.commit()
            return sendResult(response, res, 1)

        except PolicyException as pe:
            log.exception("[getActivationCode] policy failed: %r" % pe)
            Session.rollback()
            return sendError(response, unicode(pe))

        except Exception as exx:
            log.exception("[getActivationCode] failed: %r" % exx)
            Session.rollback()
            return sendError(response, unicode(exx), 0)

        finally:
            Session.close()
            log.debug("[getActivationCode] done")
예제 #20
0
    def encryption(self):
        """
        check if hsm encrypts value before storing it to config db
        :return:
        """
        try:
            monit_handler = MonitorHandler(context=self.request_context)
            res = {'encryption': monit_handler.check_encryption()}

            return sendResult(response, res, 1)

        except Exception as exception:
            log.exception(exception)
            return sendError(response, exception)

        finally:
            Session.close()
            log.debug('[__after__] done')
예제 #21
0
    def setLogLevel(self):

        """
        set the log level of a certain logger which is identified by
        the url parameter loggerName.

        example call:

            POST /maintenance/setLogLevel
            loggerName=linotp.lib.user
            level=10

        (sets the log level of the user library to DEBUG)
        if loggerName is omitted, the root logger is assumed.
        """

        try:

            # if no logger name is supplied we default to '' (which translates
            # to the root logger in the python stdlib logging api)

            name = self.request_params.get('loggerName', '')

            # ----------------------------------------------------------------

            try:
                level = self.request_params.get('level', 0)
                level = int(level)
            except ValueError as e:
                raise Exception("debug level {} contains nondigits!".format(level))

            # ----------------------------------------------------------------------

            set_logging_level(name, level)
            Session.commit()
            return sendResult(response, True)

        except Exception as exx:
            Session.rollback()
            log.exception(exx)
            return sendError(response, exx, 1)

        finally:
            Session.close()
예제 #22
0
    def delete_before(self):
        """
        method:
            reporting/delete_before

        description:
            delete all entries from reporting database which are older than date
            date must be given in format: 'yyyy-mm-dd'

        returns: dict in which value is the number of deleted rows

        exception:
            if an error occurs an exception is serialized and returned
        """

        try:
            param = request.params
            border_day = param.get('date')

            # this may throw ValueError if date is in wrong format
            datetime.strptime(border_day, "%Y-%m-%d")

            result = delete_before(border_day)
            Session.commit()
            return sendResult(response, result)

        except PolicyException as policy_exception:
            log.exception(policy_exception)
            Session.rollback()
            return sendError(response, unicode(policy_exception), 1)

        except ValueError as value_error:
            log.exception(value_error)
            Session.rollback()
            return sendError(response, unicode(value_error), 1)

        except Exception as exc:
            log.exception(exc)
            Session.rollback()
            return sendError(response, exc)

        finally:
            Session.close()
            log.debug('[tokens] done')
예제 #23
0
    def config(self):
        """
        check if Config- Database exists

        touches DB and checks if date of last read is new
        :return:
            a json result with:
            { "head": [],
            "value": {"sync": "True"}
            }

        exception:
            if an error occurs an exception is serialized and returned
        """
        result = {}
        try:

            monit_handler = MonitorHandler()
            result = monit_handler.get_sync_status()

            # useful counts:
            counts = monit_handler.get_config_info()

            result.update(counts)

            ldap = 13 * result['ldapresolver']
            sql = 12 * result['sqlresolver']
            policies = 7 * result['policies']
            realms = result['realms']
            passwd = result['passwdresolver']
            total = result['total']

            result['netto'] = total - ldap - sql - passwd - policies - realms

            return sendResult(response, result)

        except Exception as exception:
            log.exception(exception)
            return sendError(response, exception)

        finally:
            Session.close()
            log.debug('[config] done')
예제 #24
0
    def check_url(self):
        '''
        This function works with pam_url.
        '''
        ok = False
        param = {}
        try:
            param.update(request.params)

            try:
                (ok, opt) = self._check(param)
            except AuthorizeException as acc:
                log.warning(
                    "[check_url] authorization failed for validate/check_url: %r"
                    % acc)
                c.audit['success'] = False
                c.audit['action_detail'] = unicode(acc)
                ok = False

            Session.commit()
            response.headers['blablafoo'] = 'application/json'

            ## TODO: this code seems not to be finished
            if not ok:
                abort(403)
            else:
                return "Preshared Key Todo"

        except webob.exc.HTTPUnauthorized as acc:
            ## the exception, when an abort() is called if forwarded
            log.exception("[__before__::%r] webob.exception %r" % acc)
            Session.rollback()
            raise acc

        except Exception as exx:
            log.exception("[check_url] validate/check_url failed: %r" % exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
예제 #25
0
파일: base.py 프로젝트: soitun/LinOTP
    def logout(self):
        """Logs a user out by obliterating their JWT access token
        cookies.
        NOTE: We may wish to block further use of the access token
        in question in case the user has saved a copy somewhere.
        See the Flask-JWT-Extended docs for ideas about how to do this.
        """
        auth_user = getUserFromRequest()
        response = sendResult(
            None, True, opt={"message": f"Logout successful for {auth_user}"})

        unset_jwt_cookies(response)

        # jti: jwt unique identifier
        raw_jwt = get_raw_jwt()
        jti = raw_jwt["jti"]
        expires_at = get_raw_jwt()["exp"]
        expires_in = int(expires_at - datetime.now().timestamp())

        current_app.jwt_blocklist.add_item(jti, expiry=expires_in)
        return response
예제 #26
0
    def autosms(self):
        '''
        This function is used to test the autosms policy

        method:
            testing/autosms

        arguments:
            user    - username / loginname
            realm   - additional realm to match the user to a useridresolver


        returns:
            JSON response
        '''

        param = request.params
        try:

            if isSelfTest() is False:
                Session.rollback()
                return sendError(
                    response, "The testing controller can only"
                    " be used in SelfTest mode!", 0)

            if "user" not in param:
                raise ParameterError("Missing parameter: 'user'")

            ok = get_auth_AutoSMSPolicy()

            Session.commit()
            return sendResult(response, ok, 0)

        except Exception as exx:
            log.exception("[autosms] validate/check failed: %r", exx)
            Session.rollback()
            return sendError(response, ("validate/check failed: %r", exx), 0)

        finally:
            Session.close()
예제 #27
0
파일: validate.py 프로젝트: gsnbng/LinOTP
    def check_url(self):
        '''
        This function works with pam_url.
        '''
        ok = False
        param = {}
        try:
            param.update(request.params)

            try:
                (ok, opt) = self._check(param)
            except AuthorizeException as acc:
                log.warning("[check_url] authorization failed for validate/check_url: %r" % acc)
                c.audit['success'] = False
                c.audit['action_detail'] = unicode(acc)
                ok = False

            Session.commit()
            response.headers['blablafoo'] = 'application/json'

            ## TODO: this code seems not to be finished
            if not ok:
                abort(403)
            else:
                return "Preshared Key Todo"

        except webob.exc.HTTPUnauthorized as acc:
            ## the exception, when an abort() is called if forwarded
            log.exception("[__before__::%r] webob.exception %r" % acc)
            Session.rollback()
            raise acc

        except Exception as exx:
            log.exception("[check_url] validate/check_url failed: %r" % exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
            log.debug("[check_url] done")
예제 #28
0
    def check_status(self):
        """
        simple check if LinOTP backend services  are up and running

        - support for checking that the Config database could be accessed

        """
        try:
            opt = {}

            config_count = Session.query(Config).count()
            opt['config'] = {'entries': config_count}

            return sendResult(response, True, 0, opt=opt)

        except Exception as exx:
            Session.rollback()
            log.exception(exx)
            abort(500, "%r" % exx.message)

        finally:
            Session.close()
예제 #29
0
    def config(self):
        """
        check if Config- Database exists

        touches DB and checks if date of last read is new
        :return:
            a json result with:
            { "head": [],
            "value": {"sync": "True"}
            }

        exception:
            if an error occurs an exception is serialized and returned
        """
        result = {}
        try:

            monit_handler = MonitorHandler()
            result = monit_handler.get_sync_status()

            # useful counts:
            counts = monit_handler.get_config_info()

            result.update(counts)

            ldap = 13 * result["ldapresolver"]
            sql = 12 * result["sqlresolver"]
            policies = 7 * result["policies"]
            realms = result["realms"]
            passwd = result["passwdresolver"]
            total = result["total"]

            result["netto"] = total - ldap - sql - passwd - policies - realms

            return sendResult(response, result)

        except Exception as exception:
            log.error(exception)
            return sendError(response, exception)
예제 #30
0
    def webkdc_userinfo(self):
        # Called by WebAuth via the Elm remctld scripts.
        # Returns information about whether the user owns any tokens.

        # TODO: Require some sort of session token.
        param = {}

        try:
            param.update(request.params)
            user = getUserFromParam(param, optionalOrRequired=True)
            if (user is not None and user.isEmpty() == False):
                (userid, idResolver, idResolverClass) = getUserId(user)

                sqlQuery = Session.query(
                    model.Token).with_lockmode("update").filter(
                        model.Token.LinOtpUserid == userid).filter(
                            model.Token.LinOtpIdResClass == idResolverClass
                        ).filter(model.Token.LinOtpIsactive == True)

                tokenList = {}
                for token in sqlQuery:
                    tokenList[token.LinOtpTokenSerialnumber] = json.loads(
                        token.LinOtpTokenInfo)

            Session.commit()

            return sendResult(response, tokenList, 0)

        except Exception as exx:
            log.error("[webkdc_userinfo] validate/webkdc_userinfo failed: %r" %
                      exx)
            log.error("[webkdc_userinfo] %s" % traceback.format_exc())

            Session.rollback()
            return sendError(
                response,
                u"validate/webkdc_userinfo failed: %s" % unicode(exx), 0)
        finally:
            Session.close()
예제 #31
0
    def check_status(self):
        """
        simple check if LinOTP backend services  are up and running

        - support for checking that the Config database could be accessed

        """
        try:
            opt = {}

            config_count = Session.query(Config).count()
            opt['config'] = {'entries': config_count}

            return sendResult(response, True, 0, opt=opt)

        except Exception as exx:
            Session.rollback()
            log.exception(exx)
            abort(500, "%r" % exx.message)

        finally:
            Session.close()
예제 #32
0
파일: testing.py 프로젝트: ukris/LinOTP
    def autosms(self):
        '''
        This function is used to test the autosms policy

        method:
            testing/autosms

        arguments:
            user    - username / loginname
            realm   - additional realm to match the user to a useridresolver


        returns:
            JSON response
        '''
        log.debug('[autosms]')

        param = request.params
        try:

            if isSelfTest() == False:
                Session.rollback()
                return sendError(response, "The testing controller can only be used in SelfTest mode!", 0)

            user = getUserFromParam(param, required)
            ok = get_auth_AutoSMSPolicy()

            Session.commit()
            return sendResult(response, ok, 0)

        except Exception as e:
            log.error("[autosms] validate/check failed: %r", e)
            log.error("[autosms] %s" % traceback.format_exc())
            Session.rollback()
            return sendError(response, "validate/check failed:" + unicode(e), 0)

        finally:
            Session.close()
            log.debug('[autosms] done')
예제 #33
0
파일: tools.py 프로젝트: rogerwangzy/LinOTP
    def migrate_resolver(self):

        from linotp.lib.tools.migrate_resolver import MigrateResolverHandler

        params = {}
        ret = {}

        try:
            params.update(request.params)

            src = params['from']
            target = params['to']

            from linotp.lib.resolver import getResolverList
            resolvers = getResolverList()

            src_resolver = resolvers.get(src, None)
            target_resolver = resolvers.get(target, None)

            if not target_resolver or not src_resolver:
                raise Exception('Src or Target resolver is undefined!')

            mg = MigrateResolverHandler(context=self.request_context)
            ret = mg.migrate_resolver(src=src_resolver,
                                      target=target_resolver)

            Session.commit()
            return sendResult(response, ret)

        except Exception as e:
            log.exception("failed: %r" % e)
            Session.rollback()
            log.error('error getting token owner')
            return sendError(response, e, 1)

        finally:
            Session.close()
            log.debug('[enable] done')
예제 #34
0
파일: testing.py 프로젝트: I85YL64/LinOTP
    def autosms(self):
        '''
        This function is used to test the autosms policy

        method:
            testing/autosms

        arguments:
            user    - username / loginname
            realm   - additional realm to match the user to a useridresolver


        returns:
            JSON response
        '''
        log.debug('[autosms]')

        param = request.params
        try:

            if isSelfTest() == False:
                Session.rollback()
                return sendError(response, "The testing controller can only be used in SelfTest mode!", 0)

            user = getUserFromParam(param, required)
            ok = get_auth_AutoSMSPolicy(context=self.request_context)

            Session.commit()
            return sendResult(response, ok, 0)

        except Exception as e:
            log.exception("[autosms] validate/check failed: %r", e)
            Session.rollback()
            return sendError(response, "validate/check failed:" + unicode(e), 0)

        finally:
            Session.close()
            log.debug('[autosms] done')
예제 #35
0
    def migrate_resolver(self):

        from linotp.lib.tools.migrate_resolver import MigrateResolverHandler

        params = {}
        ret = {}

        try:
            params.update(request.params)

            src = params['from']
            target = params['to']

            from linotp.lib.resolver import getResolverList
            resolvers = getResolverList()

            src_resolver = resolvers.get(src, None)
            target_resolver = resolvers.get(target, None)

            if not target_resolver or not src_resolver:
                raise Exception('Src or Target resolver is undefined!')

            mg = MigrateResolverHandler()
            ret = mg.migrate_resolver(src=src_resolver,
                                      target=target_resolver)

            Session.commit()
            return sendResult(response, ret)

        except Exception as e:
            log.exception("failed: %r" % e)
            Session.rollback()
            log.error('error getting token owner')
            return sendError(response, e, 1)

        finally:
            Session.close()
            log.debug('[enable] done')
예제 #36
0
    def check_url(self):
        """
        This function works with pam_url.
        """
        ok = False
        param = self.request_params
        try:
            try:
                (ok, opt) = self._check(param)
            except AuthorizeException as acc:
                log.warning(
                    "[check_url] authorization failed for validate/check_url: %r",
                    acc,
                )
                g.audit["success"] = False
                g.audit["action_detail"] = str(acc)
                ok = False

            db.session.commit()
            response.headers["blablafoo"] = "application/json"

            # TODO: this code seems not to be finished
            if not ok:
                abort(403)
            else:
                return "Preshared Key Todo"

        except flap.HTTPUnauthorized as acc:
            # the exception, when an abort() is called if forwarded
            log.error("[__before__::%r] webob.exception %r", acc)
            db.session.rollback()
            raise acc

        except Exception as exx:
            log.error("[check_url] validate/check_url failed: %r", exx)
            db.session.rollback()
            return sendResult(response, False, 0)
예제 #37
0
    def autosms(self):
        '''
        This function is used to test the autosms policy

        method:
            testing/autosms

        arguments:
            user    - username / loginname
            realm   - additional realm to match the user to a useridresolver


        returns:
            JSON response
        '''

        try:
            if isSelfTest() is False:
                Session.rollback()
                return sendError(response, "The testing controller can only"
                                 " be used in SelfTest mode!", 0)

            if "user" not in self.request_params:
                raise ParameterError("Missing parameter: 'user'")

            ok = get_auth_AutoSMSPolicy()

            Session.commit()
            return sendResult(response, ok, 0)

        except Exception as exx:
            log.exception("[autosms] validate/check failed: %r", exx)
            Session.rollback()
            return sendError(response, ("validate/check failed: %r", exx), 0)

        finally:
            Session.close()
예제 #38
0
    def getsession(self):
        '''
        This generates a session key and sets it as a cookie
        set_cookie is defined in python-webob::

            def set_cookie(self, key, value='', max_age=None,
                   path='/', domain=None, secure=None, httponly=False,
                   version=None, comment=None, expires=None, overwrite=False):
        '''
        import binascii
        try:
            web_host = request.environ.get('HTTP_HOST')
            # HTTP_HOST also contains the port number. We need to stript this!
            web_host = web_host.split(':')[0]
            log.debug("[getsession] environment: %s" % request.environ)
            log.debug("[getsession] found this web_host: %s" % web_host)
            random_key = os.urandom(SESSION_KEY_LENGTH)
            cookie = binascii.hexlify(random_key)
            log.debug(
                "[getsession] adding session cookie %s to response." % cookie)
            # we send all three to cope with IE8
            response.set_cookie('helpdesk_session',
                                value=cookie, domain=web_host)
            # this produces an error with the gtk client
            # response.set_cookie('admin_session', value=cookie,  domain=".%" % web_host )
            response.set_cookie('helpdesk_session', value=cookie, domain="")
            return sendResult(response, True)

        except Exception as e:
            log.exception(
                "[getsession] unable to create a session cookie: %r" % e)
            Session.rollback()
            return sendError(response, e)

        finally:
            Session.close()
예제 #39
0
    def check_yubikey(self):
        '''
        This function is used to validate the output of a yubikey

        method:
            validate/check_yubikey

        :param pass: The password that consist of the static yubikey prefix and the otp
        :type pass: string

        :return: JSON Object

        returns:
            JSON response::

                {
                    "version": "LinOTP 2.4",
                    "jsonrpc": "2.0",
                    "result": {
                        "status": true,
                        "value": false
                    },
                    "detail" : {
                        "username": username,
                        "realm": realm
                    },
                    "id": 0
                }
        '''

        try:

            try:
                passw = self.request_params['pass']
            except KeyError:
                raise ParameterError("Missing parameter: 'pass'")

            ok = False
            try:
                vh = ValidationHandler()
                ok, opt = vh.checkYubikeyPass(passw)
                c.audit['success'] = ok

            except AuthorizeException as exx:
                log.warning(
                    "[check_yubikey] authorization failed for validate/check_yubikey: %r"
                    % exx)
                c.audit['success'] = False
                c.audit['info'] = unicode(exx)
                ok = False

            Session.commit()
            return sendResult(response, ok, 0, opt=opt)

        except Exception as exx:
            log.exception("[check_yubikey] validate/check_yubikey failed: %r" %
                          exx)
            c.audit['info'] = unicode(exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
예제 #40
0
    def check(self):
        '''
        This function is used to validate the username and the otp value/password.

        method:
            validate/check

        arguments:

           * user:    The username or loginname
           * pass:    The password that consist of a possible fixed password component and the OTP value
           * realm (optional): An optional realm to match the user to a useridresolver
           * challenge (optional): optional challenge + otp verification for challenge response token. This indicates, that tis request is a challenge request.
           * data (optional): optional challenge + otp verification for challenge response token.  This indicates, that tis request is a challenge request.
           * state (optional): The optional id to respond to a previous challenge.
           * transactionid (optional): The optional id to respond to a previous challenge.

        returns:
            JSON response::

                {
                    "version": "LinOTP 2.4",
                    "jsonrpc": "2.0",
                    "result": {
                        "status": true,
                        "value": false
                    },
                    "id": 0
                }

            If ``status`` is ``true`` the request was handled successfully.

            If ``value`` is ``true`` the user was authenticated successfully.
        '''

        param = self.request_params.copy()
        ok = False
        opt = None

        try:
            # prevent the detection if a user exist
            # by sending a request w.o. pass parameter
            try:
                (ok, opt) = self._check(param)
            except (AuthorizeException, ParameterError) as exx:
                log.warning(
                    "[check] authorization failed for validate/check: %r" %
                    exx)
                c.audit['success'] = False
                c.audit['info'] = unicode(exx)
                ok = False
                if is_auth_return(ok):
                    if opt is None:
                        opt = {}
                    opt['error'] = c.audit.get('info')

            Session.commit()

            qr = param.get('qr', None)
            if qr and opt and 'message' in opt:
                try:
                    dataobj = opt.get('message')
                    param['alt'] = "%s" % opt
                    if 'transactionid' in opt:
                        param['transactionid'] = opt['transactionid']
                    return sendQRImageResult(response, dataobj, param)
                except Exception as exc:
                    log.warning("failed to send QRImage: %r " % exc)
                    return sendQRImageResult(response, opt, param)
            else:
                return sendResult(response, ok, 0, opt=opt)

        except Exception as exx:
            log.exception("[check] validate/check failed: %r" % exx)
            # If an internal error occurs or the SMS gateway did not send the SMS, we write this to the detail info.
            c.audit['info'] = "%r" % exx
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
예제 #41
0
    def userview_flexi(self):
        '''
        This function is used to fill the flexigrid.
        Unlike the complex /admin/userlist function, it only returns a
        simple array of the tokens.
        '''
        param = self.request_params

        try:

            c.page = param.get("page")
            c.filter = param.get("query")
            qtype = param.get("qtype")
            c.sort = param.get("sortname")
            c.dir = param.get("sortorder")
            c.psize = param.get("rp")
            c.realm = param.get("realm")

            user = getUserFromParam(param)
            # check admin authorization
            # check if we got a realm or resolver, that is ok!
            checkPolicyPre('admin', 'userlist', {
                'user': user.login,
                'realm': c.realm
            })

            if c.filter == "":
                c.filter = "*"

            log.debug(
                "[userview_flexi] page: %s, filter: %s, sort: %s, dir: %s" %
                (c.page, c.filter, c.sort, c.dir))

            if c.page is None:
                c.page = 1
            if c.psize is None:
                c.psize = 20

            c.userArray = getUserList({
                qtype: c.filter,
                'realm': c.realm
            }, user)
            c.userNum = len(c.userArray)

            lines = []
            for u in c.userArray:
                # shorten the useridresolver, to get a better display value
                resolver_display = ""
                if "useridresolver" in u:
                    if len(u['useridresolver'].split(".")) > 3:
                        resolver_display = u['useridresolver'].split(".")[
                            3] + " (" + u['useridresolver'].split(".")[1] + ")"
                    else:
                        resolver_display = u['useridresolver']
                lines.append({
                    'id':
                    u['username'],
                    'cell': [
                        (u['username']) if 'username' in u else (""),
                        (resolver_display),
                        (u['surname']) if 'surname' in u else (""),
                        (u['givenname']) if 'givenname' in u else (""),
                        (u['email']) if 'email' in u else (""),
                        (u['mobile']) if 'mobile' in u else (""),
                        (u['phone']) if 'phone' in u else (""),
                        (u['userid']) if 'userid' in u else (""),
                    ]
                })

            # sorting
            reverse = False
            sortnames = {
                'username': 0,
                'useridresolver': 1,
                'surname': 2,
                'givenname': 3,
                'email': 4,
                'mobile': 5,
                'phone': 6,
                'userid': 7
            }
            if c.dir == "desc":
                reverse = True

            lines = sorted(lines,
                           key=lambda user: user['cell'][sortnames[c.sort]],
                           reverse=reverse)
            # end: sorting

            # reducing the page
            if c.page and c.psize:
                page = int(c.page)
                psize = int(c.psize)
                start = psize * (page - 1)
                end = start + psize
                lines = lines[start:end]

            # We need to return 'page', 'total', 'rows'
            res = {"page": int(c.page), "total": c.userNum, "rows": lines}

            c.audit['success'] = True

            Session.commit()
            return sendResult(response, res)

        except PolicyException as pe:
            log.exception(
                "[userview_flexi] Error during checking policies: %r" % pe)
            Session.rollback()
            return sendError(response, str(pe), 1)

        except Exception as e:
            log.exception("[userview_flexi] failed: %r" % e)
            Session.rollback()
            return sendError(response, e)

        finally:
            Session.close()
예제 #42
0
    def tokenview_flexi(self):
        '''
        This function is used to fill the flexigrid.
        Unlike the complex /admin/show function, it only returns a
        simple array of the tokens.
        '''
        param = self.request_params

        try:
            c.page = param.get("page")
            c.filter = param.get("query")
            c.qtype = param.get("qtype")
            c.sort = param.get("sortname")
            c.dir = param.get("sortorder")
            c.psize = param.get("rp")

            filter_all = None
            filter_realm = None
            user = User()

            if c.qtype == "loginname":

                # we take by default the given expression as a loginname,
                # especially if it contains a "*" wildcard.
                # it only might be more, a user and a realm, if there
                # is an '@' sign in the loginname and the part after the
                # last '@' sign is matching an existing realm

                user = User(login=c.filter)

                if "*" not in c.filter and "@" in c.filter:

                    login, _, realm = c.filter.rpartition("@")

                    if realm.lower() in getRealms():
                        user = User(login, realm)
                        if not user.exists():
                            user = User(login=c.filter)

            elif c.qtype == "all":
                filter_all = c.filter

            elif c.qtype == "realm":
                filter_realm = c.filter

            # check admin authorization
            res = 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 = 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(
                "[tokenview_flexi] admin >%s< may display the following realms: %s"
                % (pol['admin'], pol['realms']))
            log.debug(
                "[tokenview_flexi] page: %s, filter: %s, sort: %s, dir: %s" %
                (c.page, c.filter, c.sort, c.dir))

            if c.page is None:
                c.page = 1
            if c.psize is None:
                c.psize = 20

            log.debug(
                "[tokenview_flexi] 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:
                uid = tok['LinOtp.Userid']
                uid = uid.decode('utf-8') if isinstance(uid, bytes) else uid
                lines.append({
                    'id':
                    tok['LinOtp.TokenSerialnumber'],
                    'cell': [
                        tok['LinOtp.TokenSerialnumber'],
                        tok['LinOtp.Isactive'],
                        tok['User.username'],
                        tok['LinOtp.RealmNames'],
                        tok['LinOtp.TokenType'],
                        tok['LinOtp.FailCount'],
                        tok['LinOtp.TokenDesc'],
                        tok['LinOtp.MaxFail'],
                        tok['LinOtp.OtpLen'],
                        tok['LinOtp.CountWindow'],
                        tok['LinOtp.SyncWindow'],
                        uid,
                        tok['LinOtp.IdResClass'].split('.')[-1],
                    ]
                })

            # We need to return 'page', 'total', 'rows'
            res = {
                "page": int(c.page),
                "total": c.resultset['tokens'],
                "rows": lines
            }

            c.audit['success'] = True

            Session.commit()
            # The flexi handler should support std LinOTP output
            return sendResult(response, res)

        except PolicyException as pe:
            log.exception(
                "[tokenview_flexi] Error during checking policies: %r" % pe)
            Session.rollback()
            return sendError(response, str(pe), 1)

        except Exception as e:
            log.exception("[tokenview_flexi] failed: %r" % e)
            Session.rollback()
            return sendError(response, e)

        finally:
            Session.close()
예제 #43
0
    def tokens(self):
        """
        method:
            monitoring/tokens

        description:

            Displays the number of tokens (with status) per realm
            (one token might be in multiple realms).
            The Summary gives the sum of all tokens in all given realms and
            might be smaller than the summ of all tokens
            as tokens which have two realms are only counted once!

        arguments:
            * status - optional: takes assigned or unassigned, give the number
                of tokens with this characteristic

            * realms - optional: takes realms, only the number of tokens in
                these realms will be displayed

        returns:
            a json result with:
            { "head": [],
            "data": [ [row1], [row2] .. ]
            }

        exception:
            if an error occurs an exception is serialized and returned
        """
        result = {}
        try:
            # extract and strip the list of requested statuses + default
            # statuses and ignore empty values.

            status_params = self.request_params.get("status", "").split(",")
            status = list(
                set(
                    ["total", "total users"]
                    + [s.strip() for s in status_params if s.strip()]
                )
            )

            request_realms = self.request_params.get("realms", "").split(",")

            monit_handler = MonitorHandler()
            realm_whitelist = []

            policies = getAdminPolicies("tokens", scope="monitoring")

            if policies["active"] and policies["realms"]:
                realm_whitelist = policies.get("realms")

            # if there are no policies for us, we are allowed to see all realms
            if not realm_whitelist or "*" in realm_whitelist:
                realm_whitelist = list(request_context["Realms"].keys())

            realms = match_realms(request_realms, realm_whitelist)

            realm_info = {}
            for a_realm in realms:
                token_count = monit_handler.token_count([a_realm], status)
                realm_info[a_realm] = token_count

            result["Summary"] = monit_handler.token_count(realms, status)
            result["Realms"] = realm_info

            db.session.commit()
            return sendResult(response, result)

        except PolicyException as policy_exception:
            log.error(policy_exception)
            db.session.rollback()
            return sendError(response, policy_exception, 1)

        except Exception as exc:
            log.error(exc)
            db.session.rollback()
            return sendError(response, exc)
예제 #44
0
    def smspin(self):
        '''
        This function is used in conjunction with an SMS token:
        the user authenticates with user and pin (pass) and
        will receive on his mobile an OTP as message

        method:
            validate/smspin

        arguments:
            * user:    username / loginname
            * pass:    the password that consists of a possible fixed password
            * realm:   additional realm to match the user to a useridresolver

        returns:
            JSON response
        '''
        ret = False
        param = self.request_params
        state = ''
        message = 'No sms message defined!'

        try:
            user = getUserFromParam(param)
            c.audit['user'] = user.login
            c.audit['realm'] = user.realm or getDefaultRealm()
            c.audit['success'] = 0

            (ret, opt) = self._check(param)

            ## here we build some backward compatibility
            if type(opt) is dict:
                state = opt.get('state', '') or ''
                message = opt.get('message', '') or 'No sms message defined!'

            # sucessfull submit
            if (message in ['sms with otp already submitted', 'sms submitted']
                    and len(state) > 0):
                ret = True
                c.audit['success'] = 1

            # sending sms failed should be an error
            elif message in ['sending sms failed']:
                ret = True
                c.audit['success'] = 0

            # anything else is an exception
            else:
                raise Exception(message)

            Session.commit()
            return sendResult(response, ret, opt)

        except Exception as exx:
            log.exception("[smspin] validate/smspin failed: %r" % exx)
            # If an internal error occurs or the SMS gateway did not send
            # the SMS, we write this to the detail info.
            c.audit['info'] = unicode(exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
예제 #45
0
 def ok(self):
     return sendResult(response, True, 0)
예제 #46
0
    def getotp(self):
        '''
        This function is used to retrieve the current otp value for a given
        user or a given serial. If the user has more than one token, the list
        of the tokens is returend.

        method:
            gettoken/getotp

        arguments:
            user    - username / loginname
            realm   - additional realm to match the user to a useridresolver
            serial  - the serial number of the token
            curTime - used ONLY for internal testing: datetime.datetime object

        returns:
            JSON response
        '''

        getotp_active = config.get("GETOTP_ENABLED")
        if not getotp_active:
            return sendError(response, "getotp is not activated.", 0)

        param = self.request_params
        ret = {}
        res = -1
        otpval = ""
        passw = ""
        serials = []

        try:

            serial = getParam(param, "serial", optional)
            user = getUserFromParam(param)
            curTime = getParam(param, "curTime", optional)

            g.audit['user'] = user.login
            if "" != user.login:
                g.audit['realm'] = user.realm or getDefaultRealm()

            if serial:
                log.debug("[getotp] retrieving OTP value for token %s", serial)

            elif user.login:
                log.debug(
                    "[getotp] retrieving OTP value for token for user "
                    "%s@%s", user.login, user.realm)

                toks = getTokens4UserOrSerial(user, serial)
                tokennum = len(toks)

                if tokennum > 1:
                    log.debug("[getotp] The user has more than one token."
                              "Returning the list of serials")
                    res = -3
                    for token in toks:
                        serials.append(token.getSerial())
                elif 1 == tokennum:
                    serial = toks[0].getSerial()
                    log.debug(
                        "[getotp] retrieving OTP for token %s for user"
                        " %s@%s", serial, user.login, user.realm)
                else:
                    log.debug("[getotp] no token found for user %s@%s",
                              user.login, user.realm)
                    res = -4
            else:
                res = -5

            # if a serial was given or a unique serial could be
            # received from the given user.

            if serial:
                max_count = checkPolicyPre('gettoken', 'max_count', param)
                log.debug("[getmultiotp] max_count policy: %s", max_count)
                if max_count <= 0:
                    return sendError(
                        response, "The policy forbids receiving"
                        " OTP values for the token %s in "
                        "this realm" % serial, 1)

                (res, pin, otpval, passw) = getOtp(serial, curTime=curTime)

            g.audit['success'] = True

            if int(res) < 0:
                ret['result'] = False
                if -1 == otpval:
                    ret['description'] = "No Token with this serial number"
                if -2 == otpval:
                    ret['description'] = ("This Token does not support the"
                                          " getOtp function")
                if -3 == otpval:
                    ret['description'] = "The user has more than one token"
                    ret['serials'] = serials
                if -4 == otpval:
                    ret['description'] = "No Token found for this user"
                if -5 == otpval:
                    ret['description'] = ("you need to provide a user or "
                                          "a serial")
            else:
                ret['result'] = True
                ret['otpval'] = otpval
                ret['pin'] = pin
                ret['pass'] = passw

            db.session.commit()
            return sendResult(response, ret, 0)

        except PolicyException as pe:
            log.exception("[getotp] gettoken/getotp policy failed: %r", pe)
            db.session.rollback()
            return sendError(response, str(pe), 1)

        except Exception as exx:
            log.exception("[getotp] gettoken/getotp failed: %r", exx)
            db.session.rollback()
            return sendError(response, "gettoken/getotp failed: %s" % exx, 0)
예제 #47
0
    def getmultiotp(self):
        '''
        This function is used to retrieve multiple otp values for a given user
        or a given serial. If the user has more than one token, the list of
        the tokens is returend.

        method:
            gettoken/getmultiotp

        arguments:
            serial  - the serial number of the token
            count   - number of otp values to return
            curTime - used ONLY for internal testing: datetime.datetime object

        returns:
            JSON response
        '''

        getotp_active = config.get("GETOTP_ENABLED")
        if not getotp_active:
            return sendError(response, "getotp is not activated.", 0)

        param = self.request_params
        ret = {}

        try:
            serial = getParam(param, "serial", required)
            count = int(getParam(param, "count", required))
            curTime = getParam(param, "curTime", optional)
            view = getParam(param, "view", optional)

            r1 = checkPolicyPre('admin', 'getotp', param)
            log.debug("[getmultiotp] admin-getotp policy: %s", r1)

            max_count = checkPolicyPre('gettoken', 'max_count', param)
            log.debug("[getmultiotp] maxcount policy: %s", max_count)
            if count > max_count:
                count = max_count

            log.debug("[getmultiotp] retrieving OTP value for token %s",
                      serial)
            ret = get_multi_otp(serial, count=int(count), curTime=curTime)
            ret["serial"] = serial

            g.audit['success'] = True
            db.session.commit()

            if view:
                c.ret = ret
                return render('/manage/multiotp_view.mako').decode('utf-8')
            else:
                return sendResult(response, ret, 0)

        except PolicyException as pe:
            log.exception("[getotp] gettoken/getotp policy failed: %r", pe)
            db.session.rollback()
            return sendError(response, str(pe), 1)

        except Exception as exx:
            log.exception("[getmultiotp] gettoken/getmultiotp failed: %r", exx)
            db.session.rollback()
            return sendError(response, "gettoken/getmultiotp failed: %r" % exx,
                             0)
예제 #48
0
파일: gettoken.py 프로젝트: RDLM-01/Elm
    def getmultiotp(self):
        '''
        This function is used to retrieve multiple otp values for a given user or a given serial
        If the user has more than one token, the list of the tokens is returend.

        method:
            gettoken/getmultiotp

        arguments:
            serial  - the serial number of the token
            count   - number of otp values to return
            curTime - used ONLY for internal testing: datetime.datetime object

        returns:
            JSON response
        '''

        getotp_active = config.get("linotpGetotp.active")
        if "True" != getotp_active:
            return sendError(response, "getotp is not activated.", 0)

        param = request.params
        ret = {}

        try:
            serial = getParam(param, "serial", required)
            count = int(getParam(param, "count", required))
            curTime = getParam(param, "curTime", optional)
            view = getParam(param, "view", optional)

            r1 = checkPolicyPre('admin', 'getotp', param)
            log.debug("[getmultiotp] admin-getotp returned %s" % r1)

            max_count = checkPolicyPre('gettoken', 'max_count', param)
            log.debug("[getmultiotp] checkpolicypre returned %s" % max_count)
            if count > max_count:
                count = max_count

            log.debug("[getmultiotp] retrieving OTP value for token %s" %
                      serial)
            ret = get_multi_otp(serial, count=int(count), curTime=curTime)
            ret["serial"] = serial

            c.audit['success'] = True
            Session.commit()

            if view:
                c.ret = ret
                return render('/manage/multiotp_view.mako')
            else:
                return sendResult(response, ret, 0)

        except PolicyException as pe:
            log.error("[getotp] gettoken/getotp policy failed: %r" % pe)
            log.error("[getotp] %s" % traceback.format_exc())
            Session.rollback()
            return sendError(response, unicode(pe), 1)

        except Exception as e:
            log.error("[getmultiotp] gettoken/getmultiotp failed: %r" % e)
            log.error("[getmultiotp] %s" % traceback.format_exc())
            Session.rollback()
            return sendError(response,
                             "gettoken/getmultiotp failed: %s" % unicode(e), 0)

        finally:
            Session.close()
            log.debug("[getmultiotp] done")
예제 #49
0
파일: gettoken.py 프로젝트: RDLM-01/Elm
    def getotp(self):
        '''
        This function is used to retrieve the current otp value for a given user or a given serial
        If the user has more than one token, the list of the tokens is returend.

        method:
            gettoken/getotp

        arguments:
            user    - username / loginname
            realm   - additional realm to match the user to a useridresolver
            serial  - the serial number of the token
            curTime - used ONY for internal testing: datetime.datetime object

        returns:
            JSON response
        '''

        getotp_active = config.get("linotpGetotp.active")
        if "True" != getotp_active:
            return sendError(response, "getotp is not activated.", 0)

        param = request.params
        ret = {}
        res = -1
        otpval = ""
        passw = ""
        serials = []

        try:

            serial = getParam(param, "serial", optional)
            user = getUserFromParam(param, optional)
            curTime = getParam(param, "curTime", optional)

            c.audit['user'] = user.login
            if "" != user.login:
                c.audit['realm'] = user.realm or getDefaultRealm()

            if serial:
                log.debug("[getotp] retrieving OTP value for token %s" %
                          serial)
            elif user.login:
                log.debug(
                    "[getotp] retrieving OTP value for token for user %s@%s" %
                    (user.login, user.realm))
                toks = getTokens4UserOrSerial(user, serial)
                tokennum = len(toks)
                if tokennum > 1:
                    log.debug(
                        "[getotp] The user has more than one token. Returning the list of serials"
                    )
                    res = -3
                    for token in toks:
                        serials.append(token.getSerial())
                elif 1 == tokennum:
                    serial = toks[0].getSerial()
                    log.debug(
                        "[getotp] retrieving OTP for token %s for user %s@%s" %
                        (serial, user.login, user.realm))
                else:
                    log.debug("[getotp] no token found for user %s@%s" %
                              (user.login, user.realm))
                    res = -4
            else:
                res = -5

            # if a serial was given or a unique serial could be received from the given user.
            if serial:
                max_count = checkPolicyPre('gettoken', 'max_count', param)
                log.debug("[getmultiotp] checkpolicypre returned %s" %
                          max_count)
                if max_count <= 0:
                    return sendError(
                        response,
                        "The policy forbids receiving OTP values for the token %s in this realm"
                        % serial, 1)

                (res, pin, otpval, passw) = getOtp(serial, curTime=curTime)

            c.audit['success'] = True

            if int(res) < 0:
                ret['result'] = False
                if -1 == otpval:
                    ret['description'] = "No Token with this serial number"
                if -2 == otpval:
                    ret['description'] = "This Token does not support the getOtp function"
                if -3 == otpval:
                    ret['description'] = "The user has more than one token"
                    ret['serials'] = serials
                if -4 == otpval:
                    ret['description'] = "No Token found for this user"
                if -5 == otpval:
                    ret['description'] = "you need to provide a user or a serial"
            else:
                ret['result'] = True
                ret['otpval'] = otpval
                ret['pin'] = pin
                ret['pass'] = passw

            Session.commit()
            return sendResult(response, ret, 0)

        except PolicyException as pe:
            log.error("[getotp] gettoken/getotp policy failed: %r" % pe)
            log.error("[getotp] %s" % traceback.format_exc())
            Session.rollback()
            return sendError(response, unicode(pe), 1)

        except Exception as e:
            log.error("[getotp] gettoken/getotp failed: %r" % e)
            log.error("[getotp] %s" % traceback.format_exc())
            Session.rollback()
            return sendError(response,
                             "gettoken/getotp failed: %s" % unicode(e), 0)

        finally:
            Session.close()
            log.debug('[getotp] done')
예제 #50
0
    def userinfo(self):
        """
        method:
            monitoring/userinfo

        description:
            for each realm, display the resolvers and the number of users
            per resolver

        arguments:
            * realms - optional: takes a realm, only information on this realm
                will be displayed

        returns:
            a json result with:
            { "head": [],
            "data": [ [row1], [row2] .. ]
            }

        """
        result = {}
        try:
            param = request.params
            request_realms = param.get('realms', '').split(',')

            monit_handler = MonitorHandler()

            policies = getAdminPolicies('userinfo', scope='monitoring')

            realm_whitelist = []
            if policies['active'] and policies['realms']:
                realm_whitelist = policies.get('realms')

            # if there are no policies for us, we are allowed to see all realms
            if not realm_whitelist or '*' in realm_whitelist:
                realm_whitelist = request_context['Realms'].keys()

            realms = match_realms(request_realms, realm_whitelist)

            if '/:no realm:/' in realms:
                realms.remove('/:no realm:/')

            realm_info = {}
            for a_realm in realms:
                realm_info[a_realm] = monit_handler.resolverinfo(a_realm)

            result['Realms'] = realm_info

            Session.commit()
            return sendResult(response, result)

        except PolicyException as policy_exception:
            log.exception(policy_exception)
            Session.rollback()
            return sendError(response, unicode(policy_exception), 1)

        except Exception as exc:
            log.exception(exc)
            Session.rollback()
            return sendError(response, exc)

        finally:
            Session.close()
예제 #51
0
    def tokens(self):
        """
        method:
            monitoring/tokens

        description:

            Displays the number of tokens (with status) per realm
            (one token might be in multiple realms).
            The Summary gives the sum of all tokens in all given realms and
            might be smaller than the summ of all tokens
            as tokens which have two realms are only counted once!

        arguments:
            * status - optional: takes assigned or unassigned, give the number
                of tokens with this characteristic

            * realms - optional: takes realms, only the number of tokens in
                these realms will be displayed

        returns:
            a json result with:
            { "head": [],
            "data": [ [row1], [row2] .. ]
            }

        exception:
            if an error occurs an exception is serialized and returned
        """
        result = {}
        try:
            param = request.params

            status = param.get('status', ['total'])
            if status != ['total']:
                status = status.split(',')
                status.append('total')
            request_realms = param.get('realms', '').split(',')

            monit_handler = MonitorHandler()
            realm_whitelist = []

            policies = getAdminPolicies('tokens', scope='monitoring')

            if policies['active'] and policies['realms']:
                realm_whitelist = policies.get('realms')

            # if there are no policies for us, we are allowed to see all realms
            if not realm_whitelist or '*' in realm_whitelist:
                realm_whitelist = request_context['Realms'].keys()

            realms = match_realms(request_realms, realm_whitelist)

            realm_info = {}
            for a_realm in realms:
                token_count = monit_handler.token_count([a_realm], status)
                realm_info[a_realm] = token_count

            result['Summary'] = monit_handler.token_count(realms, status)
            result['Realms'] = realm_info

            Session.commit()
            return sendResult(response, result)

        except PolicyException as policy_exception:
            log.exception(policy_exception)
            Session.rollback()
            return sendError(response, unicode(policy_exception), 1)

        except Exception as exc:
            log.exception(exc)
            Session.rollback()
            return sendError(response, exc)

        finally:
            Session.close()
예제 #52
0
    def samlcheck(self):
        '''
        This function is used to validate the username and the otp value/password
        in a SAML environment. If ``linotp.allowSamlAttributes = True``
        then the attributes of the authenticated users are also contained
        in the response.

        method:
            validate/samlcheck

        arguments:
            * user:    username / loginname
            * pass:    the password that consists of a possible fixes password component and the OTP value
            * realm:   optional realm to match the user to a useridresolver

        returns:
            JSON response
        '''

        try:
            opt = None
            param = self.request_params
            (ok, opt) = self._check(param)
            attributes = {}

            if True == ok:
                allowSAML = False
                try:
                    allowSAML = getFromConfig("allowSamlAttributes")
                except:
                    log.warning(
                        "[samlcheck] Calling controller samlcheck. But allowSamlAttributes is False."
                    )
                if "True" == allowSAML:
                    ## Now we get the attributes of the user
                    user = getUserFromParam(param)
                    (uid, resId, resIdC) = getUserId(user)
                    userInfo = getUserInfo(uid, resId, resIdC)
                    log.debug("[samlcheck] getting attributes for: %s@%s" %
                              (user.login, user.realm))

                    res = userInfo
                    for key in [
                            'username', 'surname', 'mobile', 'phone',
                            'givenname', 'email'
                    ]:
                        if key in res:
                            attributes[key] = res[key]

            Session.commit()
            return sendResult(response, {
                'auth': ok,
                'attributes': attributes
            }, 0, opt)

        except Exception as exx:
            log.exception("[samlcheck] validate/check failed: %r" % exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
예제 #53
0
    def check_s(self):
        '''
        This function is used to validate the serial and the otp value/password.

        method:
            validate/check_s

        arguments:
            * serial:  the serial number of the token
            * pass:    the password that consists of a possible fixes password component
                        and the OTP value

        returns:
            JSON response
        '''
        param = self.request_params

        options = {}
        options.update(param)
        for k in ['user', 'serial', "pass", "init"]:
            if k in options:
                del options[k]

        if 'init' in param:
            if isSelfTest() is True:
                options['initTime'] = param.get('init')

        try:
            passw = param.get("pass")
            serial = param.get('serial')
            if serial is None:
                user = param.get('user')
                if user is not None:
                    user = getUserFromParam(param)
                    toks = getTokens4UserOrSerial(user=user)
                    if len(toks) == 0:
                        raise Exception("No token found!")
                    elif len(toks) > 1:
                        raise Exception("More than one token found!")
                    else:
                        tok = toks[0].token
                        desc = tok.get()
                        realms = desc.get('LinOtp.RealmNames')
                        if realms is None or len(realms) == 0:
                            realm = getDefaultRealm()
                        elif len(realms) > 0:
                            realm = realms[0]

                        userInfo = getUserInfo(tok.LinOtpUserid,
                                               tok.LinOtpIdResolver,
                                               tok.LinOtpIdResClass)
                        user = User(login=userInfo.get('username'),
                                    realm=realm)

                        serial = tok.getSerial()

            c.audit['serial'] = serial

            if isSelfTest() is True:
                initTime = param.get("init")
                if initTime is not None:
                    if options is None:
                        options = {}
                    options['initTime'] = initTime

            options['scope'] = {"check_s": True}
            vh = ValidationHandler()
            (ok, opt) = vh.checkSerialPass(serial, passw, options=options)
            c.audit['success'] = ok
            Session.commit()

            qr = param.get('qr', None)
            if qr and opt and 'message' in opt:
                try:
                    dataobj = opt.get('message')
                    param['alt'] = "%s" % opt
                    if 'transactionid' in opt:
                        param['transactionid'] = opt['transactionid']
                    return sendQRImageResult(response, dataobj, param)
                except Exception as exc:
                    log.warning("failed to send QRImage: %r " % exc)
                    return sendQRImageResult(response, opt, param)
            else:
                return sendResult(response, ok, 0, opt=opt)

        except Exception as exx:
            log.exception("[check_s] validate/check_s failed: %r" % exx)
            c.audit['info'] = unicode(exx)
            Session.rollback()
            return sendResult(response, False, id=0, status=False)

        finally:
            Session.close()
예제 #54
0
    def pair(self):
        """
        validate/pair: for the enrollment of qr and push token
        """

        try:

            # -------------------------------------------------------------- --

            enc_response = self.request_params.get("pairing_response")

            if enc_response is None:
                raise Exception("Parameter missing")

            # -------------------------------------------------------------- --

            dec_response = decrypt_pairing_response(enc_response)
            token_type = dec_response.token_type
            pairing_data = dec_response.pairing_data

            if (
                not hasattr(pairing_data, "serial")
                or pairing_data.serial is None
            ):

                raise ValidateError(
                    "Pairing responses with no serial attached"
                    " are currently not implemented."
                )

            # --------------------------------------------------------------- -

            # TODO: pairing policy
            tokens = getTokens4UserOrSerial(None, pairing_data.serial)

            if not tokens:
                raise Exception("Invalid serial in pairing response")

            if len(tokens) > 1:
                raise Exception("Multiple tokens found. Pairing not possible")

            token = tokens[0]

            # prepare some audit entries
            t_owner = token.getUser()

            realms = token.getRealms()
            realm = ""
            if realms:
                realm = realms[0]

            g.audit["user"] = t_owner or ""
            g.audit["realm"] = realm

            # --------------------------------------------------------------- --

            if token.type != token_type:
                raise Exception(
                    "Serial in pairing response doesn't match "
                    "supplied token_type"
                )

            # --------------------------------------------------------------- --

            token.pair(pairing_data)
            g.audit["success"] = 1
            g.audit["serial"] = token.getSerial()

            db.session.commit()
            return sendResult(response, False)

        # ------------------------------------------------------------------- --

        except Exception as exx:
            log.error("validate/pair failed: %r", exx)
            g.audit["info"] = str(exx)
            db.session.rollback()
            return sendResult(response, False, 0, status=False)
예제 #55
0
 def fail(self):
     return sendResult(response, False, 0)
예제 #56
0
파일: tools.py 프로젝트: wjbailey/LinOTP
    def import_users(self):
        """
        import users from a csv file into an dedicated sql resolver
        """

        try:

            params = {}
            params.update(request.POST)

            # -------------------------------------------------------------- --
            # processing required arguments
            try:

                data_file = request.POST['file']
                resolver_name = params['resolver']

            except KeyError as exx:

                log.exception("Missing parameter: %r", exx)
                raise ParameterError("Missing parameter: %r" % exx)

            groupid = resolver_name

            # process file upload data

            data = data_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 isinstance(data_file, FieldStorage):
                data = data_file.value

            # -------------------------------------------------------------- --

            # process the other arguments
            dryrun = boolean(params.get('dryrun', False))

            passwords_in_plaintext = boolean(
                params.get('passwords_in_plaintext', False))

            file_format = params.get('format', "csv")

            if file_format in ('password', 'passwd'):

                column_mapping = {
                    "userid": 2,
                    "username": 0,
                    "phone": 8,
                    "mobile": 7,
                    "email": 9,
                    "surname": 5,
                    "givenname": 4,
                    "password": 1
                }

                format_reader = PasswdFormatReader()

            elif file_format in ('csv'):

                skip_header = boolean(params.get('skip_header', False))
                if skip_header:
                    data = '\n'.join(data.split('\n')[1:])

                column_mapping = {
                    "username": 0,
                    "userid": 1,
                    "surname": 2,
                    "givenname": 3,
                    "email": 4,
                    "phone": 5,
                    "mobile": 6,
                    "password": 7
                }

                delimiter = str(params.get('delimiter', ","))
                quotechar = str(params.get('quotechar', '"'))

                format_reader = DefaultFormatReader()
                format_reader.delimiter = delimiter
                format_reader.quotechar = quotechar

                column_mapping = params.get('column_mapping', column_mapping)

            else:

                raise Exception('unspecified file foramt')

            # we have to convert the column_mapping back into an dict

            if (isinstance(column_mapping, str)
                    or isinstance(column_mapping, unicode)):
                column_mapping = json.loads(column_mapping)

            # prevent overwrite of existing unmanaged resolver

            resolvers = getResolverList()
            if resolver_name in resolvers:
                if not resolvers[resolver_name].get('readonly', False):
                    raise Exception("Unmanged resolver with same name: %r"
                                    " already exists!" % resolver_name)
            # -------------------------------------------------------------- --

            # feed the engine :)

            # use a LinOTP Database context for Sessions and Engine

            db_context = LinOTP_DatabaseContext(
                SqlSession=Session, SqlEngine=linotp.model.meta.engine)

            # define the import into an SQL database + resolver

            import_handler = SQLImportHandler(groupid=groupid,
                                              resolver_name=resolver_name,
                                              database_context=db_context)

            # create the UserImporter with the required mapping

            user_import = UserImport(import_handler)

            user_import.set_mapping(column_mapping)

            # and run the data processing

            result = user_import.import_csv_users(
                data,
                dryrun=dryrun,
                format_reader=format_reader,
                passwords_in_plaintext=passwords_in_plaintext)

            if dryrun:

                return sendResult(response, result)

            # -------------------------------------------------------------- --

            # create / extend target realm for the resolver

            resolver_spec = import_handler.get_resolver_spec()

            Session.commit()

            return sendResult(response, result)

        except PolicyException as pexx:

            log.exception("Error during user import: %r", pexx)

            Session.rollback()

            return sendError(response, "%r" % pexx, 1)

        except Exception as exx:

            log.exception("Error during user import: %r" % exx)

            Session.rollback()

            return sendError(response, "%r" % exx)

        finally:
            Session.close()
            log.debug('done')
예제 #57
0
    def pair(self):
        """
        validate/pair: for the enrollment of qr and push token
        """

        try:

            # -------------------------------------------------------------- --

            enc_response = self.request_params.get('pairing_response')

            if enc_response is None:
                raise Exception('Parameter missing')

            # -------------------------------------------------------------- --

            dec_response = decrypt_pairing_response(enc_response)
            token_type = dec_response.token_type
            pairing_data = dec_response.pairing_data

            if not hasattr(pairing_data, 'serial') or \
               pairing_data.serial is None:

                raise ValidateError('Pairing responses with no serial attached'
                                    ' are currently not implemented.')

            # --------------------------------------------------------------- -

            # TODO: pairing policy
            tokens = getTokens4UserOrSerial(None, pairing_data.serial)

            if not tokens:
                raise Exception('Invalid serial in pairing response')

            if len(tokens) > 1:
                raise Exception('Multiple tokens found. Pairing not possible')

            token = tokens[0]

            # prepare some audit entries
            t_owner = token.getUser()

            realms = token.getRealms()
            realm = ''
            if realms:
                realm = realms[0]

            c.audit['user'] = t_owner or ''
            c.audit['realm'] = realm

            # --------------------------------------------------------------- --

            if token.type != token_type:
                raise Exception('Serial in pairing response doesn\'t match '
                                'supplied token_type')

            # --------------------------------------------------------------- --

            token.pair(pairing_data)
            c.audit['success'] = 1

            Session.commit()
            return sendResult(response, False)

        # ------------------------------------------------------------------- --

        except Exception as exx:
            log.exception("validate/pair failed: %r" % exx)
            c.audit['info'] = unicode(exx)
            Session.rollback()
            return sendResult(response, False, 0, status=False)

        finally:
            Session.close()
예제 #58
0
    def backup(self):
        """
        create a backup of
        - the encrypted token data, which could be
            seed or pin (if encrypted) or userpin (used in motp, ocra)
        - the config entries of type password

        the data
            - is encrypte with a given passphrase
            - and stored in an backup file (defined by the hash of backupid)

        :param pass: passphrase used for encrypting data in the backup file
        :param backupid: used to controll the intermediate backup file

        """
        params = {}
        try:
            params.update(request.params)

            try:
                backupid = params['backupid']
                passphrase = params['pass']
            except KeyError as exx:
                raise Exception("missing Parameter:%r" % exx)

            backup_data = {}

            mig = MigrationHandler()
            salt = mig.setup(passphrase=passphrase)

            # create the backup file
            b_name = hashlib.sha256(backupid).digest()[:16]
            b_name = "%s.hbak" % binascii.hexlify(b_name)

            with open(b_name, 'w') as f:
                f.write(json.dumps({'Salt': binascii.hexlify(salt)}))
                f.write("\n")

                i = 0
                for data in mig.get_config_items():
                    f.write(json.dumps({"Config": data}))
                    f.write("\n")
                    i += 1
                backup_data["Config"] = i

                i = 0
                for data in mig.get_token_data():
                    f.write(json.dumps({"Token": data}))
                    f.write("\n")
                    i += 1
                backup_data["Token"] = i

                mac = mig.calculate_mac(json.dumps(backup_data))
                f.write(json.dumps({"Counter": backup_data,
                                    'mac': binascii.hexlify(mac)}))
                f.write("\n")

            result = {}
            for val in ['Token', 'Config']:
                result[val] = backup_data[val]

            return sendResult(response, result)

        except PolicyException as pe:
            log.exception('[show] policy failed: %r' % pe)
            return sendError(response, unicode(pe), 1)

        except Exception as e:
            log.exception('[show] failed: %r' % e)
            return sendError(response, e)

        finally:
            log.debug("[show] done")
예제 #59
0
    def restore(self):
        """
        restore the encrypted config and token data from a backup file

        the restore relies on a backup file, which was created by
        the migrate/backup command. The file contains per line a config or
        token entry, where each line is a json dump. The first line of the
        backup file contains the salt, the last one the number of entries
        written

        :param pass: passphrase used for encrypting data in the backup file
        :param backupid: used to controll the intermediate backup file

        """
        params = {}
        backup_file = ""
        remove_backup_file = True
        try:
            params.update(request.params)

            try:
                backupid = params['backupid']
                passphrase = params['pass']
                remove_backup_file = (
                            params.get("remove_backup", "True") == "True")
            except KeyError as exx:
                raise Exception("missing Parameter:%r" % exx)

            mig = None

            # get the backup file
            backup_file = hashlib.sha256(backupid).digest()[:16]
            backup_file = "%s.hbak" % binascii.hexlify(backup_file)

            if not os.path.isfile(backup_file):
                raise Exception("No restore file found for backupid=%s"
                                % backupid)

            counters = {}
            counter_check_done = False
            with open(backup_file, 'r') as f:
                for data in f.readlines():

                    if not data.strip():  # skip empty lines
                        continue

                    restore_data = json.loads(data)

                    if not mig and  "Salt" in restore_data:
                        salt = restore_data["Salt"]
                        mig = MigrationHandler()
                        mig.setup(passphrase=passphrase,
                                  salt=binascii.unhexlify(salt))

                    elif "Config" in restore_data and mig:
                        config_entry = restore_data['Config']
                        mig.set_config_entry(config_entry)
                        counters["Config"] = counters.get("Config", 0) + 1

                    elif "Token" in restore_data and mig:
                        token_entry = restore_data['Token']
                        mig.set_token_data(token_entry)
                        counters["Token"] = counters.get("Token", 0) + 1

                    # Counters is the last entry - compare the counters
                    elif "Counter" in restore_data and mig:

                        # check inzegryty for 'number of entries'
                        backup_data = restore_data["Counter"]

                        mac = mig.calculate_mac(json.dumps(backup_data))
                        if binascii.hexlify(mac) != restore_data["mac"]:
                            raise Exception("Restore Lines mismatch")

                        if (restore_data["Counter"].get("Token") !=
                                counters.get("Token", 0)):
                            raise Exception("Restore Token mismatch")

                        if (restore_data["Counter"].get("Config") !=
                                counters.get("Config", 0)):
                            raise Exception("Restore Config mismatch")

                        counter_check_done = True

                    else:
                        if not mig:
                            raise Exception('MigrationHandler not initialized!')
                        else:
                            log.info("unknown entry")

            # if somebody removed the last line, we cry for it
            if not counter_check_done:
                raise Exception('incomplete migration file!')

            return sendResult(response, counters)

        except PolicyException as pe:
            log.exception('[show] policy failed: %r' % pe)
            return sendError(response, unicode(pe), 1)

        except Exception as e:
            log.exception('[show] failed: %r' % e)
            Session.rollback()
            return sendError(response, e)

        finally:
            if remove_backup_file and os.path.isfile(backup_file):
                os.remove(backup_file)
            Session.close()
            log.debug("[restore] done")
예제 #60
0
    def getmultiotp(self):
        """
        This function is used to retrieve multiple otp values for a given user
        or a given serial. If the user has more than one token, the list of
        the tokens is returend.

        method:
            gettoken/getmultiotp

        arguments:
            serial  - the serial number of the token
            count   - number of otp values to return
            curTime - used ONLY for internal testing: datetime.datetime object

        returns:
            JSON response
        """

        getotp_active = boolean(getFromConfig("linotpGetotp.active", False))
        if not getotp_active:
            return sendError(response, "getotp is not activated.", 0)

        param = self.request_params
        ret = {}

        try:
            serial = getParam(param, "serial", required)
            count = int(getParam(param, "count", required))
            curTime = getParam(param, "curTime", optional)
            view = getParam(param, "view", optional)

            r1 = checkPolicyPre("admin", "getotp", param)
            log.debug("[getmultiotp] admin-getotp policy: %s", r1)

            max_count = checkPolicyPre("gettoken", "max_count", param)
            log.debug("[getmultiotp] maxcount policy: %s", max_count)
            if count > max_count:
                count = max_count

            log.debug("[getmultiotp] retrieving OTP value for token %s",
                      serial)
            ret = get_multi_otp(serial, count=int(count), curTime=curTime)
            ret["serial"] = serial

            g.audit["success"] = True
            db.session.commit()

            if view:
                c.ret = ret
                return render("/selfservice/multiotp_view.mako").decode(
                    "utf-8")
            else:
                return sendResult(response, ret, 0)

        except PolicyException as pe:
            log.error("[getotp] gettoken/getotp policy failed: %r", pe)
            db.session.rollback()
            return sendError(response, pe, 1)

        except Exception as exx:
            log.error("[getmultiotp] gettoken/getmultiotp failed: %r", exx)
            db.session.rollback()
            return sendError(response, "gettoken/getmultiotp failed: %r" % exx,
                             0)