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 | 
