Mercurial > public > mercurial-scm > hg
diff mercurial/url.py @ 13314:8dc488dfcdb4 stable
url: 'ssh known host'-like checking of fingerprints of HTTPS certificates
Known fingerprints of HTTPS servers can now be configured in the
hostfingerprints section. That makes it possible to verify the identify of web
servers without configuring and trusting the CA chain.
Limitations:
* Portnumbers are ignored, just like with ordinary certificates.
* Host name matching is case sensitive.
author | Mads Kiilerich <mads@kiilerich.com> |
---|---|
date | Fri, 28 Jan 2011 02:57:59 +0100 |
parents | 75d0c38a0bca |
children | 0d1dca7d2a04 a939f08fae9c |
line wrap: on
line diff
--- a/mercurial/url.py Thu Jan 27 17:21:23 2011 -0600 +++ b/mercurial/url.py Fri Jan 28 02:57:59 2011 +0100 @@ -533,7 +533,8 @@ else: cacerts = None - if cacerts: + hostfingerprint = self.ui.config('hostfingerprints', self.host) + if cacerts and not hostfingerprint: sock = _create_connection((self.host, self.port)) self.sock = _ssl_wrap_socket(sock, self.key_file, self.cert_file, cert_reqs=CERT_REQUIRED, @@ -545,10 +546,33 @@ self.ui.debug('%s certificate successfully verified\n' % self.host) else: - self.ui.warn(_("warning: %s certificate not verified " - "(check web.cacerts config setting)\n") % - self.host) httplib.HTTPSConnection.connect(self) + if hasattr(self.sock, 'getpeercert'): + peercert = self.sock.getpeercert(True) + peerfingerprint = util.sha1(peercert).hexdigest() + nicefingerprint = ":".join([peerfingerprint[x:x + 2] + for x in xrange(0, len(peerfingerprint), 2)]) + if hostfingerprint: + if peerfingerprint.lower() != \ + hostfingerprint.replace(':', '').lower(): + raise util.Abort(_('invalid certificate for %s ' + 'with fingerprint %s') % + (self.host, nicefingerprint)) + self.ui.debug('%s certificate matched fingerprint %s\n' % + (self.host, nicefingerprint)) + else: + self.ui.warn(_('warning: %s certificate ' + 'with fingerprint %s not verified ' + '(check hostfingerprints or web.cacerts ' + 'config setting)\n') % + (self.host, nicefingerprint)) + else: # python 2.5 ? + if hostfingerprint: + raise util.Abort(_('no certificate for %s ' + 'with fingerprint') % self.host) + self.ui.warn(_('warning: %s certificate not verified ' + '(check web.cacerts config setting)\n') % + self.host) class httpsconnection(BetterHTTPS): response_class = keepalive.HTTPResponse