def test_url_protocol_id(self, mocked_get_secret_key): """ PUSHTOKEN: Test url protocol id customization """ public_key, secret_key = crypto_sign_keypair() mocked_get_secret_key.return_value = secret_key user_public_key = base64.b64encode(public_key) fake = FakeTokenModel() token = PushTokenClass(fake) token.addToTokenInfo('partition', 0) token.addToTokenInfo('user_token_id', 123) token.addToTokenInfo('user_dsa_public_key', user_public_key) with nested(patch.dict(config), request_context_safety()): if 'mobile_app_protocol_id' in config: del config['mobile_app_protocol_id'] request_context['hsm'] = fake_hsm_wrapper # if no mobile_app_protocol_id is set, it should default # to lseqr message = 'here are the 2,750 quit you asked for. can i move' + \ 'to OT I level now? - tom' url, _ = token.create_challenge_url(transaction_id='1234567890', content_type=0, message=message, callback_url='foo') self.assertTrue(url.startswith('lseqr://')) # ------------------------------------------------------------------ -- fake = FakeTokenModel() token = PushTokenClass(fake) token.addToTokenInfo('partition', 0) token.addToTokenInfo('user_token_id', 123) token.addToTokenInfo('user_dsa_public_key', user_public_key) with nested(patch.dict(config, {'mobile_app_protocol_id': 'yolo'}), request_context_safety()): request_context['hsm'] = fake_hsm_wrapper message = 'here are the 2,750 quit you asked for. can i move' + \ 'to OT I level now? - tom' url, _ = token.create_challenge_url(transaction_id='1234567890', content_type=0, message=message, callback_url='foo') self.assertTrue(url.startswith('yolo://'))
def test_url_protocol_id(self, mocked_get_secret_key): """ QRToken unittest: Test url protocol id customization """ mocked_get_secret_key.return_value = 'X' * 64 user_public_key = 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=' fake = FakeTokenModel() token = QrTokenClass(fake) token.addToTokenInfo('user_token_id', 1234) token.addToTokenInfo('user_public_key', user_public_key) with nested(patch.dict(config), request_context_safety()): if 'mobile_app_protocol_id' in config: del config['mobile_app_protocol_id'] request_context['hsm'] = fake_hsm_wrapper # if no mobile_app_protocol_id is set, it should default # to lseqr message = 'here are the 2,750 quit you asked for. can i move' + \ 'to OT I level now? - tom' url, _ = token.create_challenge_url(transaction_id='1234567890', content_type=0, message=message, callback_url='foo', callback_sms_number='+491234') self.assertTrue(url.startswith('lseqr://')) # -------------------------------------------------------------------- - fake = FakeTokenModel() token = QrTokenClass(fake) token.addToTokenInfo('user_token_id', 1234) token.addToTokenInfo('user_public_key', user_public_key) with nested(patch.dict(config, {'mobile_app_protocol_id': 'yolo'}), request_context_safety()): request_context['hsm'] = fake_hsm_wrapper message = 'here are the 2,750 quit you asked for. can i move' + \ 'to OT I level now? - tom' url, _ = token.create_challenge_url(transaction_id='1234567890', content_type=0, message=message, callback_url='foo', callback_sms_number='+491234') self.assertTrue(url.startswith('yolo://'))
def setCurrentLicense(self, old_lic, old_sig): with request_context_safety(): context['translate'] = lambda x: x if old_lic is None and old_sig is None: removeSupportLicenseInfo() else: setSupportLicenseInfo(old_lic, old_sig)
def getCurrentLicense(self): # Test current license... with request_context_safety(): context['translate'] = lambda x: x lic, sig = getSupportLicenseInfo() isSupportLicenseValid(lic_dict=lic, lic_sign=sig, raiseException=True) return lic, sig
def __call__(self, environ, start_response): '''Invoke the Controller''' # WSGIController.__call__ dispatches to the Controller method # the request is routed to. This routing information is # available in environ['pylons.routes_dict'] # we add a unique request id to the request enviroment # so we can trace individual requests in the logging environ['REQUEST_ID'] = str(uuid4()) environ['REQUEST_START_TIMESTAMP'] = datetime.now() with request_context_safety(): try: self._parse_request_params(request) except UnicodeDecodeError as exx: # we supress Exception here as it will be handled in the # controller which will return corresponding response log.warning('Failed to access request parameters: %r' % exx) self.create_context(request, environ) try: try: user_desc = getUserFromRequest(request) self.base_auth_user = user_desc.get('login', '') except UnicodeDecodeError as exx: # we supress Exception here as it will be handled in the # controller which will return corresponding response log.warning('Failed to identify user due to %r' % exx) ret = WSGIController.__call__(self, environ, start_response) log.debug("Request reply: %r", ret) finally: meta.Session.remove() # free the lock on the scurityPovider if any if self.sep: self.sep.dropSecurityModule() closeResolvers() # hint for the garbage collector to make the dishes data_objects = [ "resolvers_loaded", "resolver_clazzes", "linotpConfig", "audit", "hsm" ] for data_obj in data_objects: if hasattr(c, data_obj): data = getattr(c, data_obj) del data log_request_timedelta(log) return ret
def test_license(self): old_lic = None old_sig = None try: old_lic, old_sig = self.getCurrentLicense() except InvalidLicenseException as exx: if (exx.message != "Support not available, your product is " "unlicensed"): raise exx try: # Load the license file... licfile = config.get('monitoringTests.licfile', '') if not licfile: self.skipTest('Path to test license file is not configured, ' 'check your configuration (test.ini)!') with request_context_safety(): context['translate'] = lambda x: x lic_dict, lic_sig = readLicenseInfo(licfile) self.installLicense(licfile) self.create_token(serial='0031') self.create_token(serial='0032', user='******') self.create_token(serial='0033', realm='mydefrealm') self.create_token(serial='0034', realm='myotherrealm') self.create_token(serial='0035', realm='myotherrealm', active=False) self.create_token(serial='0036', realm='myotherrealm', user='******', active=False) response = self.make_authenticated_request(controller='monitoring', action='license', params={}) resp = json.loads(response.body) value = resp.get('result').get('value') self.assertEqual(value.get('token-num'), int(lic_dict.get('token-num')), response) token_left = int(lic_dict.get('token-num')) - 4 self.assertEqual(value.get('token-left'), token_left, response) finally: # restore previous license... if old_lic and old_sig: self.setCurrentLicense(old_lic, old_sig) return
def authenticate(self, environ, identity): log.info("[authenticate] entering repoze authenticate function.") # log.debug( identity ) username = None realm = None options = {} realmbox = "False" authenticate = True if isSelfTest(): authenticate = False try: if isSelfTest(): if ('login' not in identity and 'repoze.who.plugins.auth_tkt.userid' in identity): u = identity.get('repoze.who.plugins.auth_tkt.userid') identity['login'] = u identity['password'] = u username = identity['login'] realm = identity['realm'] password = identity['password'] options.update(identity) realmbox = options.get("realmbox", "False") except KeyError as e: log.exception("[authenticate] Keyerror in identity: %r." % e) return None # convert string to boolean realm_mbox = False if realmbox.lower() == 'true': realm_mbox = True # check username/realm, password with request_context_safety(): linotp_config = getLinotpConfig() request_context['Config'] = linotp_config user = get_authenticated_user(username, realm, password, realm_box=realm_mbox, authenticate=authenticate, options=options) if not user: return None authUser = "******" % (user.login, user.realm) return authUser
def __call__(self, environ, start_response): '''Invoke the Controller''' # WSGIController.__call__ dispatches to the Controller method # the request is routed to. This routing information is # available in environ['pylons.routes_dict'] path = "" with request_context_safety(): self.create_context(request) try: if environ: path = environ.get("PATH_INFO", "") or "" try: user_desc = getUserFromRequest(request) self.base_auth_user = user_desc.get('login', '') except UnicodeDecodeError as exx: # we supress Exception here as it will be handled in the # controller which will return corresponding response log.info('Failed to identify user due to %r' % exx) log.debug("request %r" % path) ret = WSGIController.__call__(self, environ, start_response) log.debug("reply %r" % ret) finally: meta.Session.remove() # free the lock on the scurityPovider if any if self.sep: self.sep.dropSecurityModule() closeResolvers() # hint for the garbage collector to make the dishes data_objects = [ "resolvers_loaded", "resolver_types", "resolver_clazzes", "linotpConfig", "audit", "hsm" ] for data_obj in data_objects: if hasattr(c, data_obj): data = getattr(c, data_obj) del data log.debug("request %r done!" % path) return ret
def __call__(self, environ, start_response): '''Invoke the Controller''' # WSGIController.__call__ dispatches to the Controller method # the request is routed to. This routing information is # available in environ['pylons.routes_dict'] path = "" with request_context_safety(): self.create_context(request) try: if environ: path = environ.get("PATH_INFO", "") or "" try: user_desc = getUserFromRequest(request) self.base_auth_user = user_desc.get('login', '') except UnicodeDecodeError as exx: # we supress Exception here as it will be handled in the # controller which will return corresponding response log.info('Failed to identify user due to %r' % exx) log.debug("request %r" % path) ret = WSGIController.__call__(self, environ, start_response) log.debug("reply %r" % ret) finally: meta.Session.remove() # free the lock on the scurityPovider if any if self.sep: self.sep.dropSecurityModule() closeResolvers() # hint for the garbage collector to make the dishes data_objects = ["resolvers_loaded", "resolver_types", "resolver_clazzes", "linotpConfig", "audit", "hsm"] for data_obj in data_objects: if hasattr(c, data_obj): data = getattr(c, data_obj) del data log.debug("request %r done!" % path) return ret
def checkCurrentLicense(self): """ :return: 1 if license is available -1 if license is invalid 0 if license is not available """ try: # Test current license... with request_context_safety(): context['translate'] = lambda x: x getSupportLicenseInfo() return 1 except InvalidLicenseException as err: if err.type != 'UNLICENSED': # support license is invalid return -1 else: # support license not available return 0
def installLicense(self, licfile): with request_context_safety(): context['translate'] = lambda x: x new_lic, new_sig = readLicenseInfo(licfile) setSupportLicenseInfo(new_lic, new_sig) return
def authenticate(self, environ, identity): log.debug("Authentication through repoze.") username = None realm = None options = {} realmbox = "False" authenticate = True if isSelfTest(): authenticate = False try: if isSelfTest(): if ('login' not in identity and 'repoze.who.plugins.auth_tkt.userid' in identity): u = identity.get('repoze.who.plugins.auth_tkt.userid') identity['login'] = u identity['password'] = u username = identity['login'] realm = identity['realm'] password = identity['password'] options.update(identity) realmbox = options.get("realmbox", "False") except KeyError as e: log.exception("Keyerror in repoze identity: %r." % e) return None # convert string to boolean realm_mbox = False if realmbox.lower() == 'true': realm_mbox = True # check username/realm, password with request_context_safety(): linotp_config = getLinotpConfig() request_context['Config'] = linotp_config # add the cache manager to the context glo = getGlobalObject() cache_manager = glo.cache_manager request_context['CacheManager'] = cache_manager # and also add the hsm - enables us to do otp validation :-) sep = glo.security_provider hsm = sep.getSecurityModule() request_context['hsm'] = hsm # initialize the base context # - copied for the dumb repoze middleware cache_dir = config.get("app_conf", {}).get("cache_dir", None) setupResolvers(config=linotp_config, cache_dir=cache_dir) resolver_context = initResolvers() request_context.update(resolver_context) # prepare the request local user cache if 'UserLookup' not in request_context: request_context['UserLookup'] = {} user = get_authenticated_user(username, realm, password, realm_box=realm_mbox, authenticate=authenticate, options=options) if not user: return None authUser = "******" % (user.login, user.realm) return authUser
def __init__(self, *args, **kw): """ base controller constructor :param *args: generic argument array :param **kw: generic argument dict :return: None """ self.sep = None self.set_language(request.headers) self.base_auth_user = '' self.parent = super(WSGIController, self) self.parent.__init__(*args, **kw) # make the OpenID SQL Instance globally available openid_sql = config.get('openid_sql', None) if openid_sql is None: try: openid_storage = SQLStorage() config['openid_sql'] = openid_storage except Exception as exx: config['openid_sql'] = exx log.error("Failed to configure openid_sql: %r" % exx) first_run = False app_setup_done = config.get('app_setup_done', False) if app_setup_done is False: try: setup_app(config) config['app_setup_done'] = True first_run = True except Exception as exx: config['app_setup_done'] = False log.error("Failed to serve request: %r" % exx) raise exx # set the decryption device before loading linotp config, # so it contains the decrypted values as well glo = getGlobalObject() self.sep = glo.security_provider try: hsm = self.sep.getSecurityModule() self.hsm = hsm c.hsm = hsm except Exception as exx: log.exception('failed to assign hsm device: %r' % exx) raise exx l_config = initLinotpConfig() # initialize the elliptic curve secret + public key for the qr token linotpQrTokenSecretKey = l_config.get('QrTokenSecretKey', False) if not linotpQrTokenSecretKey: init_qrtoken_secret_key(l_config) resolver_setup_done = config.get('resolver_setup_done', False) if resolver_setup_done is False: try: cache_dir = config.get("app_conf", {}).get("cache_dir", None) setupResolvers(config=l_config, cache_dir=cache_dir) config['resolver_setup_done'] = True except Exception as exx: config['resolver_setup_done'] = False log.error("Failed to setup resolver: %r" % exx) raise exx # TODO: verify merge dropped # initResolvers() # if we are in the setup cycle, we check for the linotpLicenseFile if first_run: if "linotpLicenseFile" in config and 'license' not in l_config: license_str = '' filename = config.get("linotpLicenseFile", '') try: with open(filename) as f: license_str = f.read() except IOError: log.error("linotpLicenseFile: %s" % filename) if not license_str: log.error("empty license file: %s" % filename) else: with request_context_safety(): request_context['translate'] = translate import linotp.lib.support res, msg = linotp.lib.support.setSupportLicense(license_str) if res is False: log.error("failed to load license: %s: %s" % (license_str, msg)) else: log.info("license successfully loaded") return
def sendResultIterator(obj, id=1, opt=None, rp=None, page=None, request_context_copy=None): ''' sendResultIterator - return an json result document in a streamed mode which requires a request context to be avaliable :param obj: iterator of generator object like dict, string or list :param id: id value, for future versions :param opt: optional parameter, which allows to provide more detail :param rp: results per page :param page: number of page :return: generator of response data (yield) ''' if request_context_copy is None: request_context_copy = {} # establish the request context within the pylons middleware with request_context_safety(): for key, value in request_context_copy.items(): request_context[key] = value api_version = get_api_version() linotp_version = get_version() res = { "jsonrpc": api_version, "result": { "status": True, "value": "[DATA]", }, "version": linotp_version, "id": id } err = { "jsonrpc": api_version, "result": { "status": False, "error": {}, }, "version": linotp_version, "id": id } start_at = 0 stop_at = 0 if page: if not rp: rp = 16 try: start_at = int(page) * int(rp) stop_at = start_at + int(rp) except ValueError as exx: err['result']['error'] = { "code": 9876, "message": "%r" % exx, } log.exception( "failed to convert paging request parameters: %r" % exx) yield json.dumps(err) # finally we signal end of error result raise StopIteration() typ = "%s" % type(obj) if 'generator' not in typ and 'iterator' not in typ: raise Exception('no iterator method for object %r' % obj) res = { "jsonrpc": api_version, "result": { "status": True, "value": "[DATA]", }, "version": linotp_version, "id": id } if page: res['result']['page'] = int(page) if opt is not None and len(opt) > 0: res["detail"] = opt surrounding = json.dumps(res) prefix, postfix = surrounding.split('"[DATA]"') # first return the opening yield prefix + " [" sep = "" counter = 0 for next_one in obj: counter = counter + 1 # are we running in paging mode? if page: if counter >= start_at and counter < stop_at: res = "%s%s\n" % (sep, next_one) sep = ',' yield res if counter >= stop_at: # stop iterating if we reached the last one of the page break else: # no paging - no limit res = "%s%s\n" % (sep, next_one) sep = ',' yield res # we add the amount of queried objects total = '"queried" : %d' % counter postfix = ', %s %s' % (total, postfix) # last return the closing yield "] " + postfix
def authenticate(self, environ, identity): log.info("[authenticate] entering repoze authenticate function.") # log.debug( identity ) username = None realm = None options = {} realmbox = "False" authenticate = True if isSelfTest(): authenticate = False try: if isSelfTest(): if ('login' not in identity and 'repoze.who.plugins.auth_tkt.userid' in identity): u = identity.get('repoze.who.plugins.auth_tkt.userid') identity['login'] = u identity['password'] = u username = identity['login'] realm = identity['realm'] password = identity['password'] options.update(identity) realmbox = options.get("realmbox", "False") except KeyError as e: log.exception("[authenticate] Keyerror in identity: %r." % e) return None # convert string to boolean realm_mbox = False if realmbox.lower() == 'true': realm_mbox = True # check username/realm, password with request_context_safety(): linotp_config = getLinotpConfig() request_context['Config'] = linotp_config # add the cache manager to the context glo = getGlobalObject() cache_manager = glo.cache_manager request_context['CacheManager'] = cache_manager # and also add the hsm - enables us to do otp validation :-) sep = glo.security_provider hsm = sep.getSecurityModule() request_context['hsm'] = hsm resolver_context = initResolvers() request_context.update(resolver_context) user = get_authenticated_user(username, realm, password, realm_box=realm_mbox, authenticate=authenticate, options=options) if not user: return None authUser = "******" % (user.login, user.realm) return authUser
def __init__(self, *args, **kw): """ base controller constructor :param *args: generic argument array :param **kw: generic argument dict :return: None """ self.sep = None self.set_language(request.headers) self.base_auth_user = '' self.parent = super(WSGIController, self) self.parent.__init__(*args, **kw) # make the OpenID SQL Instance globally available openid_sql = config.get('openid_sql', None) if openid_sql is None: try: openid_storage = SQLStorage() config['openid_sql'] = openid_storage except Exception as exx: config['openid_sql'] = exx log.error("Failed to configure openid_sql: %r" % exx) first_run = False app_setup_done = config.get('app_setup_done', False) if app_setup_done is False: try: setup_app(config) config['app_setup_done'] = True first_run = True except Exception as exx: config['app_setup_done'] = False log.error("Failed to serve request: %r" % exx) raise exx # set the decryption device before loading linotp config, # so it contains the decrypted values as well glo = getGlobalObject() self.sep = glo.security_provider try: hsm = self.sep.getSecurityModule() self.hsm = hsm c.hsm = hsm except Exception as exx: log.exception('failed to assign hsm device: %r' % exx) raise exx l_config = getLinotpConfig() # initialize the elliptic curve secret + public key for the qrtoken secret_key = l_config.get('SecretKey.Partition.0', False) if not secret_key: init_key_partition(l_config, partition=0) resolver_setup_done = config.get('resolver_setup_done', False) if resolver_setup_done is False: try: cache_dir = config.get("app_conf", {}).get("cache_dir", None) setupResolvers(config=l_config, cache_dir=cache_dir) config['resolver_setup_done'] = True except Exception as exx: config['resolver_setup_done'] = False log.error("Failed to setup resolver: %r", exx) raise exx # TODO: verify merge dropped # initResolvers() # if we are in the setup cycle, we check for the linotpLicenseFile if first_run: if "linotpLicenseFile" in config and 'license' not in l_config: license_str = '' filename = config.get("linotpLicenseFile", '') try: with open(filename) as f: license_str = f.read() except IOError: log.error("could not open licence file: %s", filename) if not license_str: log.error("empty license file: %s", filename) else: with request_context_safety(): request_context['translate'] = translate import linotp.lib.support res, msg = linotp.lib.support.setSupportLicense( license_str) if res is False: log.error("failed to load license: %s: %s", license_str, msg) else: log.info("license successfully loaded") if 'provider.config_file' in config: from linotp.provider import load_provider_ini load_provider_ini(config['provider.config_file']) return
def sendResultIterator(obj, id=1, opt=None, rp=None, page=None, request_context_copy=None): ''' sendResultIterator - return an json result document in a streamed mode which requires a request context to be avaliable :param obj: iterator of generator object like dict, string or list :param id: id value, for future versions :param opt: optional parameter, which allows to provide more detail :param rp: results per page :param page: number of page :return: generator of response data (yield) ''' if request_context_copy is None: request_context_copy = {} # establish the request context within the pylons middleware with request_context_safety(): for key, value in request_context_copy.items(): request_context[key] = value api_version = get_api_version() linotp_version = get_version() res = {"jsonrpc": api_version, "result": {"status": True, "value": "[DATA]", }, "version": linotp_version, "id": id} err = {"jsonrpc": api_version, "result": {"status": False, "error": {}, }, "version": linotp_version, "id": id } start_at = 0 stop_at = 0 if page: if not rp: rp = 16 try: start_at = int(page) * int(rp) stop_at = start_at + int(rp) except ValueError as exx: err['result']['error'] = { "code": 9876, "message": "%r" % exx, } log.exception("failed to convert paging request parameters: %r" % exx) yield json.dumps(err) # finally we signal end of error result raise StopIteration() typ = "%s" % type(obj) if 'generator' not in typ and 'iterator' not in typ: raise Exception('no iterator method for object %r' % obj) res = {"jsonrpc": api_version, "result": {"status": True, "value": "[DATA]", }, "version": linotp_version, "id": id} if page: res['result']['page'] = int(page) if opt is not None and len(opt) > 0: res["detail"] = opt surrounding = json.dumps(res) prefix, postfix = surrounding.split('"[DATA]"') # first return the opening yield prefix + " [" sep = "" counter = 0 for next_one in obj: counter = counter + 1 # are we running in paging mode? if page: if counter >= start_at and counter < stop_at: res = "%s%s\n" % (sep, next_one) sep = ',' yield res if counter >= stop_at: # stop iterating if we reached the last one of the page break else: # no paging - no limit res = "%s%s\n" % (sep, next_one) sep = ',' yield res # we add the amount of queried objects total = '"queried" : %d' % counter postfix = ', %s %s' % (total, postfix) # last return the closing yield "] " + postfix