Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/sslutil.py @ 28849:1fde84d42f9c
sslutil: require a server hostname when wrapping sockets (API)
All callers appear to be passing the hostname. So this shouldn't
break anything. By specifying the hostname, more validation options
from the ssl module are available to us. Although this patch stops
short of using them.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sun, 10 Apr 2016 11:00:41 -0700 |
parents | e330db205b20 |
children | 3819c349b194 |
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 _ |
28577
7efff6ce9826
sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28525
diff
changeset
|
17 from . import ( |
7efff6ce9826
sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28525
diff
changeset
|
18 error, |
7efff6ce9826
sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28525
diff
changeset
|
19 util, |
7efff6ce9826
sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28525
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 |
28647
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
22 # Python 2.7.9+ overhauled the built-in SSL/TLS features of Python. It added |
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
23 # support for TLS 1.1, TLS 1.2, SNI, system CA stores, etc. These features are |
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
24 # all exposed via the "ssl" module. |
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
25 # |
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
26 # Depending on the version of Python being used, SSL/TLS support is either |
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
27 # modern/secure or legacy/insecure. Many operations in this module have |
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
28 # separate code paths depending on support in Python. |
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
29 |
26622
9e15286609ae
sslutil: expose attribute indicating whether SNI is supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26587
diff
changeset
|
30 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
|
31 |
28648
7fc787e5d8ec
sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28647
diff
changeset
|
32 try: |
7fc787e5d8ec
sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28647
diff
changeset
|
33 OP_NO_SSLv2 = ssl.OP_NO_SSLv2 |
7fc787e5d8ec
sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28647
diff
changeset
|
34 OP_NO_SSLv3 = ssl.OP_NO_SSLv3 |
7fc787e5d8ec
sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28647
diff
changeset
|
35 except AttributeError: |
7fc787e5d8ec
sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28647
diff
changeset
|
36 OP_NO_SSLv2 = 0x1000000 |
7fc787e5d8ec
sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28647
diff
changeset
|
37 OP_NO_SSLv3 = 0x2000000 |
7fc787e5d8ec
sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28647
diff
changeset
|
38 |
28649
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
39 try: |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
40 # ssl.SSLContext was added in 2.7.9 and presence indicates modern |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
41 # SSL/TLS features are available. |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
42 SSLContext = ssl.SSLContext |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
43 modernssl = True |
28650
737863b01d9f
sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28649
diff
changeset
|
44 _canloaddefaultcerts = util.safehasattr(SSLContext, 'load_default_certs') |
28649
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
45 except AttributeError: |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
46 modernssl = False |
28650
737863b01d9f
sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28649
diff
changeset
|
47 _canloaddefaultcerts = False |
28649
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
48 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
49 # We implement SSLContext using the interface from the standard library. |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
50 class SSLContext(object): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
51 # ssl.wrap_socket gained the "ciphers" named argument in 2.7. |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
52 _supportsciphers = sys.version_info >= (2, 7) |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
53 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
54 def __init__(self, protocol): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
55 # From the public interface of SSLContext |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
56 self.protocol = protocol |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
57 self.check_hostname = False |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
58 self.options = 0 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
59 self.verify_mode = ssl.CERT_NONE |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
60 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
61 # Used by our implementation. |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
62 self._certfile = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
63 self._keyfile = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
64 self._certpassword = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
65 self._cacerts = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
66 self._ciphers = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
67 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
68 def load_cert_chain(self, certfile, keyfile=None, password=None): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
69 self._certfile = certfile |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
70 self._keyfile = keyfile |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
71 self._certpassword = password |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
72 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
73 def load_default_certs(self, purpose=None): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
74 pass |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
75 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
76 def load_verify_locations(self, cafile=None, capath=None, cadata=None): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
77 if capath: |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
78 raise error.Abort('capath not supported') |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
79 if cadata: |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
80 raise error.Abort('cadata not supported') |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
81 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
82 self._cacerts = cafile |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
83 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
84 def set_ciphers(self, ciphers): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
85 if not self._supportsciphers: |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
86 raise error.Abort('setting ciphers not supported') |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
87 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
88 self._ciphers = ciphers |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
89 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
90 def wrap_socket(self, socket, server_hostname=None, server_side=False): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
91 # server_hostname is unique to SSLContext.wrap_socket and is used |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
92 # for SNI in that context. So there's nothing for us to do with it |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
93 # in this legacy code since we don't support SNI. |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
94 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
95 args = { |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
96 'keyfile': self._keyfile, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
97 'certfile': self._certfile, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
98 'server_side': server_side, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
99 'cert_reqs': self.verify_mode, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
100 'ssl_version': self.protocol, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
101 'ca_certs': self._cacerts, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
102 } |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
103 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
104 if self._supportsciphers: |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
105 args['ciphers'] = self._ciphers |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
106 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
107 return ssl.wrap_socket(socket, **args) |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
108 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
109 def wrapsocket(sock, keyfile, certfile, ui, cert_reqs=ssl.CERT_NONE, |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
110 ca_certs=None, serverhostname=None): |
28653
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
111 """Add SSL/TLS to a socket. |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
112 |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
113 This is a glorified wrapper for ``ssl.wrap_socket()``. It makes sane |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
114 choices based on what security options are available. |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
115 |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
116 In addition to the arguments supported by ``ssl.wrap_socket``, we allow |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
117 the following additional arguments: |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
118 |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
119 * serverhostname - The expected hostname of the remote server. If the |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
120 server (and client) support SNI, this tells the server which certificate |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
121 to use. |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
122 """ |
28849
1fde84d42f9c
sslutil: require a server hostname when wrapping sockets (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28848
diff
changeset
|
123 if not serverhostname: |
1fde84d42f9c
sslutil: require a server hostname when wrapping sockets (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28848
diff
changeset
|
124 raise error.Abort('serverhostname argument required') |
1fde84d42f9c
sslutil: require a server hostname when wrapping sockets (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28848
diff
changeset
|
125 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
126 # Despite its name, PROTOCOL_SSLv23 selects the highest protocol |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
127 # that both ends support, including TLS protocols. On legacy stacks, |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
128 # the highest it likely goes in TLS 1.0. On modern stacks, it can |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
129 # support TLS 1.2. |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
130 # |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
131 # The PROTOCOL_TLSv* constants select a specific TLS version |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
132 # only (as opposed to multiple versions). So the method for |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
133 # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
134 # disable protocols via SSLContext.options and OP_NO_* constants. |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
135 # However, SSLContext.options doesn't work unless we have the |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
136 # full/real SSLContext available to us. |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
137 # |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
138 # SSLv2 and SSLv3 are broken. We ban them outright. |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
139 if modernssl: |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
140 protocol = ssl.PROTOCOL_SSLv23 |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
141 else: |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
142 protocol = ssl.PROTOCOL_TLSv1 |
28651
4827d07073e6
sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28650
diff
changeset
|
143 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
144 # TODO use ssl.create_default_context() on modernssl. |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
145 sslcontext = SSLContext(protocol) |
28651
4827d07073e6
sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28650
diff
changeset
|
146 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
147 # This is a no-op on old Python. |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
148 sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3 |
28651
4827d07073e6
sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28650
diff
changeset
|
149 |
28848
e330db205b20
sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28653
diff
changeset
|
150 # This still works on our fake SSLContext. |
e330db205b20
sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28653
diff
changeset
|
151 sslcontext.verify_mode = cert_reqs |
e330db205b20
sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28653
diff
changeset
|
152 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
153 if certfile is not None: |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
154 def password(): |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
155 f = keyfile or certfile |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
156 return ui.getpass(_('passphrase for %s: ') % f, '') |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
157 sslcontext.load_cert_chain(certfile, keyfile, password) |
28848
e330db205b20
sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28653
diff
changeset
|
158 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
159 if ca_certs is not None: |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
160 sslcontext.load_verify_locations(cafile=ca_certs) |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
161 else: |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
162 # This is a no-op on old Python. |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
163 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
|
164 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
165 sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname) |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
166 # check if wrap_socket failed silently because socket had been |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
167 # closed |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
168 # - see http://bugs.python.org/issue13721 |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
169 if not sslsocket.cipher(): |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
170 raise error.Abort(_('ssl connection failed')) |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
171 return sslsocket |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
172 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
173 def _verifycert(cert, hostname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
174 '''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
|
175 CRLs is not handled. |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
176 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
177 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
|
178 ''' |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
179 if not cert: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
180 return _('no certificate received') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
181 dnsname = hostname.lower() |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
182 def matchdnsname(certname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
183 return (certname == dnsname or |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
184 '.' 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
|
185 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
186 san = cert.get('subjectAltName', []) |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
187 if san: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
188 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
|
189 for name in certnames: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
190 if matchdnsname(name): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
191 return None |
14666
27b080aa880a
sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798)
Nicolas Bareil <nico@chdir.org>
parents:
14616
diff
changeset
|
192 if certnames: |
27b080aa880a
sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798)
Nicolas Bareil <nico@chdir.org>
parents:
14616
diff
changeset
|
193 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
|
194 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
195 # 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
|
196 for s in cert.get('subject', []): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
197 key, value = s[0] |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
198 if key == 'commonName': |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
199 try: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
200 # 'subject' entries are unicode |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
201 certname = value.lower().encode('ascii') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
202 except UnicodeEncodeError: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
203 return _('IDN in certificate not supported') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
204 if matchdnsname(certname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
205 return None |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
206 return _('certificate is for %s') % certname |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
207 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
|
208 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
209 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
210 # 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
|
211 # 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
|
212 |
23042
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
213 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
|
214 """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
|
215 * 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
|
216 system |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
217 * 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
|
218 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
|
219 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
|
220 """ |
24614
241d98d84aed
ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents:
24291
diff
changeset
|
221 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
|
222 return False |
24614
241d98d84aed
ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents:
24291
diff
changeset
|
223 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
|
224 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
|
225 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
|
226 |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
227 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
|
228 """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
|
229 if _plainapplepython(): |
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
230 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
|
231 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
|
232 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
|
233 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
|
234 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
|
235 return '!' |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
236 |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
237 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
|
238 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
|
239 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
|
240 if hostfingerprint: |
a00a7951b20c
ssl: refactor sslkwargs - move things around a bit, preparing for next change
Mads Kiilerich <madski@unity3d.com>
parents:
19808
diff
changeset
|
241 return kws |
a00a7951b20c
ssl: refactor sslkwargs - move things around a bit, preparing for next change
Mads Kiilerich <madski@unity3d.com>
parents:
19808
diff
changeset
|
242 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
|
243 if cacerts == '!': |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
244 pass |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
245 elif cacerts: |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
246 cacerts = util.expandpath(cacerts) |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
247 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
|
248 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
|
249 else: |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
250 cacerts = _defaultcacerts() |
b76d8c641746
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)
Yuya Nishihara <yuya@tcha.org>
parents:
24288
diff
changeset
|
251 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
|
252 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
|
253 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
|
254 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
|
255 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
|
256 '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
|
257 }) |
47ff9d1abfa9
sslutil: add a config knob to support TLS (default) or SSLv23 (bc) (issue4038)
Augie Fackler <raf@durin42.com>
parents:
19749
diff
changeset
|
258 return kws |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
259 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
260 class validator(object): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
261 def __init__(self, ui, host): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
262 self.ui = ui |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
263 self.host = host |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
264 |
18887
2d7fac049d3a
sslutil: abort if peer certificate is not verified for secure use
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18879
diff
changeset
|
265 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
|
266 host = self.host |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
267 cacerts = self.ui.config('web', 'cacerts') |
28525
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
268 hostfingerprints = self.ui.configlist('hostfingerprints', host) |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
269 |
15816
4bb59919c905
sslutil: work around validator crash getting certificate on failed sockets
Mads Kiilerich <mads@kiilerich.com>
parents:
15815
diff
changeset
|
270 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
|
271 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
|
272 try: |
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
273 peercert = sock.getpeercert(True) |
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
274 peercert2 = sock.getpeercert() |
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
275 except AttributeError: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
276 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
|
277 |
15817
8f377751b510
sslutil: abort properly if no certificate received for https connection
Mads Kiilerich <mads@kiilerich.com>
parents:
15816
diff
changeset
|
278 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
|
279 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
|
280 'no certificate received') % host) |
15814
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
281 peerfingerprint = util.sha1(peercert).hexdigest() |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
282 nicefingerprint = ":".join([peerfingerprint[x:x + 2] |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
283 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
|
284 if hostfingerprints: |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
285 fingerprintmatch = False |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
286 for hostfingerprint in hostfingerprints: |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
287 if peerfingerprint.lower() == \ |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
288 hostfingerprint.replace(':', '').lower(): |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
289 fingerprintmatch = True |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
290 break |
dfb21c34e07d
sslutil: allow multiple fingerprints per host
Gregory Szorc <gregory.szorc@gmail.com>
parents:
27688
diff
changeset
|
291 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
|
292 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
|
293 'fingerprint %s') % (host, nicefingerprint), |
a45516cb8d9f
sslutil: more helpful fingerprint mismatch message
Matt Mackall <mpm@selenic.com>
parents:
15817
diff
changeset
|
294 hint=_('check hostfingerprint configuration')) |
15815
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
295 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
|
296 (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
|
297 elif cacerts != '!': |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
298 msg = _verifycert(peercert2, host) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
299 if msg: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
300 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
|
301 hint=_('configure hostfingerprint %s or use ' |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
302 '--insecure to connect insecurely') % |
c3e958b50a22
sslutil: show fingerprint when cacerts validation fails
Mads Kiilerich <mads@kiilerich.com>
parents:
15813
diff
changeset
|
303 nicefingerprint) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
304 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
|
305 elif strict: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25977
diff
changeset
|
306 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
|
307 '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
|
308 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
|
309 'config setting')) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
310 else: |
15815
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
311 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
|
312 '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
|
313 'config setting)\n') % |
edc3a901a63d
sslutil: reorder validator code to make it more readable
Mads Kiilerich <mads@kiilerich.com>
parents:
15814
diff
changeset
|
314 (host, nicefingerprint)) |