Mercurial > hg-stable
annotate mercurial/sslutil.py @ 29334:ecc9b788fd69
sslutil: per-host config option to define certificates
Recent work has introduced the [hostsecurity] config section for
defining per-host security settings. This patch builds on top
of this foundation and implements the ability to define a per-host
path to a file containing certificates used for verifying the server
certificate. It is logically a per-host web.cacerts setting.
This patch also introduces a warning when both per-host
certificates and fingerprints are defined. These are mutually
exclusive for host verification and I think the user should be
alerted when security settings are ambiguous because, well,
security is important.
Tests validating the new behavior have been added.
I decided against putting "ca" in the option name because a
non-CA certificate can be specified and used to validate the server
certificate (commonly this will be the exact public certificate
used by the server). It's worth noting that the underlying
Python API used is load_verify_locations(cafile=X) and it calls
into OpenSSL's SSL_CTX_load_verify_locations(). Even OpenSSL's
documentation seems to omit that the file can contain a non-CA
certificate if it matches the server's certificate exactly. I
thought a CA certificate was a special kind of x509 certificate.
Perhaps I'm wrong and any x509 certificate can be used as a
CA certificate [as far as OpenSSL is concerned]. In any case,
I thought it best to drop "ca" from the name because this reflects
reality.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 07 Jun 2016 20:29:54 -0700 |
parents | 1b3a0b0c414f |
children | 0d83ad967bf8 |
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 |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
109 def _hostsettings(ui, hostname): |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
110 """Obtain security settings for a hostname. |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
111 |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
112 Returns a dict of settings relevant to that hostname. |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
113 """ |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
114 s = { |
29288
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
115 # Whether we should attempt to load default/available CA certs |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
116 # if an explicit ``cafile`` is not defined. |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
117 'allowloaddefaultcerts': True, |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
118 # List of 2-tuple of (hash algorithm, hash). |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
119 'certfingerprints': [], |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
120 # Path to file containing concatenated CA certs. Used by |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
121 # SSLContext.load_verify_locations(). |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
122 'cafile': None, |
29287
fbccb334efe7
sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29286
diff
changeset
|
123 # Whether certificate verification should be disabled. |
fbccb334efe7
sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29286
diff
changeset
|
124 'disablecertverification': False, |
29268
f200b58497f1
sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29267
diff
changeset
|
125 # Whether the legacy [hostfingerprints] section has data for this host. |
f200b58497f1
sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29267
diff
changeset
|
126 'legacyfingerprint': False, |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
127 # ssl.CERT_* constant used by SSLContext.verify_mode. |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
128 'verifymode': None, |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
129 } |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
130 |
29267
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
131 # Look for fingerprints in [hostsecurity] section. Value is a list |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
132 # of <alg>:<fingerprint> strings. |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
133 fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname, |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
134 []) |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
135 for fingerprint in fingerprints: |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
136 if not (fingerprint.startswith(('sha1:', 'sha256:', 'sha512:'))): |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
137 raise error.Abort(_('invalid fingerprint for %s: %s') % ( |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
138 hostname, fingerprint), |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
139 hint=_('must begin with "sha1:", "sha256:", ' |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
140 'or "sha512:"')) |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
141 |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
142 alg, fingerprint = fingerprint.split(':', 1) |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
143 fingerprint = fingerprint.replace(':', '').lower() |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
144 s['certfingerprints'].append((alg, fingerprint)) |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
145 |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
146 # Fingerprints from [hostfingerprints] are always SHA-1. |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
147 for fingerprint in ui.configlist('hostfingerprints', hostname, []): |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
148 fingerprint = fingerprint.replace(':', '').lower() |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
149 s['certfingerprints'].append(('sha1', fingerprint)) |
29268
f200b58497f1
sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29267
diff
changeset
|
150 s['legacyfingerprint'] = True |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
151 |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
152 # If a host cert fingerprint is defined, it is the only thing that |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
153 # matters. No need to validate CA certs. |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
154 if s['certfingerprints']: |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
155 s['verifymode'] = ssl.CERT_NONE |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
156 |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
157 # If --insecure is used, don't take CAs into consideration. |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
158 elif ui.insecureconnections: |
29287
fbccb334efe7
sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29286
diff
changeset
|
159 s['disablecertverification'] = True |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
160 s['verifymode'] = ssl.CERT_NONE |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
161 |
29288
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
162 if ui.configbool('devel', 'disableloaddefaultcerts'): |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
163 s['allowloaddefaultcerts'] = False |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
164 |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
165 # If both fingerprints and a per-host ca file are specified, issue a warning |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
166 # because users should not be surprised about what security is or isn't |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
167 # being performed. |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
168 cafile = ui.config('hostsecurity', '%s:verifycertsfile' % hostname) |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
169 if s['certfingerprints'] and cafile: |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
170 ui.warn(_('(hostsecurity.%s:verifycertsfile ignored when host ' |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
171 'fingerprints defined; using host fingerprints for ' |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
172 'verification)\n') % hostname) |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
173 |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
174 # Try to hook up CA certificate validation unless something above |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
175 # makes it not necessary. |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
176 if s['verifymode'] is None: |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
177 # Look at per-host ca file first. |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
178 if cafile: |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
179 cafile = util.expandpath(cafile) |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
180 if not os.path.exists(cafile): |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
181 raise error.Abort(_('path specified by %s does not exist: %s') % |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
182 ('hostsecurity.%s:verifycertsfile' % hostname, |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
183 cafile)) |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
184 s['cafile'] = cafile |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
185 else: |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
186 # Find global certificates file in config. |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
187 cafile = ui.config('web', 'cacerts') |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
188 |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
189 if cafile: |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
190 cafile = util.expandpath(cafile) |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
191 if not os.path.exists(cafile): |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
192 raise error.Abort(_('could not find web.cacerts: %s') % |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
193 cafile) |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
194 else: |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
195 # No global CA certs. See if we can load defaults. |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
196 cafile = _defaultcacerts() |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
197 if cafile: |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
198 ui.debug('using %s to enable OS X system CA\n' % cafile) |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
199 |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
200 s['cafile'] = cafile |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
201 |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
202 # Require certificate validation if CA certs are being loaded and |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
203 # verification hasn't been disabled above. |
29288
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
204 if cafile or (_canloaddefaultcerts and s['allowloaddefaultcerts']): |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
205 s['verifymode'] = ssl.CERT_REQUIRED |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
206 else: |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
207 # At this point we don't have a fingerprint, aren't being |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
208 # explicitly insecure, and can't load CA certs. Connecting |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
209 # at this point is insecure. But we do it for BC reasons. |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
210 # TODO abort here to make secure by default. |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
211 s['verifymode'] = ssl.CERT_NONE |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
212 |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
213 assert s['verifymode'] is not None |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
214 |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
215 return s |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
216 |
29249
cca59ef27e60
sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
217 def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None): |
28653
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
218 """Add SSL/TLS to a socket. |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
219 |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
220 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
|
221 choices based on what security options are available. |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
222 |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
223 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
|
224 the following additional arguments: |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
225 |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
226 * 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
|
227 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
|
228 to use. |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
229 """ |
29224
7424f4294199
sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29115
diff
changeset
|
230 if not serverhostname: |
7424f4294199
sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29115
diff
changeset
|
231 raise error.Abort('serverhostname argument is required') |
7424f4294199
sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29115
diff
changeset
|
232 |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
233 settings = _hostsettings(ui, serverhostname) |
29249
cca59ef27e60
sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
234 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
235 # 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
|
236 # 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
|
237 # 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
|
238 # support TLS 1.2. |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
239 # |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
240 # 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
|
241 # 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
|
242 # 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
|
243 # 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
|
244 # 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
|
245 # full/real SSLContext available to us. |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
246 # |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
247 # 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
|
248 if modernssl: |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
249 protocol = ssl.PROTOCOL_SSLv23 |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
250 else: |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
251 protocol = ssl.PROTOCOL_TLSv1 |
28651
4827d07073e6
sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28650
diff
changeset
|
252 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
253 # 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
|
254 sslcontext = SSLContext(protocol) |
28651
4827d07073e6
sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28650
diff
changeset
|
255 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
256 # 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
|
257 sslcontext.options |= OP_NO_SSLv2 | OP_NO_SSLv3 |
28651
4827d07073e6
sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28650
diff
changeset
|
258 |
28848
e330db205b20
sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28653
diff
changeset
|
259 # This still works on our fake SSLContext. |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
260 sslcontext.verify_mode = settings['verifymode'] |
28848
e330db205b20
sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28653
diff
changeset
|
261 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
262 if certfile is not None: |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
263 def password(): |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
264 f = keyfile or certfile |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
265 return ui.getpass(_('passphrase for %s: ') % f, '') |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
266 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
|
267 |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
268 if settings['cafile'] is not None: |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
269 sslcontext.load_verify_locations(cafile=settings['cafile']) |
29113
5b9577edf745
sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29112
diff
changeset
|
270 caloaded = True |
29288
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
271 elif settings['allowloaddefaultcerts']: |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
272 # 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
|
273 sslcontext.load_default_certs() |
29288
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
274 caloaded = True |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
275 else: |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
276 caloaded = False |
23834
bf07c19b4c82
https: support tls sni (server name indication) for https urls (issue3090)
Alex Orange <crazycasta@gmail.com>
parents:
23069
diff
changeset
|
277 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
278 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
|
279 # 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
|
280 # closed |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
281 # - see http://bugs.python.org/issue13721 |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
282 if not sslsocket.cipher(): |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
283 raise error.Abort(_('ssl connection failed')) |
29113
5b9577edf745
sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29112
diff
changeset
|
284 |
29225
b115eed11780
sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29224
diff
changeset
|
285 sslsocket._hgstate = { |
b115eed11780
sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29224
diff
changeset
|
286 'caloaded': caloaded, |
29226
33006bd6a1d7
sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29225
diff
changeset
|
287 'hostname': serverhostname, |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
288 'settings': settings, |
29226
33006bd6a1d7
sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29225
diff
changeset
|
289 'ui': ui, |
29225
b115eed11780
sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29224
diff
changeset
|
290 } |
29113
5b9577edf745
sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29112
diff
changeset
|
291 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
292 return sslsocket |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
293 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
294 def _verifycert(cert, hostname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
295 '''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
|
296 CRLs is not handled. |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
297 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
298 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
|
299 ''' |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
300 if not cert: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
301 return _('no certificate received') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
302 dnsname = hostname.lower() |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
303 def matchdnsname(certname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
304 return (certname == dnsname or |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
305 '.' 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
|
306 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
307 san = cert.get('subjectAltName', []) |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
308 if san: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
309 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
|
310 for name in certnames: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
311 if matchdnsname(name): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
312 return None |
14666
27b080aa880a
sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798)
Nicolas Bareil <nico@chdir.org>
parents:
14616
diff
changeset
|
313 if certnames: |
27b080aa880a
sslutil: fall back to commonName when no dNSName in subjectAltName (issue2798)
Nicolas Bareil <nico@chdir.org>
parents:
14616
diff
changeset
|
314 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
|
315 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
316 # 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
|
317 for s in cert.get('subject', []): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
318 key, value = s[0] |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
319 if key == 'commonName': |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
320 try: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
321 # 'subject' entries are unicode |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
322 certname = value.lower().encode('ascii') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
323 except UnicodeEncodeError: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
324 return _('IDN in certificate not supported') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
325 if matchdnsname(certname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
326 return None |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
327 return _('certificate is for %s') % certname |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
328 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
|
329 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
330 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
331 # 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
|
332 # 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
|
333 |
23042
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
334 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
|
335 """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
|
336 * 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
|
337 system |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
338 * 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
|
339 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
|
340 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
|
341 """ |
24614
241d98d84aed
ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents:
24291
diff
changeset
|
342 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
|
343 return False |
24614
241d98d84aed
ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents:
24291
diff
changeset
|
344 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
|
345 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
|
346 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
|
347 |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
348 def _defaultcacerts(): |
29107
c8fbfb9163ce
sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29106
diff
changeset
|
349 """return path to default CA certificates or None.""" |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
350 if _plainapplepython(): |
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
351 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
|
352 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
|
353 return dummycert |
29107
c8fbfb9163ce
sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29106
diff
changeset
|
354 |
c8fbfb9163ce
sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29106
diff
changeset
|
355 return None |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
356 |
29286
a05a91a3f120
sslutil: remove "strict" argument from validatesocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29268
diff
changeset
|
357 def validatesocket(sock): |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
358 """Validate a socket meets security requiremnets. |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
359 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
360 The passed socket must have been created with ``wrapsocket()``. |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
361 """ |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
362 host = sock._hgstate['hostname'] |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
363 ui = sock._hgstate['ui'] |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
364 settings = sock._hgstate['settings'] |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
365 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
366 try: |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
367 peercert = sock.getpeercert(True) |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
368 peercert2 = sock.getpeercert() |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
369 except AttributeError: |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
370 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
|
371 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
372 if not peercert: |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
373 raise error.Abort(_('%s certificate error: ' |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
374 'no certificate received') % host) |
28850
3819c349b194
sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28849
diff
changeset
|
375 |
29289
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
376 if settings['disablecertverification']: |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
377 # We don't print the certificate fingerprint because it shouldn't |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
378 # be necessary: if the user requested certificate verification be |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
379 # disabled, they presumably already saw a message about the inability |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
380 # to verify the certificate and this message would have printed the |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
381 # fingerprint. So printing the fingerprint here adds little to no |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
382 # value. |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
383 ui.warn(_('warning: connection security to %s is disabled per current ' |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
384 'settings; communication is susceptible to eavesdropping ' |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
385 'and tampering\n') % host) |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
386 return |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
387 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
388 # If a certificate fingerprint is pinned, use it and only it to |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
389 # validate the remote cert. |
29262
dfc4f08aa160
sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29260
diff
changeset
|
390 peerfingerprints = { |
dfc4f08aa160
sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29260
diff
changeset
|
391 'sha1': util.sha1(peercert).hexdigest(), |
dfc4f08aa160
sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29260
diff
changeset
|
392 'sha256': util.sha256(peercert).hexdigest(), |
dfc4f08aa160
sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29260
diff
changeset
|
393 'sha512': util.sha512(peercert).hexdigest(), |
dfc4f08aa160
sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29260
diff
changeset
|
394 } |
29290
01248c37a68e
sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29289
diff
changeset
|
395 |
01248c37a68e
sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29289
diff
changeset
|
396 def fmtfingerprint(s): |
01248c37a68e
sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29289
diff
changeset
|
397 return ':'.join([s[x:x + 2] for x in range(0, len(s), 2)]) |
01248c37a68e
sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29289
diff
changeset
|
398 |
01248c37a68e
sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29289
diff
changeset
|
399 nicefingerprint = 'sha256:%s' % fmtfingerprint(peerfingerprints['sha256']) |
29262
dfc4f08aa160
sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29260
diff
changeset
|
400 |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
401 if settings['certfingerprints']: |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
402 for hash, fingerprint in settings['certfingerprints']: |
29262
dfc4f08aa160
sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29260
diff
changeset
|
403 if peerfingerprints[hash].lower() == fingerprint: |
29291
15e533b7909c
sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29290
diff
changeset
|
404 ui.debug('%s certificate matched fingerprint %s:%s\n' % |
15e533b7909c
sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29290
diff
changeset
|
405 (host, hash, fmtfingerprint(fingerprint))) |
15e533b7909c
sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29290
diff
changeset
|
406 return |
15e533b7909c
sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29290
diff
changeset
|
407 |
29293
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
408 # Pinned fingerprint didn't match. This is a fatal error. |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
409 if settings['legacyfingerprint']: |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
410 section = 'hostfingerprint' |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
411 nice = fmtfingerprint(peerfingerprints['sha1']) |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
412 else: |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
413 section = 'hostsecurity' |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
414 nice = '%s:%s' % (hash, fmtfingerprint(peerfingerprints[hash])) |
29291
15e533b7909c
sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29290
diff
changeset
|
415 raise error.Abort(_('certificate for %s has unexpected ' |
29293
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
416 'fingerprint %s') % (host, nice), |
29291
15e533b7909c
sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29290
diff
changeset
|
417 hint=_('check %s configuration') % section) |
28850
3819c349b194
sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28849
diff
changeset
|
418 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
419 if not sock._hgstate['caloaded']: |
29292
bc5f55493397
sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29291
diff
changeset
|
420 ui.warn(_('warning: certificate for %s not verified ' |
bc5f55493397
sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29291
diff
changeset
|
421 '(set hostsecurity.%s:certfingerprints=%s or web.cacerts ' |
bc5f55493397
sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29291
diff
changeset
|
422 'config settings)\n') % (host, host, nicefingerprint)) |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
423 return |
29113
5b9577edf745
sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29112
diff
changeset
|
424 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
425 msg = _verifycert(peercert2, host) |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
426 if msg: |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
427 raise error.Abort(_('%s certificate error: %s') % (host, msg), |
29292
bc5f55493397
sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29291
diff
changeset
|
428 hint=_('set hostsecurity.%s:certfingerprints=%s ' |
bc5f55493397
sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29291
diff
changeset
|
429 'config setting or use --insecure to connect ' |
bc5f55493397
sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29291
diff
changeset
|
430 'insecurely') % |
bc5f55493397
sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29291
diff
changeset
|
431 (host, nicefingerprint)) |