From 5243c7eb4c58a4419da2103af8c1e4004f01053b Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Tue, 24 Oct 2017 11:53:10 +0200 Subject: [feat] add fetch key by fingerprint to keymanager - Resolves: #9023 --- src/leap/bitmask/cli/keys.py | 21 +++++++++++++++++++ src/leap/bitmask/core/dispatcher.py | 10 +++++++++ src/leap/bitmask/core/mail_services.py | 9 ++++++++ src/leap/bitmask/keymanager/__init__.py | 37 +++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+) (limited to 'src') diff --git a/src/leap/bitmask/cli/keys.py b/src/leap/bitmask/cli/keys.py index 82de3868..ab73bfff 100644 --- a/src/leap/bitmask/cli/keys.py +++ b/src/leap/bitmask/cli/keys.py @@ -41,6 +41,7 @@ SUBCOMMANDS: list List all known keys export Export a given key + fetch Fetch key by fingerprint insert Insert a key to the key storage delete Delete a key from the key storage '''.format(name=command.appname) @@ -97,6 +98,26 @@ SUBCOMMANDS: return self._send(self._print_key) + def fetch(self, raw_args): + parser = argparse.ArgumentParser( + description='Bitmask fetch key by fingerprint', + prog='%s %s %s' % tuple(sys.argv[:3])) + parser.add_argument('-u', '--userid', default='', + help='Select the userid of the keyring') + parser.add_argument('address', nargs=1, + help='email address to pin to the key') + parser.add_argument('fingerprint', nargs=1, + help='fingerprint to fetch of the key') + subargs = parser.parse_args(raw_args) + + userid = subargs.userid + if not userid: + userid = self.cfg.get('bonafide', 'active', default='') + self.data += ['fetch', userid, subargs.address[0], + subargs.fingerprint[0]] + + return self._send(self._print_key) + def insert(self, raw_args): parser = argparse.ArgumentParser( description='Bitmask import key', diff --git a/src/leap/bitmask/core/dispatcher.py b/src/leap/bitmask/core/dispatcher.py index 91168d87..f2b3e8ca 100644 --- a/src/leap/bitmask/core/dispatcher.py +++ b/src/leap/bitmask/core/dispatcher.py @@ -362,6 +362,16 @@ class KeysCmd(SubCommand): return service.do_export(uid, address, private, fetch_remote) + @register_method('dict') + def do_FETCH(self, service, *parts, **kw): + if len(parts) < 5: + raise ValueError("An email address is needed") + uid = parts[2] + address = parts[3] + fingerprint = parts[4] + + return service.do_fetch(uid, address, fingerprint) + @register_method('dict') def do_INSERT(self, service, *parts, **kw): if len(parts) < 6: diff --git a/src/leap/bitmask/core/mail_services.py b/src/leap/bitmask/core/mail_services.py index 31c27364..23105c7a 100644 --- a/src/leap/bitmask/core/mail_services.py +++ b/src/leap/bitmask/core/mail_services.py @@ -422,6 +422,15 @@ class KeymanagerService(HookableService): d.addCallback(lambda key: dict(key)) return d + def do_fetch(self, userid, address, fingerprint): + km = self._container.get_instance(userid) + if km is None: + return defer.fail(ValueError("User " + userid + " has no active " + "keymanager")) + d = km.fetch_key_fingerprint(address, fingerprint) + d.addCallback(lambda key: dict(key)) + return d + def do_insert(self, userid, address, rawkey, validation='Fingerprint'): km = self._container.get_instance(userid) if km is None: diff --git a/src/leap/bitmask/keymanager/__init__.py b/src/leap/bitmask/keymanager/__init__.py index 45b7e582..e3ff3b87 100644 --- a/src/leap/bitmask/keymanager/__init__.py +++ b/src/leap/bitmask/keymanager/__init__.py @@ -261,6 +261,43 @@ class KeyManager(object): d.addCallbacks(key_found, key_not_found) return d + @defer.inlineCallbacks + def fetch_key_fingerprint(self, address, fingerprint): + """ + Fetch a key from the key servers by fingerprint. + + It will replace any key assigned to the address in the keyring and have + validation level Fingerprint. + + :param address: The address bound to the key. + :type address: str + :param fingerprint: The fingerprint of the key to fetch. + :type fingerprint: str + + :return: A Deferred which fires with an EncryptionKey fetched, + or which fails with KeyNotFound if no key was found in the + keyserver for this fingerprint. + :rtype: Deferred + """ + key_data = yield self._nicknym.fetch_key_with_fingerprint(fingerprint) + key, _ = self._openpgp.parse_key(key_data, address) + key.validation = ValidationLevels.Fingerprint + + if key.fingerprint != fingerprint: + raise keymanager_errors.KeyNotFound("Got wrong fingerprint") + + try: + old_key = yield self._openpgp.get_key(address) + if old_key.fingerprint == key.fingerprint: + key.last_audited_at = old_key.last_audited_at + key.encr_used = old_key.encr_used + key.sign_used = old_key.sign_used + except keymanager_errors.KeyNotFound: + pass + + yield self._openpgp.put_key(key) + defer.returnValue(key) + def get_all_keys(self, private=False): """ Return all keys stored in local database. -- cgit v1.2.3