summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/src/leap/soledad/client/_secrets/__init__.py25
-rw-r--r--client/src/leap/soledad/client/_secrets/crypto.py7
-rw-r--r--client/src/leap/soledad/client/_secrets/storage.py40
-rw-r--r--client/src/leap/soledad/client/_secrets/util.py4
-rw-r--r--client/src/leap/soledad/client/api.py57
-rw-r--r--testing/tests/client/test_aux_methods.py12
-rw-r--r--testing/tests/client/test_deprecated_crypto.py2
-rw-r--r--testing/tests/client/test_secrets.py10
-rw-r--r--testing/tests/server/test_server.py2
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