Show More
@@ -423,6 +423,24 b' Example for ``~/.hgrc``::' | |||
|
423 | 423 | myfeature = ~/.hgext/myfeature.py |
|
424 | 424 | |
|
425 | 425 | |
|
426 | ``hostfingerprints`` | |
|
427 | """""""""""""""""""" | |
|
428 | ||
|
429 | Fingerprints of the certificates of known HTTPS servers. | |
|
430 | A HTTPS connection to a server with a fingerprint configured here will | |
|
431 | only succeed if the servers certificate matches the fingerprint. | |
|
432 | This is very similar to how ssh known hosts works. | |
|
433 | The fingerprint is the SHA-1 hash value of the DER encoded certificate. | |
|
434 | The CA chain and web.cacerts is not used for servers with a fingerprint. | |
|
435 | ||
|
436 | For example:: | |
|
437 | ||
|
438 | [hostfingerprints] | |
|
439 | hg.intevation.org = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc | |
|
440 | ||
|
441 | This feature is only supported when using Python 2.6 or later. | |
|
442 | ||
|
443 | ||
|
426 | 444 | ``format`` |
|
427 | 445 | """""""""" |
|
428 | 446 |
@@ -546,7 +546,7 b' def remoteui(src, opts):' | |||
|
546 | 546 | dst.setconfig('bundle', 'mainreporoot', r) |
|
547 | 547 | |
|
548 | 548 | # copy selected local settings to the remote ui |
|
549 | for sect in ('auth', 'http_proxy'): | |
|
549 | for sect in ('auth', 'hostfingerprints', 'http_proxy'): | |
|
550 | 550 | for key, val in src.configitems(sect): |
|
551 | 551 | dst.setconfig(sect, key, val) |
|
552 | 552 | v = src.config('web', 'cacerts') |
@@ -533,7 +533,8 b' if has_https:' | |||
|
533 | 533 | else: |
|
534 | 534 | cacerts = None |
|
535 | 535 | |
|
536 | if cacerts: | |
|
536 | hostfingerprint = self.ui.config('hostfingerprints', self.host) | |
|
537 | if cacerts and not hostfingerprint: | |
|
537 | 538 | sock = _create_connection((self.host, self.port)) |
|
538 | 539 | self.sock = _ssl_wrap_socket(sock, self.key_file, |
|
539 | 540 | self.cert_file, cert_reqs=CERT_REQUIRED, |
@@ -545,10 +546,33 b' if has_https:' | |||
|
545 | 546 | self.ui.debug('%s certificate successfully verified\n' % |
|
546 | 547 | self.host) |
|
547 | 548 | else: |
|
548 | self.ui.warn(_("warning: %s certificate not verified " | |
|
549 | "(check web.cacerts config setting)\n") % | |
|
550 | self.host) | |
|
551 | 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 | 577 | class httpsconnection(BetterHTTPS): |
|
554 | 578 | response_class = keepalive.HTTPResponse |
@@ -106,7 +106,7 b' Test server address cannot be reused' | |||
|
106 | 106 | clone via pull |
|
107 | 107 | |
|
108 | 108 | $ hg clone https://localhost:$HGPORT/ copy-pull |
|
109 | warning: localhost certificate not verified (check web.cacerts config setting) | |
|
109 | warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting) | |
|
110 | 110 | requesting all changes |
|
111 | 111 | adding changesets |
|
112 | 112 | adding manifests |
@@ -132,7 +132,7 b' pull without cacert' | |||
|
132 | 132 | $ echo '[hooks]' >> .hg/hgrc |
|
133 | 133 | $ echo "changegroup = python '$TESTDIR'/printenv.py changegroup" >> .hg/hgrc |
|
134 | 134 | $ hg pull |
|
135 | warning: localhost certificate not verified (check web.cacerts config setting) | |
|
135 | warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting) | |
|
136 | 136 | changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=https://localhost:$HGPORT/ |
|
137 | 137 | pulling from https://localhost:$HGPORT/ |
|
138 | 138 | searching for changes |
@@ -188,3 +188,22 b' Test server cert which no longer is vali' | |||
|
188 | 188 | $ hg -R copy-pull pull --config web.cacerts=pub-expired.pem https://localhost:$HGPORT2/ |
|
189 | 189 | abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob) |
|
190 | 190 | [255] |
|
191 | ||
|
192 | Fingerprints | |
|
193 | ||
|
194 | $ echo "[hostfingerprints]" >> copy-pull/.hg/hgrc | |
|
195 | $ echo "localhost = 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca" >> copy-pull/.hg/hgrc | |
|
196 | $ echo "127.0.0.1 = 914f1aff87249c09b6859b88b1906d30756491ca" >> copy-pull/.hg/hgrc | |
|
197 | ||
|
198 | - works without cacerts | |
|
199 | $ hg -R copy-pull id https://localhost:$HGPORT/ --config web.cacerts= | |
|
200 | 5fed3813f7f5 | |
|
201 | ||
|
202 | - fails when cert doesn't match hostname (port is ignored) | |
|
203 | $ hg -R copy-pull id https://localhost:$HGPORT1/ | |
|
204 | abort: invalid certificate for localhost with fingerprint 28:ff:71:bf:65:31:14:23:ad:62:92:b4:0e:31:99:18:fc:83:e3:9b | |
|
205 | [255] | |
|
206 | ||
|
207 | - ignores that certificate doesn't match hostname | |
|
208 | $ hg -R copy-pull id https://127.0.0.1:$HGPORT/ | |
|
209 | 5fed3813f7f5 |
General Comments 0
You need to be logged in to leave comments.
Login now