diff options
author | Victor Shyba <victor1984@riseup.net> | 2017-08-22 05:23:24 -0300 |
---|---|---|
committer | drebs <drebs@riseup.net> | 2017-09-05 11:08:46 -0300 |
commit | c8c742cb981cbe4087a7863ebc3d2a8e3dd93f25 (patch) | |
tree | dfc0fbec7de3c97368e81299bf5216c62cef42a3 /src/leap/soledad/server/auth.py | |
parent | 9f4739c4ce468110fe070c766260770bb4d669a2 (diff) |
[feature] add a local realm with file auth checker
-- Related: #8867
Diffstat (limited to 'src/leap/soledad/server/auth.py')
-rw-r--r-- | src/leap/soledad/server/auth.py | 73 |
1 files changed, 68 insertions, 5 deletions
diff --git a/src/leap/soledad/server/auth.py b/src/leap/soledad/server/auth.py index 1357b289..934517b5 100644 --- a/src/leap/soledad/server/auth.py +++ b/src/leap/soledad/server/auth.py @@ -39,6 +39,7 @@ from twisted.web.resource import IResource from leap.soledad.common.couch import couch_server from ._resource import SoledadResource, SoledadAnonResource +from ._resource import LocalResource from ._blobs import BlobsResource from ._config import get_config @@ -77,8 +78,63 @@ class SoledadRealm(object): raise NotImplementedError() +@implementer(IRealm) +class LocalServicesRealm(object): + + def __init__(self, conf=None): + if conf is None: + conf = get_config() + self.anon_resource = SoledadAnonResource( + enable_blobs=conf['blobs']) + self.auth_resource = LocalResource(conf) + + def requestAvatar(self, avatarId, mind, *interfaces): + + # Anonymous access + if IAnonymous.providedBy(avatarId): + return (IResource, self.anon_resource, + lambda: None) + + # Authenticated access + else: + if IResource in interfaces: + return (IResource, self.auth_resource, + lambda: None) + raise NotImplementedError() + + +@implementer(ICredentialsChecker) +class FileTokenChecker(object): + + def __init__(self, conf=None): + conf = conf or get_config() + self._trusted_services_tokens = {} + self._tokens_file_path = conf['services_tokens_file'] + self._reload_tokens() + + def _reload_tokens(self): + with open(self._tokens_file_path) as tokens_file: + for line in tokens_file.readlines(): + line = line.strip() + if not line.startswith('#'): + service, token = line.split(':') + self._trusted_services_tokens[service] = token + + def requestAvatarId(self, credentials): + if IAnonymous.providedBy(credentials): + return defer.succeed(Anonymous()) + + service = credentials.username + token = credentials.password + + if self._trusted_services_tokens[service] != token: + return defer.fail(error.UnauthorizedLogin()) + + return defer.succeed(service) + + @implementer(ICredentialsChecker) -class TokenChecker(object): +class CouchDBTokenChecker(object): credentialInterfaces = [IUsernamePassword, IAnonymous] @@ -164,10 +220,17 @@ class TokenCredentialFactory(object): raise error.LoginFailed('Invalid credentials') -def portalFactory(sync_pool): - realm = SoledadRealm(sync_pool=sync_pool) - checker = TokenChecker() - return Portal(realm, [checker]) +def portalFactory(public=True, sync_pool=None): + database_checker = CouchDBTokenChecker() + file_checker = FileTokenChecker() + if public: + assert sync_pool + realm = SoledadRealm(sync_pool=sync_pool) + auth_checkers = [database_checker] + else: + realm = LocalServicesRealm() + auth_checkers = [file_checker, database_checker] + return Portal(realm, auth_checkers) credentialFactory = TokenCredentialFactory() |