summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/leap/bitmask/keymanager/__init__.py99
-rw-r--r--src/leap/bitmask/keymanager/keys.py3
-rw-r--r--src/leap/bitmask/keymanager/nicknym.py12
-rw-r--r--src/leap/bitmask/keymanager/openpgp.py3
-rw-r--r--src/leap/bitmask/keymanager/refresher.py19
-rw-r--r--src/leap/bitmask/mail/testing/__init__.py2
-rw-r--r--tests/integration/keymanager/test_keymanager.py26
-rw-r--r--tests/integration/keymanager/test_refresher.py35
-rw-r--r--tests/integration/mail/smtp/test_gateway.py2
9 files changed, 72 insertions, 129 deletions
diff --git a/src/leap/bitmask/keymanager/__init__.py b/src/leap/bitmask/keymanager/__init__.py
index 319be08..ed3726a 100644
--- a/src/leap/bitmask/keymanager/__init__.py
+++ b/src/leap/bitmask/keymanager/__init__.py
@@ -19,10 +19,8 @@ Key Manager is a Nicknym agent for LEAP client.
"""
import fileinput
import json
-import os
import sys
import tempfile
-import urllib
from urlparse import urlparse
@@ -32,13 +30,13 @@ from twisted.web import client
from twisted.web._responses import NOT_FOUND
from leap.common import ca_bundle
-from leap.common.check import leap_assert
-from leap.common.decorators import memoized_method
from leap.common.http import HTTPClient
from leap.common.events import emit_async, catalog
from leap.bitmask.keymanager import errors as keymanager_errors
+from leap.bitmask.keymanager.errors import KeyNotFound
from leap.bitmask.keymanager.nicknym import Nicknym
+from leap.bitmask.keymanager.refresher import RandomRefreshPublicKey
from leap.bitmask.keymanager.validation import ValidationLevels, can_upgrade
from leap.bitmask.keymanager.openpgp import OpenPGPScheme
@@ -101,7 +99,8 @@ class KeyManager(object):
self._combined_ca_bundle = ''
self._async_client = HTTPClient(self._combined_ca_bundle)
- self._nicknym = Nicknym(self._nickserver_uri, self._ca_cert_path, self._token)
+ self._nicknym = Nicknym(self._nickserver_uri,
+ self._ca_cert_path, self._token)
self.refresher = None
#
@@ -155,14 +154,17 @@ class KeyManager(object):
except IOError as e:
logger.warn("HTTP error retrieving key: %r" % (e,))
logger.warn("%s" % (content,))
- raise keymanager_errors.KeyNotFound(e.message), None, sys.exc_info()[2]
+ raise keymanager_errors.KeyNotFound(e.message), \
+ None, sys.exc_info()[2]
except ValueError as v:
logger.warn("invalid JSON data from key: %s" % (uri,))
- raise keymanager_errors.KeyNotFound(v.message + ' - ' + uri), None, sys.exc_info()[2]
+ raise keymanager_errors.KeyNotFound(v.message + ' - ' + uri), \
+ None, sys.exc_info()[2]
except Exception as e:
logger.warn("error retrieving key: %r" % (e,))
- raise keymanager_errors.KeyNotFound(e.message), None, sys.exc_info()[2]
+ raise keymanager_errors.KeyNotFound(e.message), \
+ None, sys.exc_info()[2]
# Responses are now text/plain, although it's json anyway, but
# this will fail when it shouldn't
# leap_assert(
@@ -189,7 +191,7 @@ class KeyManager(object):
raise KeyNotFound(message), None, sys.exc_info()[2]
return response
- d = self._async_client_pinned.request(
+ d = self._nicknym._async_client_pinned.request(
str(uri), 'GET', callback=check_404)
d.addCallback(client.readBody)
return d
@@ -219,76 +221,6 @@ class KeyManager(object):
raise keymanager_errors.KeyNotFound(uri)
defer.returnValue(content)
- @defer.inlineCallbacks
- def _put(self, uri, data=None):
- """
- Send a PUT request to C{uri} containing C{data}.
-
- The request will be sent using the configured CA certificate path to
- verify the server certificate and the configured session id for
- authentication.
-
- :param uri: The URI of the request.
- :type uri: str
- :param data: The body of the request.
- :type data: dict, str or file
-
- :return: A deferred that will be fired when PUT request finishes
- :rtype: Deferred
- """
- leap_assert(
- self._token is not None,
- 'We need a token to interact with webapp!')
- if type(data) == dict:
- data = urllib.urlencode(data)
- headers = {'Authorization': [str('Token token=%s' % self._token)]}
- headers['Content-Type'] = ['application/x-www-form-urlencoded']
- try:
- res = yield self._async_client_pinned.request(str(uri), 'PUT',
- body=str(data),
- headers=headers)
- except Exception as e:
- logger.warn("Error uploading key: %r" % (e,))
- raise e
- if 'error' in res:
- # FIXME: That's a workaround for 500,
- # we need to implement a readBody to assert response code
- logger.warn("Error uploading key: %r" % (res,))
- raise Exception(res)
-
- @memoized_method(invalidation=300)
- @defer.inlineCallbacks
- def _fetch_keys_from_server(self, address):
- """
- Fetch keys bound to address from nickserver and insert them in
- local database.
-
- :param address: The address bound to the keys.
- :type address: str
-
- :return: A Deferred which fires when the key is in the storage,
- or which fails with KeyNotFound if the key was not found on
- nickserver.
- :rtype: Deferred
-
- """
- # request keys from the nickserver
- server_keys = yield self._get_key_from_nicknym(address)
-
- # insert keys in local database
- if self.OPENPGP_KEY in server_keys:
- # nicknym server is authoritative for its own domain,
- # for other domains the key might come from key servers.
- validation_level = ValidationLevels.Weak_Chain
- _, domain = _split_email(address)
- if (domain == _get_domain(self._nickserver_uri)):
- validation_level = ValidationLevels.Provider_Trust
-
- yield self.put_raw_key(
- server_keys['openpgp'],
- address=address,
- validation=validation_level)
-
#
# key management
#
@@ -307,7 +239,8 @@ class KeyManager(object):
:raise UnsupportedKeyTypeError: if invalid key type
"""
def send(pubkey):
- d = self._nicknym.put_key(self.uid, pubkey.key_data, self._api_uri, self._api_version)
+ d = self._nicknym.put_key(self.uid, pubkey.key_data,
+ self._api_uri, self._api_version)
d.addCallback(lambda _:
emit_async(catalog.KEYMANAGER_DONE_UPLOADING_KEYS,
self._address))
@@ -327,9 +260,9 @@ class KeyManager(object):
:type address: str
:return: A Deferred which fires when the key is in the storage,
- or which fails with KeyNotFound if the key was not found on
- nickserver.
- :rtype: Deferred
+ or which fails with KeyNotFound if the key was not
+ found on nickserver.
+ :rtype: Deferred
"""
server_keys = yield self._nicknym.fetch_key_with_address(address)
diff --git a/src/leap/bitmask/keymanager/keys.py b/src/leap/bitmask/keymanager/keys.py
index 1b236c3..fd45448 100644
--- a/src/leap/bitmask/keymanager/keys.py
+++ b/src/leap/bitmask/keymanager/keys.py
@@ -292,7 +292,8 @@ class OpenPGPKey(object):
:return: True if key expired.
:rtype: bool
"""
- return False if self.expiry_date is None else self.expiry_date < datetime.now()
+ return False if self.expiry_date is None \
+ else self.expiry_date < datetime.now()
def parse_address(address):
diff --git a/src/leap/bitmask/keymanager/nicknym.py b/src/leap/bitmask/keymanager/nicknym.py
index 7af49d6..5fe9992 100644
--- a/src/leap/bitmask/keymanager/nicknym.py
+++ b/src/leap/bitmask/keymanager/nicknym.py
@@ -139,12 +139,14 @@ class Nicknym(object):
def check_404(response):
if response.code == NOT_FOUND:
- message = ' %s: Key not found. Request: %s' % (response.code, uri)
+ message = ' %s: Key not found. Request: %s' \
+ % (response.code, uri)
logger.warning(message)
raise KeyNotFound(message), None, sys.exc_info()[2]
return response
- d = self._async_client_pinned.request(str(uri), 'GET', callback=check_404)
+ d = self._async_client_pinned.request(str(uri), 'GET',
+ callback=check_404)
d.addCallback(client.readBody)
return d
@@ -162,7 +164,8 @@ class Nicknym(object):
:rtype: Deferred
"""
- return self._get_key_from_nicknym(self._nickserver_uri + '?address=' + address)
+ return self._get_key_from_nicknym(self._nickserver_uri +
+ '?address=' + address)
@memoized_method(invalidation=300)
def fetch_key_with_fingerprint(self, fingerprint):
@@ -178,4 +181,5 @@ class Nicknym(object):
:rtype: Deferred
"""
- return self._get_key_from_nicknym(self._nickserver_uri + '?fingerprint=' + fingerprint)
+ return self._get_key_from_nicknym(self._nickserver_uri +
+ '?fingerprint=' + fingerprint)
diff --git a/src/leap/bitmask/keymanager/openpgp.py b/src/leap/bitmask/keymanager/openpgp.py
index b256ff0..b72c62c 100644
--- a/src/leap/bitmask/keymanager/openpgp.py
+++ b/src/leap/bitmask/keymanager/openpgp.py
@@ -533,12 +533,13 @@ class OpenPGPScheme(object):
d.addCallback(delete_key)
return d
+ @defer.inlineCallbacks
def unactivate_key(self, address):
"""
Mark a active doc as deleted.
:param address: The unique address for the active content.
"""
- active_doc = self._get_active_doc_from_address(address, False)
+ active_doc = yield self._get_active_doc_from_address(address, False)
yield self._soledad.delete_doc(active_doc)
#
diff --git a/src/leap/bitmask/keymanager/refresher.py b/src/leap/bitmask/keymanager/refresher.py
index 54232c3..694a537 100644
--- a/src/leap/bitmask/keymanager/refresher.py
+++ b/src/leap/bitmask/keymanager/refresher.py
@@ -17,24 +17,25 @@
"""
-A service which continuous refreshes the (public) key directories randomly in a random time interval.
+A service which continuous refreshes the (public) key directories randomly in a
+random time interval.
"""
-import logging
-
from twisted.internet.task import LoopingCall
+from twisted.logger import Logger
from twisted.internet import defer
from random import choice, randrange
DEBUG_STOP_REFRESH = "Stop to refresh the key directory ..."
DEBUG_START_REFRESH = "Start to refresh the key directory ..."
-ERROR_UNEQUAL_FINGERPRINTS = "[WARNING] Your provider might be cheat on you, " \
- "and gave a wrong key back. Fingerprints are unequal, old %s new %s "
+ERROR_UNEQUAL_FINGERPRINTS = "[WARNING] Your provider might be cheat " \
+ "on you, and gave a wrong key back. " \
+ "Fingerprints are unequal, old %s new %s "
MIN_RANDOM_INTERVAL_RANGE = 4 * 60 # four minutes
MAX_RANDOM_INTERVAL_RANGE = 6 * 60 # six minutes
-logger = logging.getLogger(__name__)
+logger = Logger()
class RandomRefreshPublicKey(object):
@@ -74,7 +75,6 @@ class RandomRefreshPublicKey(object):
:return: A random key.
:rtype: A deferred.
"""
- # TODO maybe make a check first if key is active and get another one then.
keys = yield self._openpgp.get_all_keys()
defer.returnValue(None if keys is None or keys == [] else choice(keys))
@@ -117,8 +117,9 @@ class RandomRefreshPublicKey(object):
yield self._maybe_unactivate_key(old_updated_key)
yield self._openpgp.put_key(old_updated_key)
- # No new fetch by address needed, bc that will happen before sending an email
- # could be discussed since fetching before sending an email leaks information.
+ # No new fetch by address needed, bc that will happen before sending an
+ # email could be discussed since fetching before sending an email
+ # leaks information.
def _get_random_interval_to_refresh(self):
"""
diff --git a/src/leap/bitmask/mail/testing/__init__.py b/src/leap/bitmask/mail/testing/__init__.py
index 5ebfaf5..afb8e43 100644
--- a/src/leap/bitmask/mail/testing/__init__.py
+++ b/src/leap/bitmask/mail/testing/__init__.py
@@ -69,7 +69,7 @@ class KeyManagerWithSoledadTestCase(unittest.TestCase, BaseLeapTest):
def deliverBody(self, x):
return ''
- self.km._async_client_pinned.request = Mock(
+ self.km._nicknym._async_client_pinned.request = Mock(
return_value=defer.succeed(Response()))
d1 = self.km.put_raw_key(PRIVATE_KEY, ADDRESS)
diff --git a/tests/integration/keymanager/test_keymanager.py b/tests/integration/keymanager/test_keymanager.py
index c623b94..86e9115 100644
--- a/tests/integration/keymanager/test_keymanager.py
+++ b/tests/integration/keymanager/test_keymanager.py
@@ -206,8 +206,8 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
token = "mytoken"
km = self._key_manager(token=token)
yield km._openpgp.put_raw_key(PUBLIC_KEY, ADDRESS)
- km._async_client.request = mock.Mock(
- return_value=defer.succeed(''))
+ km._nicknym._async_client_pinned.request = \
+ mock.Mock(return_value=defer.succeed(''))
# the following data will be used on the send
km.ca_cert_path = 'capath'
km.session_id = 'sessionid'
@@ -280,9 +280,9 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
check_404_callback = used_kwargs['callback']
fake_response = mock.Mock()
fake_response.code = NOT_FOUND
- with self.assertRaisesRegexp(
- errors.KeyNotFound,
- '404: Key not found. Request: %s' % url.replace('?', '\?')):
+ with self.assertRaisesRegexp(errors.KeyNotFound,
+ '404: Key not found. Request: '
+ '%s' % url.replace('?', '\?')):
check_404_callback(fake_response)
d.addCallback(check_key_not_found_is_raised_if_404)
@@ -323,7 +323,8 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
"""
km = self._key_manager(url=NICKSERVER_URI)
- key = yield self._fetch_key_with_address(km, ADDRESS_OTHER, PUBLIC_KEY_OTHER)
+ key = yield self._fetch_key_with_address(km, ADDRESS_OTHER,
+ PUBLIC_KEY_OTHER)
self.assertIsInstance(key, OpenPGPKey)
self.assertTrue(ADDRESS_OTHER in key.uids)
self.assertEqual(key.validation, ValidationLevels.Weak_Chain)
@@ -395,8 +396,8 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
"""
km = self._key_manager()
- km._nicknym._async_client_pinned.request = mock.Mock(
- return_value=defer.succeed(PUBLIC_KEY))
+ km._async_client.request = \
+ mock.Mock(return_value=defer.succeed(PUBLIC_KEY))
yield km.fetch_key(ADDRESS, "http://site.domain/key")
key = yield km.get_key(ADDRESS)
@@ -410,7 +411,7 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
"""
km = self._key_manager()
- km._nicknym._async_client_pinned.request = mock.Mock(
+ km._async_client.request = mock.Mock(
return_value=defer.succeed(self.get_public_binary_key()))
yield km.fetch_key(ADDRESS, "http://site.domain/key")
@@ -423,7 +424,8 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
"""
km = self._key_manager()
- km._nicknym._async_client_pinned.request = mock.Mock(return_value=defer.succeed(""))
+ km._nicknym._async_client_pinned.request = \
+ mock.Mock(return_value=defer.succeed(""))
d = km.fetch_key(ADDRESS, "http://site.domain/key")
return self.assertFailure(d, errors.KeyNotFound)
@@ -434,8 +436,8 @@ class KeyManagerKeyManagementTestCase(KeyManagerWithSoledadTestCase):
"""
km = self._key_manager()
- km._nicknym._async_client_pinned.request = mock.Mock(
- return_value=defer.succeed(PUBLIC_KEY))
+ km._async_client.request = \
+ mock.Mock(return_value=defer.succeed(PUBLIC_KEY))
d = km.fetch_key(ADDRESS_2, "http://site.domain/key")
return self.assertFailure(d, errors.KeyAddressMismatch)
diff --git a/tests/integration/keymanager/test_refresher.py b/tests/integration/keymanager/test_refresher.py
index 47dd057..b5b36b0 100644
--- a/tests/integration/keymanager/test_refresher.py
+++ b/tests/integration/keymanager/test_refresher.py
@@ -18,7 +18,6 @@
"""
Tests for refreshing the key directory.
"""
-
from datetime import datetime
from mock import Mock, patch
@@ -28,8 +27,9 @@ from twisted.logger import Logger
from leap.bitmask.keymanager import openpgp
from leap.bitmask.keymanager.keys import OpenPGPKey
-from leap.bitmask.keymanager.refresher import RandomRefreshPublicKey, MIN_RANDOM_INTERVAL_RANGE, DEBUG_START_REFRESH, \
- DEBUG_STOP_REFRESH, ERROR_UNEQUAL_FINGERPRINTS
+from leap.bitmask.keymanager.refresher import RandomRefreshPublicKey, \
+ MIN_RANDOM_INTERVAL_RANGE, DEBUG_START_REFRESH, DEBUG_STOP_REFRESH,\
+ ERROR_UNEQUAL_FINGERPRINTS
from leap.bitmask.keymanager.testing import KeyManagerWithSoledadTestCase
from common import KEY_FINGERPRINT
@@ -37,9 +37,6 @@ from common import KEY_FINGERPRINT
ANOTHER_FP = 'ANOTHERFINGERPRINT'
-logger = Logger()
-
-
class RandomRefreshPublicKeyTestCase(KeyManagerWithSoledadTestCase):
@defer.inlineCallbacks
@@ -53,7 +50,8 @@ class RandomRefreshPublicKeyTestCase(KeyManagerWithSoledadTestCase):
pgp.get_all_keys = Mock(return_value=defer.succeed([key, key_another]))
random_key = yield rf._get_random_key()
- self.assertTrue(random_key.address == key.address or random_key.address == key_another.address)
+ self.assertTrue(random_key.address == key.address or
+ random_key.address == key_another.address)
@defer.inlineCallbacks
def test_do_not_throw_error_for_empty_key_dict(self):
@@ -66,8 +64,7 @@ class RandomRefreshPublicKeyTestCase(KeyManagerWithSoledadTestCase):
self.assertTrue(random_address is None)
@defer.inlineCallbacks
- def _test_log_error_if_fetch_by_fingerprint_returns_wrong_key(self):
- # FIXME !!! ---------------------------------------------------
+ def test_log_error_if_fetch_by_fingerprint_returns_wrong_key(self):
pgp = openpgp.OpenPGPScheme(
self._soledad, gpgbinary=self.gpg_binary_path)
km = self._key_manager()
@@ -75,10 +72,12 @@ class RandomRefreshPublicKeyTestCase(KeyManagerWithSoledadTestCase):
with patch.object(Logger, 'error') as mock_logger_error:
rf = RandomRefreshPublicKey(pgp, km)
rf._get_random_key = \
- Mock(return_value=defer.succeed(OpenPGPKey(fingerprint=KEY_FINGERPRINT)))
+ Mock(return_value=defer.succeed(OpenPGPKey(
+ fingerprint=KEY_FINGERPRINT)))
km._nicknym.fetch_key_with_fingerprint = \
- Mock(return_value=defer.succeed(OpenPGPKey(fingerprint=ANOTHER_FP)))
+ Mock(return_value=defer.succeed(OpenPGPKey(
+ fingerprint=ANOTHER_FP)))
yield rf.maybe_refresh_key()
@@ -92,10 +91,11 @@ class RandomRefreshPublicKeyTestCase(KeyManagerWithSoledadTestCase):
km = self._key_manager()
rf = RandomRefreshPublicKey(pgp, km)
- rf._get_random_key = Mock(return_value=defer.succeed(OpenPGPKey(fingerprint=KEY_FINGERPRINT)))
+ rf._get_random_key = Mock(return_value=defer.succeed(
+ OpenPGPKey(fingerprint=KEY_FINGERPRINT)))
- km._nicknym.fetch_key_with_fingerprint = \
- Mock(return_value=defer.succeed(OpenPGPKey(fingerprint=ANOTHER_FP)))
+ km._nicknym.fetch_key_with_fingerprint = Mock(
+ return_value=defer.succeed(OpenPGPKey(fingerprint=ANOTHER_FP)))
yield rf.maybe_refresh_key()
@@ -107,13 +107,14 @@ class RandomRefreshPublicKeyTestCase(KeyManagerWithSoledadTestCase):
rf = RandomRefreshPublicKey(pgp, km)
key = OpenPGPKey(address='zara@leap.se', expiry_date=datetime.now())
self.assertTrue(key.address is 'zara@leap.se')
- km._openpgp.unactivate_key = Mock(return_value=defer.succeed(None))
+ pgp.unactivate_key = Mock(return_value=defer.succeed(None))
+
yield rf._maybe_unactivate_key(key)
+
self.assertTrue(key.address is None)
self.assertFalse(key.is_active())
- def _test_start_refreshing(self):
- # FIXME !!! ---------------------------------------------------
+ def test_start_refreshing(self):
pgp = openpgp.OpenPGPScheme(
self._soledad, gpgbinary=self.gpg_binary_path)
diff --git a/tests/integration/mail/smtp/test_gateway.py b/tests/integration/mail/smtp/test_gateway.py
index e286be9..38abfe7 100644
--- a/tests/integration/mail/smtp/test_gateway.py
+++ b/tests/integration/mail/smtp/test_gateway.py
@@ -113,7 +113,7 @@ class TestSmtpGateway(KeyManagerWithSoledadTestCase):
self._soledad, gpgbinary=self.gpg_binary_path)
yield pgp.delete_key(pubkey)
# mock the key fetching
- self.km._fetch_keys_from_server = Mock(
+ self.km._nicknym.fetch_key_with_address = Mock(
return_value=fail(errors.KeyNotFound()))
user = TEST_USER
proto = getSMTPFactory(