author | Jun Wu <quark@fb.com> |
Sat, 12 Mar 2016 04:24:11 +0000 | |
changeset 28536 | a979f5b03320 |
parent 28525 | dfb21c34e07d |
child 28577 | 7efff6ce9826 |
permissions | -rw-r--r-- |
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) |
27688
6c7d26cef0cd
sslutil: fix reversed logic (issue5034)
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
26622
diff
changeset
|
38 |
sslcontext.options |= ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 |
25431
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') |
28525
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
165 |
hostfingerprints = self.ui.configlist('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)]) |
28525
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
181 |
if hostfingerprints: |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
182 |
fingerprintmatch = False |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
183 |
for hostfingerprint in hostfingerprints: |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
184 |
if peerfingerprint.lower() == \ |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
185 |
hostfingerprint.replace(':', '').lower(): |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
186 |
fingerprintmatch = True |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
187 |
break |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
188 |
if not fingerprintmatch: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
189 |
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
|
190 |
'fingerprint %s') % (host, nicefingerprint), |
a45516cb8d9f
sslutil: more helpful fingerprint mismatch message
Matt Mackall <mpm@selenic.com>
parents:
15817
diff
changeset
|
191 |
hint=_('check hostfingerprint configuration')) |
15815
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
192 |
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
|
193 |
(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
|
194 |
elif cacerts != '!': |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
195 |
msg = _verifycert(peercert2, host) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
196 |
if msg: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
197 |
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
|
198 |
hint=_('configure hostfingerprint %s or use ' |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
199 |
'--insecure to connect insecurely') % |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
200 |
nicefingerprint) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
201 |
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
|
202 |
elif strict: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
203 |
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
|
204 |
'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
|
205 |
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
|
206 |
'config setting')) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
207 |
else: |
15815
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
208 |
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
|
209 |
'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
|
210 |
'config setting)\n') % |
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
211 |
(host, nicefingerprint)) |