Mercurial > hg
comparison 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 |
comparison
equal
deleted
inserted
replaced
13312:9f188734dbb0 | 13314:8dc488dfcdb4 |
---|---|
531 if cacerts: | 531 if cacerts: |
532 cacerts = util.expandpath(cacerts) | 532 cacerts = util.expandpath(cacerts) |
533 else: | 533 else: |
534 cacerts = None | 534 cacerts = None |
535 | 535 |
536 if cacerts: | 536 hostfingerprint = self.ui.config('hostfingerprints', self.host) |
537 if cacerts and not hostfingerprint: | |
537 sock = _create_connection((self.host, self.port)) | 538 sock = _create_connection((self.host, self.port)) |
538 self.sock = _ssl_wrap_socket(sock, self.key_file, | 539 self.sock = _ssl_wrap_socket(sock, self.key_file, |
539 self.cert_file, cert_reqs=CERT_REQUIRED, | 540 self.cert_file, cert_reqs=CERT_REQUIRED, |
540 ca_certs=cacerts) | 541 ca_certs=cacerts) |
541 msg = _verifycert(self.sock.getpeercert(), self.host) | 542 msg = _verifycert(self.sock.getpeercert(), self.host) |
543 raise util.Abort(_('%s certificate error: %s') % | 544 raise util.Abort(_('%s certificate error: %s') % |
544 (self.host, msg)) | 545 (self.host, msg)) |
545 self.ui.debug('%s certificate successfully verified\n' % | 546 self.ui.debug('%s certificate successfully verified\n' % |
546 self.host) | 547 self.host) |
547 else: | 548 else: |
548 self.ui.warn(_("warning: %s certificate not verified " | |
549 "(check web.cacerts config setting)\n") % | |
550 self.host) | |
551 httplib.HTTPSConnection.connect(self) | 549 httplib.HTTPSConnection.connect(self) |
550 if hasattr(self.sock, 'getpeercert'): | |
551 peercert = self.sock.getpeercert(True) | |
552 peerfingerprint = util.sha1(peercert).hexdigest() | |
553 nicefingerprint = ":".join([peerfingerprint[x:x + 2] | |
554 for x in xrange(0, len(peerfingerprint), 2)]) | |
555 if hostfingerprint: | |
556 if peerfingerprint.lower() != \ | |
557 hostfingerprint.replace(':', '').lower(): | |
558 raise util.Abort(_('invalid certificate for %s ' | |
559 'with fingerprint %s') % | |
560 (self.host, nicefingerprint)) | |
561 self.ui.debug('%s certificate matched fingerprint %s\n' % | |
562 (self.host, nicefingerprint)) | |
563 else: | |
564 self.ui.warn(_('warning: %s certificate ' | |
565 'with fingerprint %s not verified ' | |
566 '(check hostfingerprints or web.cacerts ' | |
567 'config setting)\n') % | |
568 (self.host, nicefingerprint)) | |
569 else: # python 2.5 ? | |
570 if hostfingerprint: | |
571 raise util.Abort(_('no certificate for %s ' | |
572 'with fingerprint') % self.host) | |
573 self.ui.warn(_('warning: %s certificate not verified ' | |
574 '(check web.cacerts config setting)\n') % | |
575 self.host) | |
552 | 576 |
553 class httpsconnection(BetterHTTPS): | 577 class httpsconnection(BetterHTTPS): |
554 response_class = keepalive.HTTPResponse | 578 response_class = keepalive.HTTPResponse |
555 # must be able to send big bundle as stream. | 579 # must be able to send big bundle as stream. |
556 send = _gen_sendfile(BetterHTTPS) | 580 send = _gen_sendfile(BetterHTTPS) |