equal
deleted
inserted
replaced
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br> |
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br> |
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> |
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> |
6 # |
6 # |
7 # This software may be used and distributed according to the terms of the |
7 # This software may be used and distributed according to the terms of the |
8 # GNU General Public License version 2 or any later version. |
8 # GNU General Public License version 2 or any later version. |
9 import os, sys |
9 import os, sys, ssl |
10 |
10 |
11 from mercurial import util |
11 from mercurial import util |
12 from mercurial.i18n import _ |
12 from mercurial.i18n import _ |
13 |
13 |
14 _canloaddefaultcerts = False |
14 _canloaddefaultcerts = False |
15 try: |
15 try: |
16 # avoid using deprecated/broken FakeSocket in python 2.6 |
|
17 import ssl |
|
18 CERT_REQUIRED = ssl.CERT_REQUIRED |
16 CERT_REQUIRED = ssl.CERT_REQUIRED |
19 try: |
17 try: |
20 ssl_context = ssl.SSLContext |
18 ssl_context = ssl.SSLContext |
21 _canloaddefaultcerts = util.safehasattr(ssl_context, |
19 _canloaddefaultcerts = util.safehasattr(ssl_context, |
22 'load_default_certs') |
20 'load_default_certs') |
66 # - see http://bugs.python.org/issue13721 |
64 # - see http://bugs.python.org/issue13721 |
67 if not sslsocket.cipher(): |
65 if not sslsocket.cipher(): |
68 raise util.Abort(_('ssl connection failed')) |
66 raise util.Abort(_('ssl connection failed')) |
69 return sslsocket |
67 return sslsocket |
70 except ImportError: |
68 except ImportError: |
71 CERT_REQUIRED = 2 |
69 raise |
72 |
|
73 import socket, httplib |
|
74 |
|
75 def wrapsocket(sock, keyfile, certfile, ui, |
|
76 cert_reqs=CERT_REQUIRED, |
|
77 ca_certs=None, serverhostname=None): |
|
78 if not util.safehasattr(socket, 'ssl'): |
|
79 raise util.Abort(_('Python SSL support not found')) |
|
80 if ca_certs: |
|
81 raise util.Abort(_( |
|
82 'certificate checking requires Python 2.6')) |
|
83 |
|
84 ssl = socket.ssl(sock, keyfile, certfile) |
|
85 return httplib.FakeSocket(sock, ssl) |
|
86 |
70 |
87 def _verifycert(cert, hostname): |
71 def _verifycert(cert, hostname): |
88 '''Verify that cert (in socket.getpeercert() format) matches hostname. |
72 '''Verify that cert (in socket.getpeercert() format) matches hostname. |
89 CRLs is not handled. |
73 CRLs is not handled. |
90 |
74 |
121 return _('no commonName or subjectAltName found in certificate') |
105 return _('no commonName or subjectAltName found in certificate') |
122 |
106 |
123 |
107 |
124 # CERT_REQUIRED means fetch the cert from the server all the time AND |
108 # CERT_REQUIRED means fetch the cert from the server all the time AND |
125 # validate it against the CA store provided in web.cacerts. |
109 # validate it against the CA store provided in web.cacerts. |
126 # |
|
127 # We COMPLETELY ignore CERT_REQUIRED on Python <= 2.5, as it's totally |
|
128 # busted on those versions. |
|
129 |
110 |
130 def _plainapplepython(): |
111 def _plainapplepython(): |
131 """return true if this seems to be a pure Apple Python that |
112 """return true if this seems to be a pure Apple Python that |
132 * is unfrozen and presumably has the whole mercurial module in the file |
113 * is unfrozen and presumably has the whole mercurial module in the file |
133 system |
114 system |
181 |
162 |
182 def __call__(self, sock, strict=False): |
163 def __call__(self, sock, strict=False): |
183 host = self.host |
164 host = self.host |
184 cacerts = self.ui.config('web', 'cacerts') |
165 cacerts = self.ui.config('web', 'cacerts') |
185 hostfingerprint = self.ui.config('hostfingerprints', host) |
166 hostfingerprint = self.ui.config('hostfingerprints', host) |
186 if not getattr(sock, 'getpeercert', False): # python 2.5 ? |
|
187 if hostfingerprint: |
|
188 raise util.Abort(_("host fingerprint for %s can't be " |
|
189 "verified (Python too old)") % host) |
|
190 if strict: |
|
191 raise util.Abort(_("certificate for %s can't be verified " |
|
192 "(Python too old)") % host) |
|
193 if self.ui.configbool('ui', 'reportoldssl', True): |
|
194 self.ui.warn(_("warning: certificate for %s can't be verified " |
|
195 "(Python too old)\n") % host) |
|
196 return |
|
197 |
167 |
198 if not sock.cipher(): # work around http://bugs.python.org/issue13721 |
168 if not sock.cipher(): # work around http://bugs.python.org/issue13721 |
199 raise util.Abort(_('%s ssl connection error') % host) |
169 raise util.Abort(_('%s ssl connection error') % host) |
200 try: |
170 try: |
201 peercert = sock.getpeercert(True) |
171 peercert = sock.getpeercert(True) |