Mercurial > hg
annotate mercurial/sslutil.py @ 27367:8833daddfc3f
test: rename 'check-code' own test to 'test-contrib-check-code.t'
This test (making sure the 'check-code' script run as intended) have been
confused with the test making that the mercurial code base comply with our
coding still by multiple generations of contributors.
We are moving it out of the way so that all tests starting with
'test-check' are now doing compliance testing.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Sat, 05 Dec 2015 22:47:26 -0800 |
parents | 9e15286609ae |
children | 6c7d26cef0cd |
rev | line source |
---|---|
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
1 # sslutil.py - SSL handling for mercurial |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
2 # |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com> |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br> |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
6 # |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
7 # This software may be used and distributed according to the terms of the |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
8 # GNU General Public License version 2 or any later version. |
25977
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
9 |
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
10 from __future__ import absolute_import |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
11 |
25977
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
12 import os |
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
13 import ssl |
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
14 import sys |
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
15 |
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
16 from .i18n import _ |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
17 from . import error, util |
24291
760a86865f80
ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents:
24290
diff
changeset
|
18 |
26622
9e15286609ae
sslutil: expose attribute indicating whether SNI is supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26587
diff
changeset
|
19 hassni = getattr(ssl, 'HAS_SNI', False) |
9e15286609ae
sslutil: expose attribute indicating whether SNI is supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26587
diff
changeset
|
20 |
24291
760a86865f80
ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents:
24290
diff
changeset
|
21 _canloaddefaultcerts = False |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
22 try: |
25431
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
23 ssl_context = ssl.SSLContext |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
24 _canloaddefaultcerts = util.safehasattr(ssl_context, 'load_default_certs') |
23834
bf07c19b4c82
https: support tls sni (server name indication) for https urls (issue3090)
Alex Orange <crazycasta@gmail.com>
parents:
23069
diff
changeset
|
25 |
25431
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
26 def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE, |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
27 ca_certs=None, serverhostname=None): |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
28 # Allow any version of SSL starting with TLSv1 and |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
29 # up. Note that specifying TLSv1 here prohibits use of |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
30 # newer standards (like TLSv1_2), so this is the right way |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
31 # to do this. Note that in the future it'd be better to |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
32 # support using ssl.create_default_context(), which sets |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
33 # up a bunch of things in smart ways (strong ciphers, |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
34 # protocol versions, etc) and is upgraded by Python |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
35 # maintainers for us, but that breaks too many things to |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
36 # do it in a hurry. |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
37 sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
38 sslcontext.options &= ssl.OP_NO_SSLv2 & ssl.OP_NO_SSLv3 |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
39 if certfile is not None: |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
40 def password(): |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
41 f = keyfile or certfile |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
42 return ui.getpass(_('passphrase for %s: ') % f, '') |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
43 sslcontext.load_cert_chain(certfile, keyfile, password) |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
44 sslcontext.verify_mode = cert_reqs |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
45 if ca_certs is not None: |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
46 sslcontext.load_verify_locations(cafile=ca_certs) |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
47 elif _canloaddefaultcerts: |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
48 sslcontext.load_default_certs() |
23834
bf07c19b4c82
https: support tls sni (server name indication) for https urls (issue3090)
Alex Orange <crazycasta@gmail.com>
parents:
23069
diff
changeset
|
49 |
25431
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
50 sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname) |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
51 # check if wrap_socket failed silently because socket had been |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
52 # closed |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
53 # - see http://bugs.python.org/issue13721 |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
54 if not sslsocket.cipher(): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
55 raise error.Abort(_('ssl connection failed')) |
25431
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
56 return sslsocket |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
57 except AttributeError: |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
58 def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE, |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
59 ca_certs=None, serverhostname=None): |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
60 sslsocket = ssl.wrap_socket(sock, keyfile, certfile, |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
61 cert_reqs=cert_reqs, ca_certs=ca_certs, |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
62 ssl_version=ssl.PROTOCOL_TLSv1) |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
63 # check if wrap_socket failed silently because socket had been |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
64 # closed |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
65 # - see http://bugs.python.org/issue13721 |
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
66 if not sslsocket.cipher(): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
67 raise error.Abort(_('ssl connection failed')) |
25431
96159068c506
ssl: drop try-except clause that was necessary for ancient Python
Yuya Nishihara <yuya@tcha.org>
parents:
25430
diff
changeset
|
68 return sslsocket |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
69 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
70 def _verifycert(cert, hostname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
71 '''Verify that cert (in socket.getpeercert() format) matches hostname. |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
72 CRLs is not handled. |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
73 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
74 Returns error message if any problems are found and None on success. |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
75 ''' |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
76 if not cert: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
77 return _('no certificate received') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
78 dnsname = hostname.lower() |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
79 def matchdnsname(certname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
80 return (certname == dnsname or |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
81 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]) |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
82 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
83 san = cert.get('subjectAltName', []) |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
84 if san: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
85 certnames = [value.lower() for key, value in san if key == 'DNS'] |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
86 for name in certnames: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
87 if matchdnsname(name): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
88 return None |
14666
27b080aa880a
sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798)
Nicolas Bareil <nico@chdir.org>
parents:
14616
diff
changeset
|
89 if certnames: |
27b080aa880a
sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798)
Nicolas Bareil <nico@chdir.org>
parents:
14616
diff
changeset
|
90 return _('certificate is for %s') % ', '.join(certnames) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
91 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
92 # subject is only checked when subjectAltName is empty |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
93 for s in cert.get('subject', []): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
94 key, value = s[0] |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
95 if key == 'commonName': |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
96 try: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
97 # 'subject' entries are unicode |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
98 certname = value.lower().encode('ascii') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
99 except UnicodeEncodeError: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
100 return _('IDN in certificate not supported') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
101 if matchdnsname(certname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
102 return None |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
103 return _('certificate is for %s') % certname |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
104 return _('no commonName or subjectAltName found in certificate') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
105 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
106 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
107 # CERT_REQUIRED means fetch the cert from the server all the time AND |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
108 # validate it against the CA store provided in web.cacerts. |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
109 |
23042
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
110 def _plainapplepython(): |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
111 """return true if this seems to be a pure Apple Python that |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
112 * is unfrozen and presumably has the whole mercurial module in the file |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
113 system |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
114 * presumably is an Apple Python that uses Apple OpenSSL which has patches |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
115 for using system certificate store CAs in addition to the provided |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
116 cacerts file |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
117 """ |
24614
241d98d84aed
ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents:
24291
diff
changeset
|
118 if sys.platform != 'darwin' or util.mainfrozen() or not sys.executable: |
23042
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
119 return False |
24614
241d98d84aed
ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents:
24291
diff
changeset
|
120 exe = os.path.realpath(sys.executable).lower() |
23042
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
121 return (exe.startswith('/usr/bin/python') or |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
122 exe.startswith('/system/library/frameworks/python.framework/')) |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
123 |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
124 def _defaultcacerts(): |
24291
760a86865f80
ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents:
24290
diff
changeset
|
125 """return path to CA certificates; None for system's store; ! to disable""" |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
126 if _plainapplepython(): |
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
127 dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem') |
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
128 if os.path.exists(dummycert): |
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
129 return dummycert |
24291
760a86865f80
ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents:
24290
diff
changeset
|
130 if _canloaddefaultcerts: |
760a86865f80
ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents:
24290
diff
changeset
|
131 return None |
24290
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
132 return '!' |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
133 |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
134 def sslkwargs(ui, host): |
25415
21b536f01eda
ssl: prompt passphrase of client key file via ui.getpass() (issue4648)
Yuya Nishihara <yuya@tcha.org>
parents:
24614
diff
changeset
|
135 kws = {'ui': ui} |
22574
a00a7951b20c
ssl: refactor sslkwargs - move things around a bit, preparing for next change
Mads Kiilerich <madski@unity3d.com>
parents:
19808
diff
changeset
|
136 hostfingerprint = ui.config('hostfingerprints', host) |
a00a7951b20c
ssl: refactor sslkwargs - move things around a bit, preparing for next change
Mads Kiilerich <madski@unity3d.com>
parents:
19808
diff
changeset
|
137 if hostfingerprint: |
a00a7951b20c
ssl: refactor sslkwargs - move things around a bit, preparing for next change
Mads Kiilerich <madski@unity3d.com>
parents:
19808
diff
changeset
|
138 return kws |
a00a7951b20c
ssl: refactor sslkwargs - move things around a bit, preparing for next change
Mads Kiilerich <madski@unity3d.com>
parents:
19808
diff
changeset
|
139 cacerts = ui.config('web', 'cacerts') |
24290
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
140 if cacerts == '!': |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
141 pass |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
142 elif cacerts: |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
143 cacerts = util.expandpath(cacerts) |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
144 if not os.path.exists(cacerts): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
145 raise error.Abort(_('could not find web.cacerts: %s') % cacerts) |
24290
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
146 else: |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
147 cacerts = _defaultcacerts() |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
148 if cacerts and cacerts != '!': |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
149 ui.debug('using %s to enable OS X system CA\n' % cacerts) |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
150 ui.setconfig('web', 'cacerts', cacerts, 'defaultcacerts') |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
151 if cacerts != '!': |
19806
47ff9d1abfa9
sslutil: add a config knob to support TLS (default) or SSLv23 (bc) (issue4038)
Augie Fackler <raf@durin42.com>
parents:
19749
diff
changeset
|
152 kws.update({'ca_certs': cacerts, |
25432
bdc15b3c9bdb
ssl: remove CERT_REQUIRED constant that was necessary for compatibility
Yuya Nishihara <yuya@tcha.org>
parents:
25431
diff
changeset
|
153 'cert_reqs': ssl.CERT_REQUIRED, |
19806
47ff9d1abfa9
sslutil: add a config knob to support TLS (default) or SSLv23 (bc) (issue4038)
Augie Fackler <raf@durin42.com>
parents:
19749
diff
changeset
|
154 }) |
47ff9d1abfa9
sslutil: add a config knob to support TLS (default) or SSLv23 (bc) (issue4038)
Augie Fackler <raf@durin42.com>
parents:
19749
diff
changeset
|
155 return kws |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
156 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
157 class validator(object): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
158 def __init__(self, ui, host): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
159 self.ui = ui |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
160 self.host = host |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
161 |
18887
2d7fac049d3a
sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18879
diff
changeset
|
162 def __call__(self, sock, strict=False): |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
163 host = self.host |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
164 cacerts = self.ui.config('web', 'cacerts') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
165 hostfingerprint = self.ui.config('hostfingerprints', host) |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
166 |
15816
4bb59919c905
sslutil: work around validator crash getting certificate on failed sockets
Mads Kiilerich <mads@kiilerich.com>
parents:
15815
diff
changeset
|
167 if not sock.cipher(): # work around http://bugs.python.org/issue13721 |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
168 raise error.Abort(_('%s ssl connection error') % host) |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
169 try: |
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
170 peercert = sock.getpeercert(True) |
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
171 peercert2 = sock.getpeercert() |
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
172 except AttributeError: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
173 raise error.Abort(_('%s ssl connection error') % host) |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
174 |
15817
8f377751b510
sslutil: abort properly if no certificate received for https connection
Mads Kiilerich <mads@kiilerich.com>
parents:
15816
diff
changeset
|
175 if not peercert: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
176 raise error.Abort(_('%s certificate error: ' |
15817
8f377751b510
sslutil: abort properly if no certificate received for https connection
Mads Kiilerich <mads@kiilerich.com>
parents:
15816
diff
changeset
|
177 'no certificate received') % host) |
15814
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
178 peerfingerprint = util.sha1(peercert).hexdigest() |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
179 nicefingerprint = ":".join([peerfingerprint[x:x + 2] |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
180 for x in xrange(0, len(peerfingerprint), 2)]) |
15815
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
181 if hostfingerprint: |
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
182 if peerfingerprint.lower() != \ |
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
183 hostfingerprint.replace(':', '').lower(): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
184 raise error.Abort(_('certificate for %s has unexpected ' |
15997
a45516cb8d9f
sslutil: more helpful fingerprint mismatch message
Matt Mackall <mpm@selenic.com>
parents:
15817
diff
changeset
|
185 'fingerprint %s') % (host, nicefingerprint), |
a45516cb8d9f
sslutil: more helpful fingerprint mismatch message
Matt Mackall <mpm@selenic.com>
parents:
15817
diff
changeset
|
186 hint=_('check hostfingerprint configuration')) |
15815
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
187 self.ui.debug('%s certificate matched fingerprint %s\n' % |
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
188 (host, nicefingerprint)) |
24290
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
189 elif cacerts != '!': |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
190 msg = _verifycert(peercert2, host) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
191 if msg: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
192 raise error.Abort(_('%s certificate error: %s') % (host, msg), |
15814
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
193 hint=_('configure hostfingerprint %s or use ' |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
194 '--insecure to connect insecurely') % |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
195 nicefingerprint) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
196 self.ui.debug('%s certificate successfully verified\n' % host) |
18887
2d7fac049d3a
sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18879
diff
changeset
|
197 elif strict: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
198 raise error.Abort(_('%s certificate with fingerprint %s not ' |
18887
2d7fac049d3a
sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18879
diff
changeset
|
199 'verified') % (host, nicefingerprint), |
2d7fac049d3a
sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18879
diff
changeset
|
200 hint=_('check hostfingerprints or web.cacerts ' |
2d7fac049d3a
sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18879
diff
changeset
|
201 'config setting')) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
202 else: |
15815
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
203 self.ui.warn(_('warning: %s certificate with fingerprint %s not ' |
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
204 'verified (check hostfingerprints or web.cacerts ' |
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
205 'config setting)\n') % |
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
206 (host, nicefingerprint)) |