##// END OF EJS Templates
url: 'ssh known host'-like checking of fingerprints of HTTPS certificates...
Mads Kiilerich -
r13314:8dc488df stable
parent child Browse files
Show More
@@ -423,6 +423,24 b' Example for ``~/.hgrc``::'
423 myfeature = ~/.hgext/myfeature.py
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 ``format``
444 ``format``
427 """"""""""
445 """"""""""
428
446
@@ -546,7 +546,7 b' def remoteui(src, opts):'
546 dst.setconfig('bundle', 'mainreporoot', r)
546 dst.setconfig('bundle', 'mainreporoot', r)
547
547
548 # copy selected local settings to the remote ui
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 for key, val in src.configitems(sect):
550 for key, val in src.configitems(sect):
551 dst.setconfig(sect, key, val)
551 dst.setconfig(sect, key, val)
552 v = src.config('web', 'cacerts')
552 v = src.config('web', 'cacerts')
@@ -533,7 +533,8 b' if has_https:'
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,
@@ -545,10 +546,33 b' if has_https:'
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 httplib.HTTPSConnection.connect(self)
549 "(check web.cacerts config setting)\n") %
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') %
550 self.host)
575 self.host)
551 httplib.HTTPSConnection.connect(self)
552
576
553 class httpsconnection(BetterHTTPS):
577 class httpsconnection(BetterHTTPS):
554 response_class = keepalive.HTTPResponse
578 response_class = keepalive.HTTPResponse
@@ -106,7 +106,7 b' Test server address cannot be reused'
106 clone via pull
106 clone via pull
107
107
108 $ hg clone https://localhost:$HGPORT/ copy-pull
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 requesting all changes
110 requesting all changes
111 adding changesets
111 adding changesets
112 adding manifests
112 adding manifests
@@ -132,7 +132,7 b' pull without cacert'
132 $ echo '[hooks]' >> .hg/hgrc
132 $ echo '[hooks]' >> .hg/hgrc
133 $ echo "changegroup = python '$TESTDIR'/printenv.py changegroup" >> .hg/hgrc
133 $ echo "changegroup = python '$TESTDIR'/printenv.py changegroup" >> .hg/hgrc
134 $ hg pull
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 changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=https://localhost:$HGPORT/
136 changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=https://localhost:$HGPORT/
137 pulling from https://localhost:$HGPORT/
137 pulling from https://localhost:$HGPORT/
138 searching for changes
138 searching for changes
@@ -188,3 +188,22 b' Test server cert which no longer is vali'
188 $ hg -R copy-pull pull --config web.cacerts=pub-expired.pem https://localhost:$HGPORT2/
188 $ hg -R copy-pull pull --config web.cacerts=pub-expired.pem https://localhost:$HGPORT2/
189 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
189 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
190 [255]
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