--- a/mercurial/sslutil.py Wed May 25 19:57:31 2016 -0700
+++ b/mercurial/sslutil.py Sat May 28 11:12:02 2016 -0700
@@ -106,6 +106,23 @@
return ssl.wrap_socket(socket, **args)
+def _hostsettings(ui, hostname):
+ """Obtain security settings for a hostname.
+
+ Returns a dict of settings relevant to that hostname.
+ """
+ s = {
+ # List of 2-tuple of (hash algorithm, hash).
+ 'certfingerprints': [],
+ }
+
+ # Fingerprints from [hostfingerprints] are always SHA-1.
+ for fingerprint in ui.configlist('hostfingerprints', hostname, []):
+ fingerprint = fingerprint.replace(':', '').lower()
+ s['certfingerprints'].append(('sha1', fingerprint))
+
+ return s
+
def _determinecertoptions(ui, host):
"""Determine certificate options for a connections.
@@ -217,6 +234,7 @@
sslsocket._hgstate = {
'caloaded': caloaded,
'hostname': serverhostname,
+ 'settings': _hostsettings(ui, serverhostname),
'ui': ui,
}
@@ -292,6 +310,7 @@
"""
host = sock._hgstate['hostname']
ui = sock._hgstate['ui']
+ settings = sock._hgstate['settings']
try:
peercert = sock.getpeercert(True)
@@ -305,15 +324,13 @@
# If a certificate fingerprint is pinned, use it and only it to
# validate the remote cert.
- hostfingerprints = ui.configlist('hostfingerprints', host)
peerfingerprint = util.sha1(peercert).hexdigest()
nicefingerprint = ":".join([peerfingerprint[x:x + 2]
for x in xrange(0, len(peerfingerprint), 2)])
- if hostfingerprints:
+ if settings['certfingerprints']:
fingerprintmatch = False
- for hostfingerprint in hostfingerprints:
- if peerfingerprint.lower() == \
- hostfingerprint.replace(':', '').lower():
+ for hash, fingerprint in settings['certfingerprints']:
+ if peerfingerprint.lower() == fingerprint:
fingerprintmatch = True
break
if not fingerprintmatch: