diff options
-rw-r--r-- | client/src/leap/soledad/client/_secrets/__init__.py | 25 | ||||
-rw-r--r-- | client/src/leap/soledad/client/_secrets/crypto.py | 7 | ||||
-rw-r--r-- | client/src/leap/soledad/client/_secrets/storage.py | 40 | ||||
-rw-r--r-- | client/src/leap/soledad/client/_secrets/util.py | 4 | ||||
-rw-r--r-- | client/src/leap/soledad/client/api.py | 57 | ||||
-rw-r--r-- | testing/tests/client/test_aux_methods.py | 12 | ||||
-rw-r--r-- | testing/tests/client/test_deprecated_crypto.py | 2 | ||||
-rw-r--r-- | testing/tests/client/test_secrets.py | 10 | ||||
-rw-r--r-- | testing/tests/server/test_server.py | 2 |
9 files changed, 60 insertions, 99 deletions
diff --git a/client/src/leap/soledad/client/_secrets/__init__.py b/client/src/leap/soledad/client/_secrets/__init__.py index 78cfae5e..43541e16 100644 --- a/client/src/leap/soledad/client/_secrets/__init__.py +++ b/client/src/leap/soledad/client/_secrets/__init__.py @@ -43,16 +43,11 @@ class Secrets(EmitMixin): 'local_secret': 448, # local_secret to derive a local_key for storage } - def __init__(self, uuid, passphrase, url, local_path, get_token, userid, - shared_db=None): - self._uuid = uuid - self._passphrase = passphrase - self._userid = userid + def __init__(self, soledad): + self._soledad = soledad self._secrets = {} - self.crypto = SecretsCrypto(self.get_passphrase) - self.storage = SecretsStorage( - uuid, self.get_passphrase, url, local_path, get_token, userid, - shared_db=shared_db) + self.crypto = SecretsCrypto(soledad) + self.storage = SecretsStorage(soledad) self._bootstrap() # @@ -83,6 +78,8 @@ class Secrets(EmitMixin): if encrypted['version'] < self.crypto.VERSION or force_storage: # TODO: what should we do if it's the first run and remote save # fails? + # TODO: we have to actually update the encrypted version before + # saving, we are currently not doing it. self.storage.save_local(encrypted) self.storage.save_remote(encrypted) @@ -112,15 +109,7 @@ class Secrets(EmitMixin): data = {'secret': encrypted, 'version': 2} return data - def get_passphrase(self): - return self._passphrase.encode('utf-8') - - @property - def passphrase(self): - return self.get_passphrase() - - def change_passphrase(self, new_passphrase): - self._passphrase = new_passphrase + def store_secrets(self): encrypted = self.crypto.encrypt(self._secrets) self.storage.save_local(encrypted) self.storage.save_remote(encrypted) diff --git a/client/src/leap/soledad/client/_secrets/crypto.py b/client/src/leap/soledad/client/_secrets/crypto.py index 02d7dc02..fa7aaca0 100644 --- a/client/src/leap/soledad/client/_secrets/crypto.py +++ b/client/src/leap/soledad/client/_secrets/crypto.py @@ -34,11 +34,12 @@ class SecretsCrypto(object): VERSION = 2 - def __init__(self, get_pass): - self._get_pass = get_pass + def __init__(self, soledad): + self._soledad = soledad def _get_key(self, salt): - key = scrypt.hash(self._get_pass(), salt, buflen=32) + passphrase = self._soledad.passphrase.encode('utf8') + key = scrypt.hash(passphrase, salt, buflen=32) return key # diff --git a/client/src/leap/soledad/client/_secrets/storage.py b/client/src/leap/soledad/client/_secrets/storage.py index 5fde8988..bb74dba3 100644 --- a/client/src/leap/soledad/client/_secrets/storage.py +++ b/client/src/leap/soledad/client/_secrets/storage.py @@ -33,29 +33,26 @@ logger = getLogger(__name__) class SecretsStorage(EmitMixin): - def __init__(self, uuid, get_pass, url, local_path, get_token, userid, - shared_db=None): - self._uuid = uuid - self._get_pass = get_pass - self._local_path = local_path - self._get_token = get_token - self._userid = userid - - self._shared_db = shared_db or self._init_shared_db(url, self._creds) + def __init__(self, soledad): + self._soledad = soledad + self._shared_db = self._soledad.shared_db or self._init_shared_db() self.__remote_doc = None @property def _creds(self): - return {'token': {'uuid': self._uuid, 'token': self._get_token()}} + uuid = self._soledad.uuid + token = self._soledad.token + return {'token': {'uuid': uuid, 'token': token}} # # local storage # def load_local(self): - logger.info("trying to load secrets from disk: %s" % self._local_path) + path = self._soledad.secrets_path + logger.info("trying to load secrets from disk: %s" % path) try: - with open(self._local_path, 'r') as f: + with open(path, 'r') as f: encrypted = json.loads(f.read()) logger.info("secrets loaded successfully from disk") return encrypted @@ -64,23 +61,26 @@ class SecretsStorage(EmitMixin): return None def save_local(self, encrypted): + path = self._soledad.secrets_path json_data = json.dumps(encrypted) - with open(self._local_path, 'w') as f: + with open(path, 'w') as f: f.write(json_data) # # remote storage # - def _init_shared_db(self, url, creds): - url = urlparse.urljoin(url, SHARED_DB_NAME) - db = SoledadSharedDatabase.open_database( - url, self._uuid, creds=creds) - self._shared_db = db + def _init_shared_db(self): + url = urlparse.urljoin(self._soledad.server_url, SHARED_DB_NAME) + uuid = self._soledad.uuid + creds = self._creds + db = SoledadSharedDatabase.open_database(url, uuid, creds) + return db def _remote_doc_id(self): - passphrase = self._get_pass() - text = '%s%s' % (passphrase, self._uuid) + passphrase = self._soledad.passphrase.encode('utf8') + uuid = self._soledad.uuid + text = '%s%s' % (passphrase, uuid) digest = sha256(text).hexdigest() return digest diff --git a/client/src/leap/soledad/client/_secrets/util.py b/client/src/leap/soledad/client/_secrets/util.py index 0dcdd3af..75418518 100644 --- a/client/src/leap/soledad/client/_secrets/util.py +++ b/client/src/leap/soledad/client/_secrets/util.py @@ -27,7 +27,9 @@ class EmitMixin(object): @property def _user_data(self): - return {'uuid': self._uuid, 'userid': self._userid} + uuid = self._soledad.uuid + userid = self._soledad.userid + return {'uuid': uuid, 'userid': userid} def emit(verb): diff --git a/client/src/leap/soledad/client/api.py b/client/src/leap/soledad/client/api.py index 16569ec2..4be38cf1 100644 --- a/client/src/leap/soledad/client/api.py +++ b/client/src/leap/soledad/client/api.py @@ -177,27 +177,25 @@ class Soledad(object): some reason. """ # store config params - self._uuid = uuid - self._passphrase = passphrase + self.uuid = uuid + self.passphrase = passphrase + self.secrets_path = secrets_path self._local_db_path = local_db_path - self._server_url = server_url - self._secrets_path = None + self.server_url = server_url + self.shared_db = shared_db + self.token = auth_token + self.offline = offline + self._dbsyncer = None - self._offline = offline # configure SSL certificate global SOLEDAD_CERT SOLEDAD_CERT = cert_file - self.set_token(auth_token) - self._init_config_with_defaults() self._init_working_dirs() - self._secrets_path = secrets_path - - self._init_secrets(shared_db=shared_db) - + self._secrets = Secrets(self) self._crypto = SoledadCrypto(self._secrets.remote_secret) try: @@ -214,14 +212,6 @@ class Soledad(object): self._dbpool.close() raise - def _get_offline(self): - return self._offline - - def _set_offline(self, offline): - self._offline = offline - - offline = property(_get_offline, _set_offline) - # # initialization/destruction methods # @@ -230,7 +220,7 @@ class Soledad(object): """ Initialize configuration using default values for missing params. """ - soledad_assert_type(self._passphrase, unicode) + soledad_assert_type(self.passphrase, unicode) def initialize(attr, val): return ((getattr(self, attr, None) is None) and @@ -241,7 +231,7 @@ class Soledad(object): initialize("_local_db_path", os.path.join( self.default_prefix, self.local_db_file_name)) # initialize server_url - soledad_assert(self._server_url is not None, + soledad_assert(self.server_url is not None, 'Missing URL for Soledad server.') def _init_working_dirs(self): @@ -255,14 +245,6 @@ class Soledad(object): for path in paths: create_path_if_not_exists(path) - def _init_secrets(self, shared_db=None): - """ - Initialize Soledad secrets. - """ - self._secrets = Secrets( - self._uuid, self._passphrase, self._server_url, self._secrets_path, - self.get_token, self.userid, shared_db=shared_db) - def _init_u1db_sqlcipher_backend(self): """ Initialize the U1DB SQLCipher database for local storage. @@ -647,10 +629,6 @@ class Soledad(object): return self._local_db_path @property - def uuid(self): - return self._uuid - - @property def userid(self): return self.uuid @@ -687,7 +665,7 @@ class Soledad(object): generation before the synchronization was performed. :rtype: twisted.internet.defer.Deferred """ - sync_url = urlparse.urljoin(self._server_url, 'user-%s' % self.uuid) + sync_url = urlparse.urljoin(self.server_url, 'user-%s' % self.uuid) if not self._dbsyncer: return creds = {'token': {'uuid': self.uuid, 'token': self.token}} @@ -748,14 +726,6 @@ class Soledad(object): """ return self.sync_lock.locked - def set_token(self, token): - self._token = token - - def get_token(self): - return self._token - - token = property(get_token, set_token, doc='The authentication Token.') - # # ISecretsStorage # @@ -779,7 +749,8 @@ class Soledad(object): :raise NoStorageSecret: Raised if there's no storage secret available. """ - self._secrets.change_passphrase(new_passphrase) + self.passphrase = new_passphrase + self._secrets.store_secrets() # # Raw SQLCIPHER Queries diff --git a/testing/tests/client/test_aux_methods.py b/testing/tests/client/test_aux_methods.py index a08f7d36..729aa28a 100644 --- a/testing/tests/client/test_aux_methods.py +++ b/testing/tests/client/test_aux_methods.py @@ -33,7 +33,7 @@ class AuxMethodsTestCase(BaseSoledadTest): def test__init_dirs(self): sol = self._soledad_instance(prefix='_init_dirs') local_db_dir = os.path.dirname(sol.local_db_path) - secrets_path = os.path.dirname(sol.secrets.storage._local_path) + secrets_path = os.path.dirname(sol.secrets_path) self.assertTrue(os.path.isdir(local_db_dir)) self.assertTrue(os.path.isdir(secrets_path)) @@ -63,8 +63,8 @@ class AuxMethodsTestCase(BaseSoledadTest): # instantiate without initializing so we just test # _init_config_with_defaults() sol = SoledadMock() - sol._passphrase = u'' - sol._server_url = '' + sol.passphrase = u'' + sol.server_url = '' sol._init_config_with_defaults() # assert value of local_db_path self.assertEquals( @@ -84,11 +84,11 @@ class AuxMethodsTestCase(BaseSoledadTest): cert_file=None) self.assertEqual( os.path.join(self.tempdir, 'value_3'), - sol.secrets.storage._local_path) + sol.secrets_path) self.assertEqual( os.path.join(self.tempdir, 'value_2'), sol.local_db_path) - self.assertEqual('value_1', sol._server_url) + self.assertEqual('value_1', sol.server_url) sol.close() @inlineCallbacks @@ -128,5 +128,5 @@ class AuxMethodsTestCase(BaseSoledadTest): Assert passphrase getter works fine. """ sol = self._soledad_instance() - self.assertEqual('123', sol._passphrase) + self.assertEqual('123', sol.passphrase) sol.close() diff --git a/testing/tests/client/test_deprecated_crypto.py b/testing/tests/client/test_deprecated_crypto.py index 8c711c22..1af1a130 100644 --- a/testing/tests/client/test_deprecated_crypto.py +++ b/testing/tests/client/test_deprecated_crypto.py @@ -51,7 +51,7 @@ class DeprecatedCryptoTest(SoledadWithCouchServerMixin, TestCaseWithServer): self._soledad_instance(user=user, server_url=server_url)) self.make_app() - remote = self.request_state._create_database(replica_uid=client._uuid) + remote = self.request_state._create_database(replica_uid=client.uuid) remote = CouchDatabase.open_database( urljoin(self.couch_url, 'user-' + user), create=True) diff --git a/testing/tests/client/test_secrets.py b/testing/tests/client/test_secrets.py index bbeb1fc2..18ff458b 100644 --- a/testing/tests/client/test_secrets.py +++ b/testing/tests/client/test_secrets.py @@ -121,12 +121,10 @@ class SecretsCryptoTestCase(unittest.TestCase): } def setUp(self): - def _get_pass(): - return '123' - self._crypto = SecretsCrypto(_get_pass) - - def test__get_pass(self): - self.assertEqual(self._crypto._get_pass(), '123') + class Soledad(object): + passphrase = '123' + soledad = Soledad() + self._crypto = SecretsCrypto(soledad) def test__get_key(self): salt = 'abc' diff --git a/testing/tests/server/test_server.py b/testing/tests/server/test_server.py index 647ef5a8..4a5ec43f 100644 --- a/testing/tests/server/test_server.py +++ b/testing/tests/server/test_server.py @@ -135,7 +135,7 @@ class EncryptedSyncTestCase( user=user, prefix='x', auth_token='auth-token', - secrets_path=sol1._secrets_path, + secrets_path=sol1.secrets_path, passphrase=passphrase) # ensure remote db exists before syncing |