Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/sslutil.py @ 29561:1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Mercurial now requires TLS 1.1+ when TLS 1.1+ is supported by the
client. Since we made the decision to require TLS 1.1+ when running
with modern Python versions, it makes sense to do something for
legacy Python versions that only support TLS 1.0.
Feature parity would be to prevent TLS 1.0 connections out of the
box and require a config option to enable them. However, this is
extremely user hostile since Mercurial wouldn't talk to https://
by default in these installations! I can easily see how someone
would do something foolish like use "--insecure" instead - and
that would be worse than allowing TLS 1.0!
This patch takes the compromise position of printing a warning when
performing TLS 1.0 connections when running on old Python
versions. While this warning is no more annoying than the
CA certificate / fingerprint warnings in Mercurial 3.8, we provide
a config option to disable the warning because to many people
upgrading Python to make the warning go away is not an available
recourse (unlike pinning fingerprints is for the CA warning).
The warning appears as optional output in a lot of tests.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 13 Jul 2016 21:49:17 -0700 |
parents | 303e9300772a |
children | 9654ef41f7cc |
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 |
29341
0d83ad967bf8
cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents:
29334
diff
changeset
|
12 import hashlib |
25977
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
13 import os |
29452
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
14 import re |
25977
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
15 import ssl |
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
16 import sys |
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
17 |
696f6e2be282
sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25432
diff
changeset
|
18 from .i18n import _ |
28577
7efff6ce9826
sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28525
diff
changeset
|
19 from . import ( |
7efff6ce9826
sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28525
diff
changeset
|
20 error, |
7efff6ce9826
sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28525
diff
changeset
|
21 util, |
7efff6ce9826
sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28525
diff
changeset
|
22 ) |
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
|
23 |
28647
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
24 # 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
|
25 # 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
|
26 # 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
|
27 # |
834d1c4ba749
sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28577
diff
changeset
|
28 # 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
|
29 # 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
|
30 # 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
|
31 |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
32 configprotocols = set([ |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
33 'tls1.0', |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
34 'tls1.1', |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
35 'tls1.2', |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
36 ]) |
26622
9e15286609ae
sslutil: expose attribute indicating whether SNI is supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
26587
diff
changeset
|
37 |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
38 hassni = getattr(ssl, 'HAS_SNI', False) |
28648
7fc787e5d8ec
sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28647
diff
changeset
|
39 |
28649
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
40 try: |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
41 # 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
|
42 # SSL/TLS features are available. |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
43 SSLContext = ssl.SSLContext |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
44 modernssl = True |
28650
737863b01d9f
sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28649
diff
changeset
|
45 _canloaddefaultcerts = util.safehasattr(SSLContext, 'load_default_certs') |
28649
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
46 except AttributeError: |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
47 modernssl = False |
28650
737863b01d9f
sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28649
diff
changeset
|
48 _canloaddefaultcerts = False |
28649
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
49 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
50 # 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
|
51 class SSLContext(object): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
52 # 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
|
53 _supportsciphers = sys.version_info >= (2, 7) |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
54 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
55 def __init__(self, protocol): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
56 # From the public interface of SSLContext |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
57 self.protocol = protocol |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
58 self.check_hostname = False |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
59 self.options = 0 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
60 self.verify_mode = ssl.CERT_NONE |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
61 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
62 # Used by our implementation. |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
63 self._certfile = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
64 self._keyfile = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
65 self._certpassword = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
66 self._cacerts = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
67 self._ciphers = None |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
68 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
69 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
|
70 self._certfile = certfile |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
71 self._keyfile = keyfile |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
72 self._certpassword = password |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
73 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
74 def load_default_certs(self, purpose=None): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
75 pass |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
76 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
77 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
|
78 if capath: |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
29341
diff
changeset
|
79 raise error.Abort(_('capath not supported')) |
28649
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
80 if cadata: |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
29341
diff
changeset
|
81 raise error.Abort(_('cadata not supported')) |
28649
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
82 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
83 self._cacerts = cafile |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
84 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
85 def set_ciphers(self, ciphers): |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
86 if not self._supportsciphers: |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
29341
diff
changeset
|
87 raise error.Abort(_('setting ciphers not supported')) |
28649
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
88 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
89 self._ciphers = ciphers |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
90 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
91 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
|
92 # 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
|
93 # 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
|
94 # 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
|
95 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
96 args = { |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
97 'keyfile': self._keyfile, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
98 'certfile': self._certfile, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
99 'server_side': server_side, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
100 'cert_reqs': self.verify_mode, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
101 'ssl_version': self.protocol, |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
102 'ca_certs': self._cacerts, |
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 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
105 if self._supportsciphers: |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
106 args['ciphers'] = self._ciphers |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
107 |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
108 return ssl.wrap_socket(socket, **args) |
7acab42ef184
sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28648
diff
changeset
|
109 |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
110 def _hostsettings(ui, hostname): |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
111 """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
|
112 |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
113 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
|
114 """ |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
115 s = { |
29288
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
116 # 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
|
117 # 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
|
118 'allowloaddefaultcerts': True, |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
119 # 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
|
120 'certfingerprints': [], |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
121 # 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
|
122 # SSLContext.load_verify_locations(). |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
123 'cafile': None, |
29287
fbccb334efe7
sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29286
diff
changeset
|
124 # 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
|
125 'disablecertverification': False, |
29268
f200b58497f1
sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29267
diff
changeset
|
126 # 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
|
127 'legacyfingerprint': False, |
29507
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
128 # PROTOCOL_* constant to use for SSLContext.__init__. |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
129 'protocol': None, |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
130 # 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
|
131 'verifymode': None, |
29508
d65ec41b6384
sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29507
diff
changeset
|
132 # Defines extra ssl.OP* bitwise options to set. |
d65ec41b6384
sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29507
diff
changeset
|
133 'ctxoptions': None, |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
134 } |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
135 |
29507
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
136 # Despite its name, PROTOCOL_SSLv23 selects the highest protocol |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
137 # that both ends support, including TLS protocols. On legacy stacks, |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
138 # the highest it likely goes is TLS 1.0. On modern stacks, it can |
29507
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
139 # support TLS 1.2. |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
140 # |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
141 # The PROTOCOL_TLSv* constants select a specific TLS version |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
142 # only (as opposed to multiple versions). So the method for |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
143 # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
144 # disable protocols via SSLContext.options and OP_NO_* constants. |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
145 # However, SSLContext.options doesn't work unless we have the |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
146 # full/real SSLContext available to us. |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
147 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
148 # Allow minimum TLS protocol to be specified in the config. |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
149 def validateprotocol(protocol, key): |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
150 if protocol not in configprotocols: |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
151 raise error.Abort( |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
152 _('unsupported protocol from hostsecurity.%s: %s') % |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
153 (key, protocol), |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
154 hint=_('valid protocols: %s') % |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
155 ' '.join(sorted(configprotocols))) |
29507
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
156 |
29560
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
157 # Legacy Python can only do TLS 1.0. We default to TLS 1.1+ where we |
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
158 # can because TLS 1.0 has known vulnerabilities (like BEAST and POODLE). |
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
159 # We allow users to downgrade to TLS 1.0+ via config options in case a |
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
160 # legacy server is encountered. |
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
161 if modernssl: |
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
162 defaultprotocol = 'tls1.1' |
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
163 else: |
29561
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
164 # Let people on legacy Python versions know they are borderline |
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
165 # secure. |
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
166 # We don't document this config option because we want people to see |
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
167 # the bold warnings on the web site. |
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
168 # internal config: hostsecurity.disabletls10warning |
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
169 if not ui.configbool('hostsecurity', 'disabletls10warning'): |
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
170 ui.warn(_('warning: connecting to %s using legacy security ' |
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
171 'technology (TLS 1.0); see ' |
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
172 'https://mercurial-scm.org/wiki/SecureConnections for ' |
1a782fabf80d
sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29560
diff
changeset
|
173 'more info\n') % hostname) |
29560
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
174 defaultprotocol = 'tls1.0' |
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
175 |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
176 key = 'minimumprotocol' |
29560
303e9300772a
sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29559
diff
changeset
|
177 protocol = ui.config('hostsecurity', key, defaultprotocol) |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
178 validateprotocol(protocol, key) |
29508
d65ec41b6384
sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29507
diff
changeset
|
179 |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
180 key = '%s:minimumprotocol' % hostname |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
181 protocol = ui.config('hostsecurity', key, protocol) |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
182 validateprotocol(protocol, key) |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
183 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
184 s['protocol'], s['ctxoptions'] = protocolsettings(protocol) |
29558
a935cd7d51a6
sslutil: prevent CRIME
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29557
diff
changeset
|
185 |
29267
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
186 # 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
|
187 # of <alg>:<fingerprint> strings. |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
188 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
|
189 []) |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
190 for fingerprint in fingerprints: |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
191 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
|
192 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
|
193 hostname, fingerprint), |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
194 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
|
195 'or "sha512:"')) |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
196 |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
197 alg, fingerprint = fingerprint.split(':', 1) |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
198 fingerprint = fingerprint.replace(':', '').lower() |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
199 s['certfingerprints'].append((alg, fingerprint)) |
f0ccb6cde3e5
sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29262
diff
changeset
|
200 |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
201 # 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
|
202 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
|
203 fingerprint = fingerprint.replace(':', '').lower() |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
204 s['certfingerprints'].append(('sha1', fingerprint)) |
29268
f200b58497f1
sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29267
diff
changeset
|
205 s['legacyfingerprint'] = True |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
206 |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
207 # 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
|
208 # 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
|
209 if s['certfingerprints']: |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
210 s['verifymode'] = ssl.CERT_NONE |
29447
13edc11eb7b7
sslutil: don't load default certificates when they aren't relevant
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29446
diff
changeset
|
211 s['allowloaddefaultcerts'] = False |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
212 |
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
213 # 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
|
214 elif ui.insecureconnections: |
29287
fbccb334efe7
sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29286
diff
changeset
|
215 s['disablecertverification'] = True |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
216 s['verifymode'] = ssl.CERT_NONE |
29447
13edc11eb7b7
sslutil: don't load default certificates when they aren't relevant
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29446
diff
changeset
|
217 s['allowloaddefaultcerts'] = False |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
218 |
29288
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
219 if ui.configbool('devel', 'disableloaddefaultcerts'): |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
220 s['allowloaddefaultcerts'] = False |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
221 |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
222 # 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
|
223 # 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
|
224 # being performed. |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
225 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
|
226 if s['certfingerprints'] and cafile: |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
227 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
|
228 '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
|
229 'verification)\n') % hostname) |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
230 |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
231 # 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
|
232 # makes it not necessary. |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
233 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
|
234 # 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
|
235 if cafile: |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
236 cafile = util.expandpath(cafile) |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
237 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
|
238 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
|
239 ('hostsecurity.%s:verifycertsfile' % hostname, |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
240 cafile)) |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
241 s['cafile'] = cafile |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
242 else: |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
243 # 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
|
244 cafile = ui.config('web', 'cacerts') |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
245 |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
246 if cafile: |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
247 cafile = util.expandpath(cafile) |
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
248 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
|
249 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
|
250 cafile) |
29484
53b7fc7cc2bb
sslutil: don't attempt to find default CA certs file when told not to
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29483
diff
changeset
|
251 elif s['allowloaddefaultcerts']: |
29482
4e72995f6c9c
sslutil: change comment and logged message for found ca cert file
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29459
diff
changeset
|
252 # CAs not defined in config. Try to find system bundles. |
29483
918dce4b8c26
sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29482
diff
changeset
|
253 cafile = _defaultcacerts(ui) |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
254 if cafile: |
29482
4e72995f6c9c
sslutil: change comment and logged message for found ca cert file
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29459
diff
changeset
|
255 ui.debug('using %s for CA file\n' % cafile) |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
256 |
29334
ecc9b788fd69
sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29293
diff
changeset
|
257 s['cafile'] = cafile |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
258 |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
259 # 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
|
260 # 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
|
261 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
|
262 s['verifymode'] = ssl.CERT_REQUIRED |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
263 else: |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
264 # 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
|
265 # explicitly insecure, and can't load CA certs. Connecting |
29411
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
266 # is insecure. We allow the connection and abort during |
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
267 # validation (once we have the fingerprint to print to the |
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
268 # user). |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
269 s['verifymode'] = ssl.CERT_NONE |
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
270 |
29507
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
271 assert s['protocol'] is not None |
29508
d65ec41b6384
sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29507
diff
changeset
|
272 assert s['ctxoptions'] is not None |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
273 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
|
274 |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
275 return s |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
276 |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
277 def protocolsettings(protocol): |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
278 """Resolve the protocol and context options for a config value.""" |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
279 if protocol not in configprotocols: |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
280 raise ValueError('protocol value not supported: %s' % protocol) |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
281 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
282 # Legacy ssl module only supports up to TLS 1.0. Ideally we'd use |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
283 # PROTOCOL_SSLv23 and options to disable SSLv2 and SSLv3. However, |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
284 # SSLContext.options doesn't work in our implementation since we use |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
285 # a fake SSLContext on these Python versions. |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
286 if not modernssl: |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
287 if protocol != 'tls1.0': |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
288 raise error.Abort(_('current Python does not support protocol ' |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
289 'setting %s') % protocol, |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
290 hint=_('upgrade Python or disable setting since ' |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
291 'only TLS 1.0 is supported')) |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
292 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
293 return ssl.PROTOCOL_TLSv1, 0 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
294 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
295 # WARNING: returned options don't work unless the modern ssl module |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
296 # is available. Be careful when adding options here. |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
297 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
298 # SSLv2 and SSLv3 are broken. We ban them outright. |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
299 options = ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
300 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
301 if protocol == 'tls1.0': |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
302 # Defaults above are to use TLS 1.0+ |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
303 pass |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
304 elif protocol == 'tls1.1': |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
305 options |= ssl.OP_NO_TLSv1 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
306 elif protocol == 'tls1.2': |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
307 options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
308 else: |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
309 raise error.Abort(_('this should not happen')) |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
310 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
311 # Prevent CRIME. |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
312 # There is no guarantee this attribute is defined on the module. |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
313 options |= getattr(ssl, 'OP_NO_COMPRESSION', 0) |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
314 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
315 return ssl.PROTOCOL_SSLv23, options |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
316 |
29249
cca59ef27e60
sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
317 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
|
318 """Add SSL/TLS to a socket. |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
319 |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
320 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
|
321 choices based on what security options are available. |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
322 |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
323 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
|
324 the following additional arguments: |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
325 |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
326 * 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
|
327 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
|
328 to use. |
1eb0bd8adf39
sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28652
diff
changeset
|
329 """ |
29224
7424f4294199
sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29115
diff
changeset
|
330 if not serverhostname: |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
29341
diff
changeset
|
331 raise error.Abort(_('serverhostname argument is required')) |
29224
7424f4294199
sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29115
diff
changeset
|
332 |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
333 settings = _hostsettings(ui, serverhostname) |
29249
cca59ef27e60
sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
334 |
29557
53de8255ec4e
sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29554
diff
changeset
|
335 # We can't use ssl.create_default_context() because it calls |
53de8255ec4e
sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29554
diff
changeset
|
336 # load_default_certs() unless CA arguments are passed to it. We want to |
53de8255ec4e
sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29554
diff
changeset
|
337 # have explicit control over CA loading because implicitly loading |
53de8255ec4e
sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29554
diff
changeset
|
338 # CAs may undermine the user's intent. For example, a user may define a CA |
53de8255ec4e
sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29554
diff
changeset
|
339 # bundle with a specific CA cert removed. If the system/default CA bundle |
53de8255ec4e
sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29554
diff
changeset
|
340 # is loaded and contains that removed CA, you've just undone the user's |
53de8255ec4e
sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29554
diff
changeset
|
341 # choice. |
29507
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
342 sslcontext = SSLContext(settings['protocol']) |
97dcdcf75f4f
sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29501
diff
changeset
|
343 |
29508
d65ec41b6384
sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29507
diff
changeset
|
344 # This is a no-op unless using modern ssl. |
d65ec41b6384
sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29507
diff
changeset
|
345 sslcontext.options |= settings['ctxoptions'] |
28651
4827d07073e6
sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28650
diff
changeset
|
346 |
28848
e330db205b20
sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28653
diff
changeset
|
347 # 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
|
348 sslcontext.verify_mode = settings['verifymode'] |
28848
e330db205b20
sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28653
diff
changeset
|
349 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
350 if certfile is not None: |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
351 def password(): |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
352 f = keyfile or certfile |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
353 return ui.getpass(_('passphrase for %s: ') % f, '') |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
354 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
|
355 |
29260
70bc9912d83d
sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29259
diff
changeset
|
356 if settings['cafile'] is not None: |
29446
2f7f1e10f840
sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29411
diff
changeset
|
357 try: |
2f7f1e10f840
sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29411
diff
changeset
|
358 sslcontext.load_verify_locations(cafile=settings['cafile']) |
2f7f1e10f840
sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29411
diff
changeset
|
359 except ssl.SSLError as e: |
2f7f1e10f840
sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29411
diff
changeset
|
360 raise error.Abort(_('error loading CA file %s: %s') % ( |
2f7f1e10f840
sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29411
diff
changeset
|
361 settings['cafile'], e.args[1]), |
2f7f1e10f840
sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29411
diff
changeset
|
362 hint=_('file is empty or malformed?')) |
29113
5b9577edf745
sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29112
diff
changeset
|
363 caloaded = True |
29288
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
364 elif settings['allowloaddefaultcerts']: |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
365 # 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
|
366 sslcontext.load_default_certs() |
29288
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
367 caloaded = True |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
368 else: |
7dee15dee53c
sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29287
diff
changeset
|
369 caloaded = False |
23834
bf07c19b4c82
https: support tls sni (server name indication) for https urls (issue3090)
Alex Orange <crazycasta@gmail.com>
parents:
23069
diff
changeset
|
370 |
29449
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
371 try: |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
372 sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname) |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
373 except ssl.SSLError as e: |
29449
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
374 # If we're doing certificate verification and no CA certs are loaded, |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
375 # that is almost certainly the reason why verification failed. Provide |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
376 # a hint to the user. |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
377 # Only modern ssl module exposes SSLContext.get_ca_certs() so we can |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
378 # only show this warning if modern ssl is available. |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
379 if (caloaded and settings['verifymode'] == ssl.CERT_REQUIRED and |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
380 modernssl and not sslcontext.get_ca_certs()): |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
381 ui.warn(_('(an attempt was made to load CA certificates but none ' |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
382 'were loaded; see ' |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
383 'https://mercurial-scm.org/wiki/SecureConnections for ' |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
384 'how to configure Mercurial to avoid this error)\n')) |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
385 # Try to print more helpful error messages for known failures. |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
386 if util.safehasattr(e, 'reason'): |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
387 if e.reason == 'UNSUPPORTED_PROTOCOL': |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
388 ui.warn(_('(could not negotiate a common protocol; see ' |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
389 'https://mercurial-scm.org/wiki/SecureConnections ' |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
390 'for how to configure Mercurial to avoid this ' |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
391 'error)\n')) |
29449
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
392 raise |
5b71a8d7f7ff
sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29447
diff
changeset
|
393 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
394 # 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
|
395 # closed |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
396 # - see http://bugs.python.org/issue13721 |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
397 if not sslsocket.cipher(): |
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
398 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
|
399 |
29225
b115eed11780
sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29224
diff
changeset
|
400 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
|
401 'caloaded': caloaded, |
29226
33006bd6a1d7
sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29225
diff
changeset
|
402 'hostname': serverhostname, |
29259
ec247e8595f9
sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29258
diff
changeset
|
403 'settings': settings, |
29226
33006bd6a1d7
sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29225
diff
changeset
|
404 '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
|
405 } |
29113
5b9577edf745
sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29112
diff
changeset
|
406 |
28652
c617614aefd2
sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28651
diff
changeset
|
407 return sslsocket |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
408 |
29554
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
409 def wrapserversocket(sock, ui, certfile=None, keyfile=None, cafile=None, |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
410 requireclientcert=False): |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
411 """Wrap a socket for use by servers. |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
412 |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
413 ``certfile`` and ``keyfile`` specify the files containing the certificate's |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
414 public and private keys, respectively. Both keys can be defined in the same |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
415 file via ``certfile`` (the private key must come first in the file). |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
416 |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
417 ``cafile`` defines the path to certificate authorities. |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
418 |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
419 ``requireclientcert`` specifies whether to require client certificates. |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
420 |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
421 Typically ``cafile`` is only defined if ``requireclientcert`` is true. |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
422 """ |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
423 protocol, options = protocolsettings('tls1.0') |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
424 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
425 # This config option is intended for use in tests only. It is a giant |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
426 # footgun to kill security. Don't define it. |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
427 exactprotocol = ui.config('devel', 'serverexactprotocol') |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
428 if exactprotocol == 'tls1.0': |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
429 protocol = ssl.PROTOCOL_TLSv1 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
430 elif exactprotocol == 'tls1.1': |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
431 protocol = ssl.PROTOCOL_TLSv1_1 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
432 elif exactprotocol == 'tls1.2': |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
433 protocol = ssl.PROTOCOL_TLSv1_2 |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
434 elif exactprotocol: |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
435 raise error.Abort(_('invalid value for serverexactprotocol: %s') % |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
436 exactprotocol) |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
437 |
29554
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
438 if modernssl: |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
439 # We /could/ use create_default_context() here since it doesn't load |
29559
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
440 # CAs when configured for client auth. However, it is hard-coded to |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
441 # use ssl.PROTOCOL_SSLv23 which may not be appropriate here. |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
442 sslcontext = SSLContext(protocol) |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
443 sslcontext.options |= options |
7dec5e441bf7
sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29558
diff
changeset
|
444 |
29554
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
445 # Improve forward secrecy. |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
446 sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0) |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
447 sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0) |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
448 |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
449 # Use the list of more secure ciphers if found in the ssl module. |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
450 if util.safehasattr(ssl, '_RESTRICTED_SERVER_CIPHERS'): |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
451 sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0) |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
452 sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS) |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
453 else: |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
454 sslcontext = SSLContext(ssl.PROTOCOL_TLSv1) |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
455 |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
456 if requireclientcert: |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
457 sslcontext.verify_mode = ssl.CERT_REQUIRED |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
458 else: |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
459 sslcontext.verify_mode = ssl.CERT_NONE |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
460 |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
461 if certfile or keyfile: |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
462 sslcontext.load_cert_chain(certfile=certfile, keyfile=keyfile) |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
463 |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
464 if cafile: |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
465 sslcontext.load_verify_locations(cafile=cafile) |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
466 |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
467 return sslcontext.wrap_socket(sock, server_side=True) |
4a7b0c696fbc
sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29537
diff
changeset
|
468 |
29452
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
469 class wildcarderror(Exception): |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
470 """Represents an error parsing wildcards in DNS name.""" |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
471 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
472 def _dnsnamematch(dn, hostname, maxwildcards=1): |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
473 """Match DNS names according RFC 6125 section 6.4.3. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
474 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
475 This code is effectively copied from CPython's ssl._dnsname_match. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
476 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
477 Returns a bool indicating whether the expected hostname matches |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
478 the value in ``dn``. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
479 """ |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
480 pats = [] |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
481 if not dn: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
482 return False |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
483 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
484 pieces = dn.split(r'.') |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
485 leftmost = pieces[0] |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
486 remainder = pieces[1:] |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
487 wildcards = leftmost.count('*') |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
488 if wildcards > maxwildcards: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
489 raise wildcarderror( |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
490 _('too many wildcards in certificate DNS name: %s') % dn) |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
491 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
492 # speed up common case w/o wildcards |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
493 if not wildcards: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
494 return dn.lower() == hostname.lower() |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
495 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
496 # RFC 6125, section 6.4.3, subitem 1. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
497 # The client SHOULD NOT attempt to match a presented identifier in which |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
498 # the wildcard character comprises a label other than the left-most label. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
499 if leftmost == '*': |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
500 # When '*' is a fragment by itself, it matches a non-empty dotless |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
501 # fragment. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
502 pats.append('[^.]+') |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
503 elif leftmost.startswith('xn--') or hostname.startswith('xn--'): |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
504 # RFC 6125, section 6.4.3, subitem 3. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
505 # The client SHOULD NOT attempt to match a presented identifier |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
506 # where the wildcard character is embedded within an A-label or |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
507 # U-label of an internationalized domain name. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
508 pats.append(re.escape(leftmost)) |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
509 else: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
510 # Otherwise, '*' matches any dotless string, e.g. www* |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
511 pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
512 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
513 # add the remaining fragments, ignore any wildcards |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
514 for frag in remainder: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
515 pats.append(re.escape(frag)) |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
516 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
517 pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
518 return pat.match(hostname) is not None |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
519 |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
520 def _verifycert(cert, hostname): |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
521 '''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
|
522 CRLs is not handled. |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
523 |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
524 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
|
525 ''' |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
526 if not cert: |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
527 return _('no certificate received') |
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
528 |
29452
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
529 dnsnames = [] |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
530 san = cert.get('subjectAltName', []) |
29452
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
531 for key, value in san: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
532 if key == 'DNS': |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
533 try: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
534 if _dnsnamematch(value, hostname): |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
535 return |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
536 except wildcarderror as e: |
29460
a7d1532b26a1
sslutil: don't access message attribute in exception (issue5285)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29452
diff
changeset
|
537 return e.args[0] |
29452
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
538 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
539 dnsnames.append(value) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
540 |
29452
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
541 if not dnsnames: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
542 # The subject is only checked when there is no DNS in subjectAltName. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
543 for sub in cert.get('subject', []): |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
544 for key, value in sub: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
545 # According to RFC 2818 the most specific Common Name must |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
546 # be used. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
547 if key == 'commonName': |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
548 # 'subject' entries are unicide. |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
549 try: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
550 value = value.encode('ascii') |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
551 except UnicodeEncodeError: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
552 return _('IDN in certificate not supported') |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
553 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
554 try: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
555 if _dnsnamematch(value, hostname): |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
556 return |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
557 except wildcarderror as e: |
29460
a7d1532b26a1
sslutil: don't access message attribute in exception (issue5285)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29452
diff
changeset
|
558 return e.args[0] |
29452
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
559 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
560 dnsnames.append(value) |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
561 |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
562 if len(dnsnames) > 1: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
563 return _('certificate is for %s') % ', '.join(dnsnames) |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
564 elif len(dnsnames) == 1: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
565 return _('certificate is for %s') % dnsnames[0] |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
566 else: |
26a5d605b868
sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29042
diff
changeset
|
567 return _('no commonName or subjectAltName found in certificate') |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
568 |
23042
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
569 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
|
570 """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
|
571 * 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
|
572 system |
2cd3fa4412dc
ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents:
22575
diff
changeset
|
573 * 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
|
574 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
|
575 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
|
576 """ |
24614
241d98d84aed
ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents:
24291
diff
changeset
|
577 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
|
578 return False |
24614
241d98d84aed
ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents:
24291
diff
changeset
|
579 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
|
580 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
|
581 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
|
582 |
29500
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
583 _systemcacertpaths = [ |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
584 # RHEL, CentOS, and Fedora |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
585 '/etc/pki/tls/certs/ca-bundle.trust.crt', |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
586 # Debian, Ubuntu, Gentoo |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
587 '/etc/ssl/certs/ca-certificates.crt', |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
588 ] |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
589 |
29483
918dce4b8c26
sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29482
diff
changeset
|
590 def _defaultcacerts(ui): |
29488
1c26b9ce66f8
sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29487
diff
changeset
|
591 """return path to default CA certificates or None. |
1c26b9ce66f8
sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29487
diff
changeset
|
592 |
1c26b9ce66f8
sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29487
diff
changeset
|
593 It is assumed this function is called when the returned certificates |
1c26b9ce66f8
sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29487
diff
changeset
|
594 file will actually be used to validate connections. Therefore this |
1c26b9ce66f8
sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29487
diff
changeset
|
595 function may print warnings or debug messages assuming this usage. |
29500
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
596 |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
597 We don't print a message when the Python is able to load default |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
598 CA certs because this scenario is detected at socket connect time. |
29488
1c26b9ce66f8
sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29487
diff
changeset
|
599 """ |
29486
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
600 # The "certifi" Python package provides certificates. If it is installed, |
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
601 # assume the user intends it to be used and use it. |
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
602 try: |
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
603 import certifi |
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
604 certs = certifi.where() |
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
605 ui.debug('using ca certificates from certifi\n') |
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
606 return certs |
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
607 except ImportError: |
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
608 pass |
a62c00f6dd04
sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29484
diff
changeset
|
609 |
29489
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
610 # On Windows, only the modern ssl module is capable of loading the system |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
611 # CA certificates. If we're not capable of doing that, emit a warning |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
612 # because we'll get a certificate verification error later and the lack |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
613 # of loaded CA certificates will be the reason why. |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
614 # Assertion: this code is only called if certificates are being verified. |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
615 if os.name == 'nt': |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
616 if not _canloaddefaultcerts: |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
617 ui.warn(_('(unable to load Windows CA certificates; see ' |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
618 'https://mercurial-scm.org/wiki/SecureConnections for ' |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
619 'how to configure Mercurial to avoid this message)\n')) |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
620 |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
621 return None |
54ad81b0665f
sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29488
diff
changeset
|
622 |
29487
cdcb5747dc88
sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29486
diff
changeset
|
623 # Apple's OpenSSL has patches that allow a specially constructed certificate |
cdcb5747dc88
sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29486
diff
changeset
|
624 # to load the system CA store. If we're running on Apple Python, use this |
cdcb5747dc88
sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29486
diff
changeset
|
625 # trick. |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
626 if _plainapplepython(): |
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
627 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
|
628 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
|
629 return dummycert |
29107
c8fbfb9163ce
sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29106
diff
changeset
|
630 |
29499
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
631 # The Apple OpenSSL trick isn't available to us. If Python isn't able to |
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
632 # load system certs, we're out of luck. |
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
633 if sys.platform == 'darwin': |
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
634 # FUTURE Consider looking for Homebrew or MacPorts installed certs |
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
635 # files. Also consider exporting the keychain certs to a file during |
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
636 # Mercurial install. |
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
637 if not _canloaddefaultcerts: |
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
638 ui.warn(_('(unable to load CA certificates; see ' |
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
639 'https://mercurial-scm.org/wiki/SecureConnections for ' |
9c5325c79683
sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29489
diff
changeset
|
640 'how to configure Mercurial to avoid this message)\n')) |
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
|
641 return None |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
642 |
29537
5f8b36d5a6ec
sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29508
diff
changeset
|
643 # / is writable on Windows. Out of an abundance of caution make sure |
5f8b36d5a6ec
sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29508
diff
changeset
|
644 # we're not on Windows because paths from _systemcacerts could be installed |
5f8b36d5a6ec
sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29508
diff
changeset
|
645 # by non-admin users. |
5f8b36d5a6ec
sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29508
diff
changeset
|
646 assert os.name != 'nt' |
5f8b36d5a6ec
sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29508
diff
changeset
|
647 |
29500
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
648 # Try to find CA certificates in well-known locations. We print a warning |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
649 # when using a found file because we don't want too much silent magic |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
650 # for security settings. The expectation is that proper Mercurial |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
651 # installs will have the CA certs path defined at install time and the |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
652 # installer/packager will make an appropriate decision on the user's |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
653 # behalf. We only get here and perform this setting as a feature of |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
654 # last resort. |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
655 if not _canloaddefaultcerts: |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
656 for path in _systemcacertpaths: |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
657 if os.path.isfile(path): |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
658 ui.warn(_('(using CA certificates from %s; if you see this ' |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
659 'message, your Mercurial install is not properly ' |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
660 'configured; see ' |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
661 'https://mercurial-scm.org/wiki/SecureConnections ' |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
662 'for how to configure Mercurial to avoid this ' |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
663 'message)\n') % path) |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
664 return path |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
665 |
29500
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
666 ui.warn(_('(unable to load CA certificates; see ' |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
667 'https://mercurial-scm.org/wiki/SecureConnections for ' |
4b16a5bd9948
sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29499
diff
changeset
|
668 'how to configure Mercurial to avoid this message)\n')) |
14204
5fa21960b2f4
sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
669 |
29107
c8fbfb9163ce
sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29106
diff
changeset
|
670 return None |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
671 |
29286
a05a91a3f120
sslutil: remove "strict" argument from validatesocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29268
diff
changeset
|
672 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
|
673 """Validate a socket meets security requiremnets. |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
674 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
675 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
|
676 """ |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
677 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
|
678 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
|
679 settings = sock._hgstate['settings'] |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
680 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
681 try: |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
682 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
|
683 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
|
684 except AttributeError: |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
685 raise error.Abort(_('%s ssl connection error') % host) |
24288
922e087ba158
ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents:
23851
diff
changeset
|
686 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
687 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
|
688 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
|
689 'no certificate received') % host) |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
690 |
29289
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
691 if settings['disablecertverification']: |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
692 # 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
|
693 # 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
|
694 # 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
|
695 # 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
|
696 # 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
|
697 # value. |
3536673a25ae
sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29288
diff
changeset
|
698 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
|
699 '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
|
700 '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
|
701 return |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
702 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
703 # 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
|
704 # validate the remote cert. |
29262
dfc4f08aa160
sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29260
diff
changeset
|
705 peerfingerprints = { |
29341
0d83ad967bf8
cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents:
29334
diff
changeset
|
706 'sha1': hashlib.sha1(peercert).hexdigest(), |
0d83ad967bf8
cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents:
29334
diff
changeset
|
707 'sha256': hashlib.sha256(peercert).hexdigest(), |
0d83ad967bf8
cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents:
29334
diff
changeset
|
708 'sha512': hashlib.sha512(peercert).hexdigest(), |
29262
dfc4f08aa160
sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29260
diff
changeset
|
709 } |
18879
93b03a222c3e
sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents:
16391
diff
changeset
|
710 |
29290
01248c37a68e
sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29289
diff
changeset
|
711 def fmtfingerprint(s): |
01248c37a68e
sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29289
diff
changeset
|
712 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
|
713 |
01248c37a68e
sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29289
diff
changeset
|
714 nicefingerprint = 'sha256:%s' % fmtfingerprint(peerfingerprints['sha256']) |
28850
3819c349b194
sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28849
diff
changeset
|
715 |
29258
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
716 if settings['certfingerprints']: |
6315c1e14f75
sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29253
diff
changeset
|
717 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
|
718 if peerfingerprints[hash].lower() == fingerprint: |
29291
15e533b7909c
sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29290
diff
changeset
|
719 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
|
720 (host, hash, fmtfingerprint(fingerprint))) |
15e533b7909c
sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29290
diff
changeset
|
721 return |
28850
3819c349b194
sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28849
diff
changeset
|
722 |
29293
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
723 # 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
|
724 if settings['legacyfingerprint']: |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
725 section = 'hostfingerprint' |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
726 nice = fmtfingerprint(peerfingerprints['sha1']) |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
727 else: |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
728 section = 'hostsecurity' |
1b3a0b0c414f
sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29292
diff
changeset
|
729 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
|
730 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
|
731 'fingerprint %s') % (host, nice), |
29291
15e533b7909c
sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29290
diff
changeset
|
732 hint=_('check %s configuration') % section) |
28850
3819c349b194
sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
28849
diff
changeset
|
733 |
29411
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
734 # Security is enabled but no CAs are loaded. We can't establish trust |
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
735 # for the cert so abort. |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
736 if not sock._hgstate['caloaded']: |
29411
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
737 raise error.Abort( |
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
738 _('unable to verify security of %s (no loaded CA certificates); ' |
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
739 'refusing to connect') % host, |
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
740 hint=_('see https://mercurial-scm.org/wiki/SecureConnections for ' |
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
741 'how to configure Mercurial to avoid this error or set ' |
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
742 'hostsecurity.%s:fingerprints=%s to trust this server') % |
e1778b9c8d53
sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29410
diff
changeset
|
743 (host, nicefingerprint)) |
29113
5b9577edf745
sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29112
diff
changeset
|
744 |
29227
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
745 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
|
746 if msg: |
dffe78d80a6c
sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29226
diff
changeset
|
747 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
|
748 hint=_('set hostsecurity.%s:certfingerprints=%s ' |
bc5f55493397
sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29291
diff
changeset
|
749 '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
|
750 'insecurely') % |
bc5f55493397
sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29291
diff
changeset
|
751 (host, nicefingerprint)) |