Ejemplo n.º 1
0
    def _getkey(self, email, key):
        error = None
        key_data = None
        for url_base in self.KEY_SERVER_BASE_URLS:
            url = self._getkey_url(url_base, email, key)
            if 'keylookup' in self.session.config.sys.debug:
                self.session.ui.debug('Fetching: %s' % url)
            try:
                key_data = secure_urlget(self.session,
                                         url,
                                         maxbytes=self.MAX_KEY_SIZE + 1)
                error = None
                break
            except urllib2.HTTPError as e:
                error = e
                if e.code == 404:
                    # If a server reports the key was not found, let's stop
                    # because the servers are supposed to be in sync.
                    break
            except (IOError, urllib2.URLError, ssl.SSLError,
                    ssl.CertificateError) as e:
                error = e

        if not key_data:
            error = 'No key data!'

        if not error and len(key_data) > self.MAX_KEY_SIZE:
            error = "Key too big (>%d bytes), ignoring" % self.MAX_KEY_SIZE
            if 'keylookup' in self.session.config.sys.debug:
                self.session.ui.debug(error)

        if error:
            raise ValueError(str(error))

        return self._gnupg().import_keys(key_data, filter_uid_emails=[email])
Ejemplo n.º 2
0
    def _lookup(self, address, strict_email_match=False):
        error = None
        for url_base in self.KEY_SERVER_BASE_URLS:
            url = self._lookup_url(url_base, address)
            if 'keyservers' in self.session.config.sys.debug:
                self.session.ui.debug('[%s] Fetching: %s' % (self.NAME, url))
            try:
                raw_result = secure_urlget(self.session,
                                           url,
                                           maxbytes=self.MAX_KEY_SIZE + 1)
                error = None
                break
            except urllib2.HTTPError as e:
                error = str(e)
                if e.code == 404:
                    # If a server reports the key was not found, let's stop
                    # because the servers are supposed to be in sync.
                    break
            except (IOError, urllib2.URLError, ssl.SSLError,
                    ssl.CertificateError) as e:
                error = str(e)

        if not error and len(raw_result) > self.MAX_KEY_SIZE:
            error = "Response too big (>%d bytes), ignoring" % self.MAX_KEY_SIZE
            if 'keyservers' in self.session.config.sys.debug:
                self.session.ui.debug('[%s] %s' % (self.NAME, error))

        if error:
            if 'keyservers' in self.session.config.sys.debug:
                self.session.ui.debug('Error: %s' % error)
            if 'Error 404' in error:
                return {}
            raise ValueError(error)

        if 'keyservers' in self.session.config.sys.debug:
            self.session.ui.debug('[%s] DATA: %s' %
                                  (self.NAME, raw_result[:200]))
        results = self._gnupg().parse_hpk_response(raw_result.split('\n'))

        if strict_email_match:
            for key in results.keys():
                match = [
                    u for u in results[key].get('uids', [])
                    if u['email'].lower() == address
                ]
                if not match:
                    if 'keyservers' in self.session.config.sys.debug:
                        self.session.ui.debug(
                            '[%s] No UID for %s, ignoring key' %
                            (self.NAME, address))
                    del results[key]

        if 'keyservers' in self.session.config.sys.debug:
            self.session.ui.debug('[%s] Results=%d' %
                                  (self.NAME, len(results)))

        return results
Ejemplo n.º 3
0
    def _lookup(self, address, strict_email_match=True):
        local, _, domain = address.partition("@")
        if domain.lower() in self.DOMAIN_BLACKLIST:
            # FIXME: Maybe make this dynamic; check for the WKD policy file and
            #        if it is present remove the provider from the blacklist.
            self.session.ui.debug('[%s] Blacklisted domain, skipping: %s' %
                                  (self.NAME, domain))
            return {}

        # FIXMEs:
        #   - Check the spec and make sure we are doing the right thing when
        #     comes to redirects. Probably switch off. But Linus! They seem
        #     broken now, wah, wah, wah.
        #   - Check the policy file, if it doesn't exist don't leak the
        #     e-mail address to the server? Cache this? Counter-argument,
        #     shame if user has no policy file but has a published key.
        #   - Check content-type, because some sites return weird crap.

        local_part_encoded = _zbase_encode(
            hashlib.sha1(local.lower().encode('utf-8')).digest())
        error = None
        keyinfo = None
        for url in WebKeyDirectoryURLs(address):
            try:
                if 'keylookup' in self.session.config.sys.debug:
                    self.session.ui.debug('[%s] Fetching %s' %
                                          (self.NAME, url))
                key_data = secure_urlget(self.session,
                                         url,
                                         maxbytes=self.MAX_KEY_SIZE + 1,
                                         timeout=int(self.TIMEOUT / 3))
                if key_data:
                    keyinfo = get_keyinfo(key_data,
                                          key_source=(self.SHORTNAME, url),
                                          key_info_class=MailpileKeyInfo)[0]
                    error = None
                    break
                else:
                    error = 'Key not found'
            except urllib.request.HTTPError as e:
                if e.code == 404 and '+' not in address:
                    error = '404: %s' % e
                    # 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)
            except ssl.CertificateError as e:
                error = 'TLS: %s' % e
            except (urllib.request.URLError, ValueError, KeyError) as e:
                error = 'FAIL: %s' % e

        if not error and len(key_data) > self.MAX_KEY_SIZE:
            error = "Key too big (>%d bytes), ignoring" % self.MAX_KEY_SIZE
            if 'keylookup' in self.session.config.sys.debug:
                self.session.ui.debug(error)

        if error and 'keylookup' in self.session.config.sys.debug:
            self.session.ui.debug('[%s] Error: %s' % (self.NAME, error))
        if not error:
            self.key_cache[keyinfo["fingerprint"]] = key_data
        elif error[:3] in ('TLS', 'FAI', '404'):
            return {}  # Suppress these errors, they are common.
        else:
            raise ValueError(error)

        # FIXME: Key refreshes will need to know where this key came
        #        from, we should record this somewhere. Should WKD
        #        keys be considered ephemeral? What about revocations?
        #        What about signatures? What if we get back multiple
        #        keys/certs? What if we get back a revocation?

        return {keyinfo["fingerprint"]: keyinfo}
Ejemplo n.º 4
0
 def _get(self, url):
     self.session.ui.mark('Getting: {0!s}'.format(url))
     return secure_urlget(self.session, url,
                          timeout=5,
                          anonymous=self.config.anonymous)
Ejemplo n.º 5
0
 def _get(self, url):
     self.session.ui.mark('Getting: %s' % url)
     return secure_urlget(self.session, url,
                          timeout=5,
                          anonymous=self.config.anonymous)