self.key_cache[keydata["fingerprint"]] = key if len(keys) > 5: # Just to set some limit... break self.key_cache[messageid] = keys return keys def has_pgpkey_data_kw_extractor(index, msg, mimetype, filename, part, loader, body_info=None, **kwargs): kws = [] if _might_be_pgp_key(filename, mimetype): data = _get_keydata(part.get_payload(None, True)) for keydata in data: for uid in keydata.get('uids', []): if uid.get('email'): kws.append('%s:pgpkey' % uid['email'].lower()) if data: body_info['pgp_key'] = filename kws += ['pgpkey:has'] # FIXME: If this is a PGP key, make all the key IDs searchable so # we can find this file again later! Searching by e-mail is lame. # This is issue #655 ? return kws register_crypto_key_lookup_handler(EmailKeyLookupHandler) _plugins.register_data_kw_extractor('pgpkey', has_pgpkey_data_kw_extractor) _ = gettext
self.key_cache[keydata["fingerprint"]] = key if len(keys) > 5: # Just to set some limit... break self.key_cache[messageid] = keys return keys def has_pgpkey_data_kw_extractor(index, msg, mimetype, filename, part, loader, body_info=None, **kwargs): kws = [] if _might_be_pgp_key(filename, mimetype): data = _get_keydata(part.get_payload(None, True)) for keydata in data: for uid in keydata.get('uids', []): if uid.get('email'): kws.append('%s:pgpkey' % uid['email'].lower()) if data: body_info['pgp_key'] = filename kws += ['pgpkey:has'] # FIXME: If this part is a signature, record which signatures we've # seen from which keys, for historic profiling purposes. Keys # used more often are less likely to be forgeries. return kws register_crypto_key_lookup_handler(EmailKeyLookupHandler) _plugins.register_data_kw_extractor('pgpkey', has_pgpkey_data_kw_extractor) _ = gettext
fingerprint: { "fingerprint": fingerprint, "url": url, "pkaver": pkaver } } def _getkey(self, key): if key["fingerprint"] and not key["url"]: res = self._gnupg().recv_key(key["fingerprint"]) elif key["url"]: r = urllib2.urlopen(key["url"]) result = r.readlines() start = 0 end = len(result) # Hack to deal with possible HTML results from keyservers: for i in range(len(result)): if result[i].startswith("-----BEGIN PGP"): start = i elif result[i].startswith("-----END PGP"): end = i result = "".join(result[start:end]) res = self._gnupg().import_keys(result) return res else: raise ValueError("Need a fingerprint or a URL") _ = gettext register_crypto_key_lookup_handler(DNSPKALookupHandler)
url = ("https://%s/.well-known/openpgpkey/hu/%s" % (domain, local_part_encoded)) # This fails A LOT, so just swallow the most common errors. try: with ConnBroker.context(need=[ConnBroker.OUTGOING_HTTPS]): r = urllib2.urlopen(url) except urllib2.URLError: # This gets thrown on TLS key mismatch return {} except urllib2.HTTPError as e: if e.code == 404: return {} raise result = r.read() keydata = get_keydata(result)[0] self.key_cache[keydata["fingerprint"]] = result return {keydata["fingerprint"]: keydata} def _getkey(self, keydata): data = self.key_cache.pop(keydata["fingerprint"]) if data: return self._gnupg().import_keys(data) else: raise ValueError("Key not found") _ = gettext register_crypto_key_lookup_handler(WKDLookupHandler)
if pkaver != "pka1": raise ValueError("We only know how to deal with pka version 1") return {fingerprint: {"fingerprint": fingerprint, "url": url, "pkaver": pkaver}} def _getkey(self, key): if key["fingerprint"] and not key["url"]: res = self._gnupg().recv_key(key["fingerprint"]) elif key["url"]: with ConnBroker.context(need=[ConnBroker.OUTGOING_HTTP]): r = urllib2.urlopen(key["url"]) result = r.readlines() start = 0 end = len(result) # Hack to deal with possible HTML results from keyservers: for i in range(len(result)): if result[i].startswith("-----BEGIN PGP"): start = i elif result[i].startswith("-----END PGP"): end = i result = "".join(result[start:end]) res = self._gnupg().import_keys(result) return res else: raise ValueError("Need a fingerprint or a URL") _ = gettext register_crypto_key_lookup_handler(DNSPKALookupHandler)
if e.code == 404: error = '404' # Since we are testing openpgpkey.* first, if we actually get a # valid response back we should treat that as authoritative and # not waste cycles checking the bare domain too. break else: error = str(e) if not error: result = r.read() keydata = get_keydata(result)[0] self.key_cache[keydata["fingerprint"]] = result elif error in ('TLS', '404'): return {} # Suppress these errors, they are common. else: raise ValueError(error) return {keydata["fingerprint"]: keydata} def _getkey(self, keydata): data = self.key_cache.pop(keydata["fingerprint"]) if data: return self._gnupg().import_keys(data) else: raise ValueError("Key not found") _ = gettext register_crypto_key_lookup_handler(WKDLookupHandler)
return results if __name__ == "__main__": import sys import doctest results = doctest.testmod(optionflags=doctest.ELLIPSIS) print('%s' % (results, )) if results.failed: sys.exit(1) else: _plugins = PluginManager(builtin=__file__) _plugins.register_meta_kw_extractor('autocrypt', autocrypt_meta_kwe) _plugins.register_commands( AutocryptSearch, AutocryptForget, AutocryptParse, AutocryptPeers) register_crypto_key_lookup_handler(AutocryptKeyLookupHandler) register_crypto_policy('autocrypt', autocrypt_policy_checker) # Note: we perform our transformations BEFORE the GnuPG transformations # (prio 500), so the memory hole transformation can take care of hiding # the Autocrypt-Gossip headers. _plugins.register_outgoing_email_content_transform( '400_autocrypt', AutocryptTxf)