##// END OF EJS Templates
sslutil: Restore missing imports of socket and httplib to sslutil...
Stephen Thorne -
r14616:64dfbe57 default
parent child Browse files
Show More
@@ -1,126 +1,128 b''
1 1 # sslutil.py - SSL handling for mercurial
2 2 #
3 3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
5 5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9 import os
10 10
11 11 from mercurial import util
12 12 from mercurial.i18n import _
13 13 try:
14 14 # avoid using deprecated/broken FakeSocket in python 2.6
15 15 import ssl
16 16 ssl_wrap_socket = ssl.wrap_socket
17 17 CERT_REQUIRED = ssl.CERT_REQUIRED
18 18 except ImportError:
19 19 CERT_REQUIRED = 2
20 20
21 import socket, httplib
22
21 23 def ssl_wrap_socket(sock, key_file, cert_file,
22 24 cert_reqs=CERT_REQUIRED, ca_certs=None):
23 25 if ca_certs:
24 26 raise util.Abort(_(
25 27 'certificate checking requires Python 2.6'))
26 28
27 29 ssl = socket.ssl(sock, key_file, cert_file)
28 30 return httplib.FakeSocket(sock, ssl)
29 31
30 32 def _verifycert(cert, hostname):
31 33 '''Verify that cert (in socket.getpeercert() format) matches hostname.
32 34 CRLs is not handled.
33 35
34 36 Returns error message if any problems are found and None on success.
35 37 '''
36 38 if not cert:
37 39 return _('no certificate received')
38 40 dnsname = hostname.lower()
39 41 def matchdnsname(certname):
40 42 return (certname == dnsname or
41 43 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1])
42 44
43 45 san = cert.get('subjectAltName', [])
44 46 if san:
45 47 certnames = [value.lower() for key, value in san if key == 'DNS']
46 48 for name in certnames:
47 49 if matchdnsname(name):
48 50 return None
49 51 return _('certificate is for %s') % ', '.join(certnames)
50 52
51 53 # subject is only checked when subjectAltName is empty
52 54 for s in cert.get('subject', []):
53 55 key, value = s[0]
54 56 if key == 'commonName':
55 57 try:
56 58 # 'subject' entries are unicode
57 59 certname = value.lower().encode('ascii')
58 60 except UnicodeEncodeError:
59 61 return _('IDN in certificate not supported')
60 62 if matchdnsname(certname):
61 63 return None
62 64 return _('certificate is for %s') % certname
63 65 return _('no commonName or subjectAltName found in certificate')
64 66
65 67
66 68 # CERT_REQUIRED means fetch the cert from the server all the time AND
67 69 # validate it against the CA store provided in web.cacerts.
68 70 #
69 71 # We COMPLETELY ignore CERT_REQUIRED on Python <= 2.5, as it's totally
70 72 # busted on those versions.
71 73
72 74 def sslkwargs(ui, host):
73 75 cacerts = ui.config('web', 'cacerts')
74 76 hostfingerprint = ui.config('hostfingerprints', host)
75 77 if cacerts and not hostfingerprint:
76 78 cacerts = util.expandpath(cacerts)
77 79 if not os.path.exists(cacerts):
78 80 raise util.Abort(_('could not find web.cacerts: %s') % cacerts)
79 81 return {'ca_certs': cacerts,
80 82 'cert_reqs': CERT_REQUIRED,
81 83 }
82 84 return {}
83 85
84 86 class validator(object):
85 87 def __init__(self, ui, host):
86 88 self.ui = ui
87 89 self.host = host
88 90
89 91 def __call__(self, sock):
90 92 host = self.host
91 93 cacerts = self.ui.config('web', 'cacerts')
92 94 hostfingerprint = self.ui.config('hostfingerprints', host)
93 95 if cacerts and not hostfingerprint:
94 96 msg = _verifycert(sock.getpeercert(), host)
95 97 if msg:
96 98 raise util.Abort(_('%s certificate error: %s '
97 99 '(use --insecure to connect '
98 100 'insecurely)') % (host, msg))
99 101 self.ui.debug('%s certificate successfully verified\n' % host)
100 102 else:
101 103 if getattr(sock, 'getpeercert', False):
102 104 peercert = sock.getpeercert(True)
103 105 peerfingerprint = util.sha1(peercert).hexdigest()
104 106 nicefingerprint = ":".join([peerfingerprint[x:x + 2]
105 107 for x in xrange(0, len(peerfingerprint), 2)])
106 108 if hostfingerprint:
107 109 if peerfingerprint.lower() != \
108 110 hostfingerprint.replace(':', '').lower():
109 111 raise util.Abort(_('invalid certificate for %s '
110 112 'with fingerprint %s') %
111 113 (host, nicefingerprint))
112 114 self.ui.debug('%s certificate matched fingerprint %s\n' %
113 115 (host, nicefingerprint))
114 116 else:
115 117 self.ui.warn(_('warning: %s certificate '
116 118 'with fingerprint %s not verified '
117 119 '(check hostfingerprints or web.cacerts '
118 120 'config setting)\n') %
119 121 (host, nicefingerprint))
120 122 else: # python 2.5 ?
121 123 if hostfingerprint:
122 124 raise util.Abort(_('no certificate for %s with '
123 125 'configured hostfingerprint') % host)
124 126 self.ui.warn(_('warning: %s certificate not verified '
125 127 '(check web.cacerts config setting)\n') %
126 128 host)
General Comments 0
You need to be logged in to leave comments. Login now