annotate mercurial/sslutil.py @ 32805:2b0fc56840d0

profile: use explicit logic to control file closing We make the decision to close 'fp' more explicit instead of relying on the implication of other variable. This makes the overall logic more robust.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 12 Jun 2017 17:14:56 +0200
parents bd872f64a8ba
children 3bdbbadddecc
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
17 from .i18n import _
28577
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
18 from . import (
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
19 error,
30639
d524c88511a7 py3: replace os.name with pycompat.osname (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
20 pycompat,
28577
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
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
diff changeset
32 configprotocols = {
29559
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',
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
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
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
40 # TLS 1.1 and 1.2 may not be supported if the OpenSSL Python is compiled
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
41 # against doesn't support them.
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
diff changeset
42 supportedprotocols = {'tls1.0'}
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
43 if util.safehasattr(ssl, 'PROTOCOL_TLSv1_1'):
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
44 supportedprotocols.add('tls1.1')
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
45 if util.safehasattr(ssl, 'PROTOCOL_TLSv1_2'):
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
46 supportedprotocols.add('tls1.2')
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
47
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
48 try:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
49 # 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
50 # SSL/TLS features are available.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
51 SSLContext = ssl.SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
52 modernssl = True
28650
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28649
diff changeset
53 _canloaddefaultcerts = util.safehasattr(SSLContext, 'load_default_certs')
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
54 except AttributeError:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
55 modernssl = False
28650
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28649
diff changeset
56 _canloaddefaultcerts = False
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
57
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
58 # 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
59 class SSLContext(object):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
60 def __init__(self, protocol):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
61 # From the public interface of SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
62 self.protocol = protocol
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
63 self.check_hostname = False
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
64 self.options = 0
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
65 self.verify_mode = ssl.CERT_NONE
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
66
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
67 # Used by our implementation.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
68 self._certfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
69 self._keyfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
70 self._certpassword = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
71 self._cacerts = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
72 self._ciphers = None
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_cert_chain(self, certfile, keyfile=None, password=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
75 self._certfile = certfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
76 self._keyfile = keyfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
77 self._certpassword = password
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
78
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
79 def load_default_certs(self, purpose=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
80 pass
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
81
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
82 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
83 if capath:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
84 raise error.Abort(_('capath not supported'))
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
85 if cadata:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
86 raise error.Abort(_('cadata not supported'))
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
87
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
88 self._cacerts = cafile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
89
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
90 def set_ciphers(self, ciphers):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
91 self._ciphers = ciphers
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
92
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
93 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
94 # 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
95 # 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
96 # 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
97
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
98 args = {
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
99 'keyfile': self._keyfile,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
100 'certfile': self._certfile,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
101 'server_side': server_side,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
102 'cert_reqs': self.verify_mode,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
103 'ssl_version': self.protocol,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
104 'ca_certs': self._cacerts,
32247
e05cfb4a6a8e sslutil: remove conditional cipher code needed for Python 2.6
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32194
diff changeset
105 'ciphers': self._ciphers,
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
106 }
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
107
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,
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
130 # String representation of minimum protocol to be used for UI
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
131 # presentation.
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
132 'protocolui': None,
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
133 # 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
134 'verifymode': None,
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
135 # 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
136 'ctxoptions': None,
29577
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
137 # OpenSSL Cipher List to use (instead of default).
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
138 'ciphers': None,
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
139 }
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
140
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
141 # 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
142 def validateprotocol(protocol, key):
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
143 if protocol not in configprotocols:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
144 raise error.Abort(
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
145 _('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
146 (key, protocol),
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
147 hint=_('valid protocols: %s') %
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
148 ' '.join(sorted(configprotocols)))
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
149
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
150 # We default to TLS 1.1+ where we can because TLS 1.0 has known
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
151 # vulnerabilities (like BEAST and POODLE). We allow users to downgrade to
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
152 # TLS 1.0+ via config options in case a legacy server is encountered.
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
153 if 'tls1.1' in supportedprotocols:
29560
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
154 defaultprotocol = 'tls1.1'
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
155 else:
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
156 # Let people know they are borderline secure.
29561
1a782fabf80d sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29560
diff changeset
157 # 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
158 # 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
159 # 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
160 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
161 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
162 '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
163 '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
164 'more info\n') % hostname)
29560
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
165 defaultprotocol = 'tls1.0'
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
166
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
167 key = 'minimumprotocol'
29560
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29559
diff changeset
168 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
169 validateprotocol(protocol, key)
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
170
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
171 key = '%s:minimumprotocol' % hostname
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
172 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
173 validateprotocol(protocol, key)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
174
29617
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
175 # If --insecure is used, we allow the use of TLS 1.0 despite config options.
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
176 # We always print a "connection security to %s is disabled..." message when
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
177 # --insecure is used. So no need to print anything more here.
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
178 if ui.insecureconnections:
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
179 protocol = 'tls1.0'
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29601
diff changeset
180
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
181 s['protocol'], s['ctxoptions'], s['protocolui'] = protocolsettings(protocol)
29558
a935cd7d51a6 sslutil: prevent CRIME
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29557
diff changeset
182
29577
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
183 ciphers = ui.config('hostsecurity', 'ciphers')
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
184 ciphers = ui.config('hostsecurity', '%s:ciphers' % hostname, ciphers)
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
185 s['ciphers'] = ciphers
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
186
29267
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
187 # 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
188 # of <alg>:<fingerprint> strings.
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
189 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
190 [])
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
191 for fingerprint in fingerprints:
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
192 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
193 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
194 hostname, fingerprint),
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
195 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
196 'or "sha512:"'))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
197
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
198 alg, fingerprint = fingerprint.split(':', 1)
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
199 fingerprint = fingerprint.replace(':', '').lower()
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
200 s['certfingerprints'].append((alg, fingerprint))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
201
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
202 # 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
203 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
204 fingerprint = fingerprint.replace(':', '').lower()
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
205 s['certfingerprints'].append(('sha1', fingerprint))
29268
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29267
diff changeset
206 s['legacyfingerprint'] = True
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
207
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
208 # 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
209 # 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
210 if s['certfingerprints']:
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
211 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
212 s['allowloaddefaultcerts'] = False
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
213
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
214 # 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
215 elif ui.insecureconnections:
29287
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29286
diff changeset
216 s['disablecertverification'] = True
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
217 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
218 s['allowloaddefaultcerts'] = False
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
219
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
220 if ui.configbool('devel', 'disableloaddefaultcerts'):
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
221 s['allowloaddefaultcerts'] = False
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
222
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
223 # 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
224 # 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
225 # being performed.
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
226 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
227 if s['certfingerprints'] and cafile:
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
228 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
229 '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
230 'verification)\n') % hostname)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
231
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
232 # 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
233 # makes it not necessary.
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
234 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
235 # 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
236 if cafile:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
237 cafile = util.expandpath(cafile)
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
238 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
239 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
240 ('hostsecurity.%s:verifycertsfile' % hostname,
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
241 cafile))
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
242 s['cafile'] = cafile
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
243 else:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
244 # 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
245 cafile = ui.config('web', 'cacerts')
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
246
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
247 if cafile:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
248 cafile = util.expandpath(cafile)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
249 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
250 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
251 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
252 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
253 # 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
254 cafile = _defaultcacerts(ui)
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
255 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
256 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
257
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
258 s['cafile'] = cafile
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
259
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
260 # 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
261 # 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
262 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
263 s['verifymode'] = ssl.CERT_REQUIRED
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
264 else:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
265 # 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
266 # 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
267 # 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
268 # 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
269 # user).
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
270 s['verifymode'] = ssl.CERT_NONE
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
271
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
272 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
273 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
274 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
275
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
276 return s
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
277
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
278 def protocolsettings(protocol):
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
279 """Resolve the protocol for a config value.
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
280
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
281 Returns a 3-tuple of (protocol, options, ui value) where the first
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
282 2 items are values used by SSLContext and the last is a string value
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
283 of the ``minimumprotocol`` config option equivalent.
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
284 """
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
285 if protocol not in configprotocols:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
286 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
287
29578
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
288 # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
289 # that both ends support, including TLS protocols. On legacy stacks,
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
290 # the highest it likely goes is TLS 1.0. On modern stacks, it can
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
291 # support TLS 1.2.
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
292 #
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
293 # The PROTOCOL_TLSv* constants select a specific TLS version
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
294 # only (as opposed to multiple versions). So the method for
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
295 # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
296 # disable protocols via SSLContext.options and OP_NO_* constants.
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
297 # However, SSLContext.options doesn't work unless we have the
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29577
diff changeset
298 # full/real SSLContext available to us.
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
diff changeset
299 if supportedprotocols == {'tls1.0'}:
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
300 if protocol != 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
301 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
302 'setting %s') % protocol,
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
303 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
304 '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
305
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
306 return ssl.PROTOCOL_TLSv1, 0, 'tls1.0'
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
307
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
308 # 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
309 # 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
310
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
311 # 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
312 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
313
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
314 if protocol == 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
315 # 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
316 pass
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
317 elif protocol == 'tls1.1':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
318 options |= ssl.OP_NO_TLSv1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
319 elif protocol == 'tls1.2':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
320 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
321 else:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
322 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
323
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
324 # Prevent CRIME.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
325 # 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
326 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
327
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
328 return ssl.PROTOCOL_SSLv23, options, protocol
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
329
29249
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29248
diff changeset
330 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
331 """Add SSL/TLS to a socket.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
332
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
333 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
334 choices based on what security options are available.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
335
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
336 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
337 the following additional arguments:
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
338
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
339 * 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
340 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
341 to use.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
342 """
29224
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29115
diff changeset
343 if not serverhostname:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
344 raise error.Abort(_('serverhostname argument is required'))
29224
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29115
diff changeset
345
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
346 settings = _hostsettings(ui, serverhostname)
29249
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29248
diff changeset
347
29557
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29554
diff changeset
348 # 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
349 # 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
350 # 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
351 # 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
352 # 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
353 # 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
354 # choice.
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
355 sslcontext = SSLContext(settings['protocol'])
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
356
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
357 # 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
358 sslcontext.options |= settings['ctxoptions']
28651
4827d07073e6 sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28650
diff changeset
359
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
360 # 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
361 sslcontext.verify_mode = settings['verifymode']
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
362
29577
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
363 if settings['ciphers']:
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
364 try:
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
365 sslcontext.set_ciphers(settings['ciphers'])
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
366 except ssl.SSLError as e:
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
367 raise error.Abort(_('could not set ciphers: %s') % e.args[0],
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
368 hint=_('change cipher string (%s) in config') %
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
369 settings['ciphers'])
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29561
diff changeset
370
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
371 if certfile is not None:
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
372 def password():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
373 f = keyfile or certfile
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
374 return ui.getpass(_('passphrase for %s: ') % f, '')
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
375 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
376
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
377 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
378 try:
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
379 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
380 except ssl.SSLError as e:
29927
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29631
diff changeset
381 if len(e.args) == 1: # pypy has different SSLError args
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29631
diff changeset
382 msg = e.args[0]
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29631
diff changeset
383 else:
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29631
diff changeset
384 msg = e.args[1]
29446
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
385 raise error.Abort(_('error loading CA file %s: %s') % (
29927
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29631
diff changeset
386 settings['cafile'], msg),
29446
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
387 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
388 caloaded = True
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
389 elif settings['allowloaddefaultcerts']:
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
390 # 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
391 sslcontext.load_default_certs()
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
392 caloaded = True
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
393 else:
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
394 caloaded = False
23834
bf07c19b4c82 https: support tls sni (server name indication) for https urls (issue3090)
Alex Orange <crazycasta@gmail.com>
parents: 23069
diff changeset
395
29449
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
396 try:
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
397 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
398 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
399 # 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
400 # 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
401 # a hint to the user.
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
402 # 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
403 # only show this warning if modern ssl is available.
31725
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 31290
diff changeset
404 # The exception handler is here to handle bugs around cert attributes:
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 31290
diff changeset
405 # https://bugs.python.org/issue20916#msg213479. (See issues5313.)
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 31290
diff changeset
406 # When the main 20916 bug occurs, 'sslcontext.get_ca_certs()' is a
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 31290
diff changeset
407 # non-empty list, but the following conditional is otherwise True.
29631
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
408 try:
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
409 if (caloaded and settings['verifymode'] == ssl.CERT_REQUIRED and
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
410 modernssl and not sslcontext.get_ca_certs()):
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
411 ui.warn(_('(an attempt was made to load CA certificates but '
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
412 'none were loaded; see '
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
413 'https://mercurial-scm.org/wiki/SecureConnections '
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
414 'for how to configure Mercurial to avoid this '
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
415 'error)\n'))
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
416 except ssl.SSLError:
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29619
diff changeset
417 pass
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
418 # 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
419 if util.safehasattr(e, 'reason'):
29619
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
420 # This error occurs when the client and server don't share a
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
421 # common/supported SSL/TLS protocol. We've disabled SSLv2 and SSLv3
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
422 # outright. Hopefully the reason for this error is that we require
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
423 # TLS 1.1+ and the server only supports TLS 1.0. Whatever the
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
424 # reason, try to emit an actionable warning.
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
425 if e.reason == 'UNSUPPORTED_PROTOCOL':
29619
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
426 # We attempted TLS 1.0+.
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
427 if settings['protocolui'] == 'tls1.0':
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
428 # We support more than just TLS 1.0+. If this happens,
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
429 # the likely scenario is either the client or the server
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
430 # is really old. (e.g. server doesn't support TLS 1.0+ or
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
431 # client doesn't support modern TLS versions introduced
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
432 # several years from when this comment was written).
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32273
diff changeset
433 if supportedprotocols != {'tls1.0'}:
29619
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
434 ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
435 '(could not communicate with %s using security '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
436 'protocols %s; if you are using a modern Mercurial '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
437 'version, consider contacting the operator of this '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
438 'server; see '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
439 'https://mercurial-scm.org/wiki/SecureConnections '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
440 'for more info)\n') % (
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
441 serverhostname,
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
442 ', '.join(sorted(supportedprotocols))))
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
443 else:
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
444 ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
445 '(could not communicate with %s using TLS 1.0; the '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
446 'likely cause of this is the server no longer '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
447 'supports TLS 1.0 because it has known security '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
448 'vulnerabilities; see '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
449 'https://mercurial-scm.org/wiki/SecureConnections '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
450 'for more info)\n') % serverhostname)
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
451 else:
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
452 # We attempted TLS 1.1+. We can only get here if the client
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
453 # supports the configured protocol. So the likely reason is
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
454 # the client wants better security than the server can
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
455 # offer.
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
456 ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
457 '(could not negotiate a common security protocol (%s+) '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
458 'with %s; the likely cause is Mercurial is configured '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
459 'to be more secure than the server can support)\n') % (
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
460 settings['protocolui'], serverhostname))
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
461 ui.warn(_('(consider contacting the operator of this '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
462 'server and ask them to support modern TLS '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
463 'protocol versions; or, set '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
464 'hostsecurity.%s:minimumprotocol=tls1.0 to allow '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
465 'use of legacy, less secure protocols when '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
466 'communicating with this server)\n') %
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
467 serverhostname)
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
468 ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
469 '(see https://mercurial-scm.org/wiki/SecureConnections '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29618
diff changeset
470 'for more info)\n'))
29449
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
471 raise
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
472
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
473 # 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
474 # closed
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
475 # - see http://bugs.python.org/issue13721
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
476 if not sslsocket.cipher():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
477 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
478
29225
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29224
diff changeset
479 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
480 'caloaded': caloaded,
29226
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29225
diff changeset
481 'hostname': serverhostname,
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
482 'settings': settings,
29226
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29225
diff changeset
483 '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
484 }
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
485
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
486 return sslsocket
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
487
29554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
488 def wrapserversocket(sock, ui, certfile=None, keyfile=None, cafile=None,
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
489 requireclientcert=False):
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
490 """Wrap a socket for use by servers.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
491
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
492 ``certfile`` and ``keyfile`` specify the files containing the certificate's
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
493 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
494 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
495
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
496 ``cafile`` defines the path to certificate authorities.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
497
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
498 ``requireclientcert`` specifies whether to require client certificates.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
499
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
500 Typically ``cafile`` is only defined if ``requireclientcert`` is true.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
501 """
29618
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29617
diff changeset
502 protocol, options, _protocolui = protocolsettings('tls1.0')
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
503
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
504 # 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
505 # 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
506 exactprotocol = ui.config('devel', 'serverexactprotocol')
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
507 if exactprotocol == 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
508 protocol = ssl.PROTOCOL_TLSv1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
509 elif exactprotocol == 'tls1.1':
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
510 if 'tls1.1' not in supportedprotocols:
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
511 raise error.Abort(_('TLS 1.1 not supported by this Python'))
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
512 protocol = ssl.PROTOCOL_TLSv1_1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
513 elif exactprotocol == 'tls1.2':
29601
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
514 if 'tls1.2' not in supportedprotocols:
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29578
diff changeset
515 raise error.Abort(_('TLS 1.2 not supported by this Python'))
29559
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
516 protocol = ssl.PROTOCOL_TLSv1_2
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
517 elif exactprotocol:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
518 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
519 exactprotocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
520
29554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
521 if modernssl:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
522 # 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
523 # 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
524 # 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
525 sslcontext = SSLContext(protocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
526 sslcontext.options |= options
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29558
diff changeset
527
29554
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
528 # Improve forward secrecy.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
529 sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
530 sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
531
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
532 # 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
533 if util.safehasattr(ssl, '_RESTRICTED_SERVER_CIPHERS'):
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
534 sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
535 sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
536 else:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
537 sslcontext = SSLContext(ssl.PROTOCOL_TLSv1)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
538
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
539 if requireclientcert:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
540 sslcontext.verify_mode = ssl.CERT_REQUIRED
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
541 else:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
542 sslcontext.verify_mode = ssl.CERT_NONE
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
543
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
544 if certfile or keyfile:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
545 sslcontext.load_cert_chain(certfile=certfile, keyfile=keyfile)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
546
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
547 if cafile:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
548 sslcontext.load_verify_locations(cafile=cafile)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
549
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
550 return sslcontext.wrap_socket(sock, server_side=True)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29537
diff changeset
551
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
552 class wildcarderror(Exception):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
553 """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
554
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
555 def _dnsnamematch(dn, hostname, maxwildcards=1):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
556 """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
557
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
558 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
559
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
560 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
561 the value in ``dn``.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
562 """
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
563 pats = []
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
564 if not dn:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
565 return False
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
566
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
567 pieces = dn.split(r'.')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
568 leftmost = pieces[0]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
569 remainder = pieces[1:]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
570 wildcards = leftmost.count('*')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
571 if wildcards > maxwildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
572 raise wildcarderror(
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
573 _('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
574
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
575 # 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
576 if not wildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
577 return dn.lower() == hostname.lower()
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
578
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
579 # 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
580 # 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
581 # 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
582 if leftmost == '*':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
583 # 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
584 # fragment.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
585 pats.append('[^.]+')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
586 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
587 # 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
588 # 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
589 # 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
590 # 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
591 pats.append(re.escape(leftmost))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
592 else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
593 # 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
594 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
595
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
596 # 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
597 for frag in remainder:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
598 pats.append(re.escape(frag))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
599
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
600 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
601 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
602
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
603 def _verifycert(cert, hostname):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
604 '''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
605 CRLs is not handled.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
606
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
607 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
608 '''
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
609 if not cert:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
610 return _('no certificate received')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
611
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
612 dnsnames = []
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
613 san = cert.get('subjectAltName', [])
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
614 for key, value in san:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
615 if key == 'DNS':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
616 try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
617 if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
618 return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
619 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
620 return e.args[0]
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
621
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
622 dnsnames.append(value)
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
623
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
624 if not dnsnames:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
625 # 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
626 for sub in cert.get('subject', []):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
627 for key, value in sub:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
628 # 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
629 # be used.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
630 if key == 'commonName':
30332
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 30228
diff changeset
631 # 'subject' entries are unicode.
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
632 try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
633 value = value.encode('ascii')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
634 except UnicodeEncodeError:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
635 return _('IDN in certificate not supported')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
636
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
637 try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
638 if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
639 return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
640 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
641 return e.args[0]
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
642
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
643 dnsnames.append(value)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
644
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
645 if len(dnsnames) > 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
646 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
647 elif len(dnsnames) == 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
648 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
649 else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
650 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
651
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
652 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
653 """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
654 * 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
655 system
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
656 * 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
657 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
658 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
659 """
30641
16b5df5792a8 py3: replace sys.platform with pycompat.sysplatform (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30639
diff changeset
660 if (pycompat.sysplatform != 'darwin' or
30669
10b17ed9b591 py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30641
diff changeset
661 util.mainfrozen() or not pycompat.sysexecutable):
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
662 return False
30669
10b17ed9b591 py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30641
diff changeset
663 exe = os.path.realpath(pycompat.sysexecutable).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
664 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
665 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
666
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
667 _systemcacertpaths = [
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
668 # 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
669 '/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
670 # Debian, Ubuntu, Gentoo
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
671 '/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
672 ]
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
673
29483
918dce4b8c26 sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29482
diff changeset
674 def _defaultcacerts(ui):
29488
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
675 """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
676
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
677 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
678 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
679 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
680
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
681 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
682 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
683 """
30228
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
684 # The "certifi" Python package provides certificates. If it is installed
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
685 # and usable, assume the user intends it to be used and use it.
29486
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
686 try:
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
687 import certifi
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
688 certs = certifi.where()
30228
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
689 if os.path.exists(certs):
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
690 ui.debug('using ca certificates from certifi\n')
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
691 return certs
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 29927
diff changeset
692 except (ImportError, AttributeError):
29486
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
693 pass
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
694
29489
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
695 # 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
696 # 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
697 # 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
698 # 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
699 # Assertion: this code is only called if certificates are being verified.
30639
d524c88511a7 py3: replace os.name with pycompat.osname (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
700 if pycompat.osname == 'nt':
29489
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
701 if not _canloaddefaultcerts:
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
702 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
703 '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
704 '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
705
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
706 return None
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
707
29487
cdcb5747dc88 sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29486
diff changeset
708 # 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
709 # 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
710 # trick.
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
711 if _plainapplepython():
31074
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30669
diff changeset
712 dummycert = os.path.join(
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30669
diff changeset
713 os.path.dirname(pycompat.fsencode(__file__)), 'dummycert.pem')
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
714 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
715 return dummycert
29107
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29106
diff changeset
716
29499
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
717 # 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
718 # load system certs, we're out of luck.
30641
16b5df5792a8 py3: replace sys.platform with pycompat.sysplatform (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30639
diff changeset
719 if pycompat.sysplatform == 'darwin':
29499
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
720 # 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
721 # 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
722 # Mercurial install.
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
723 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
724 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
725 '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
726 '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
727 return None
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
728
29537
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29508
diff changeset
729 # / 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
730 # 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
731 # by non-admin users.
30639
d524c88511a7 py3: replace os.name with pycompat.osname (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30332
diff changeset
732 assert pycompat.osname != 'nt'
29537
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29508
diff changeset
733
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
734 # 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
735 # 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
736 # 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
737 # 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
738 # 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
739 # 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
740 # last resort.
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
741 if not _canloaddefaultcerts:
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
742 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
743 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
744 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
745 '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
746 'configured; see '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
747 '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
748 '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
749 'message)\n') % path)
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
750 return path
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
751
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
752 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
753 '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
754 '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
755
29107
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29106
diff changeset
756 return None
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
757
29286
a05a91a3f120 sslutil: remove "strict" argument from validatesocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29268
diff changeset
758 def validatesocket(sock):
30332
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 30228
diff changeset
759 """Validate a socket meets security requirements.
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
760
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
761 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
762 """
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
763 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
764 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
765 settings = sock._hgstate['settings']
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
766
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
767 try:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
768 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
769 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
770 except AttributeError:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
771 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
772
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
773 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
774 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
775 'no certificate received') % host)
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
776
29289
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
777 if settings['disablecertverification']:
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
778 # 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
779 # 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
780 # 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
781 # 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
782 # 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
783 # value.
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
784 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
785 '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
786 '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
787 return
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
788
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
789 # 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
790 # validate the remote cert.
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
791 peerfingerprints = {
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29334
diff changeset
792 '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
793 '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
794 'sha512': hashlib.sha512(peercert).hexdigest(),
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
795 }
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
796
29290
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
797 def fmtfingerprint(s):
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
798 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
799
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
800 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
801
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
802 if settings['certfingerprints']:
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
803 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
804 if peerfingerprints[hash].lower() == fingerprint:
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
805 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
806 (host, hash, fmtfingerprint(fingerprint)))
31290
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31074
diff changeset
807 if settings['legacyfingerprint']:
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31074
diff changeset
808 ui.warn(_('(SHA-1 fingerprint for %s found in legacy '
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31074
diff changeset
809 '[hostfingerprints] section; '
32273
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
810 'if you trust this fingerprint, remove the old '
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
811 'SHA-1 fingerprint from [hostfingerprints] and '
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
812 'add the following entry to the new '
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
813 '[hostsecurity] section: %s:fingerprints=%s)\n') %
2e455cbeac50 sslutil: tweak the legacy [hostfingerprints] warning message
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32247
diff changeset
814 (host, host, nicefingerprint))
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
815 return
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
816
29293
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
817 # 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
818 if settings['legacyfingerprint']:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
819 section = 'hostfingerprint'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
820 nice = fmtfingerprint(peerfingerprints['sha1'])
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
821 else:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
822 section = 'hostsecurity'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
823 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
824 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
825 'fingerprint %s') % (host, nice),
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
826 hint=_('check %s configuration') % section)
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
827
29411
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
828 # 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
829 # 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
830 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
831 raise error.Abort(
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
832 _('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
833 'refusing to connect') % host,
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
834 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
835 '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
836 '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
837 (host, nicefingerprint))
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
838
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
839 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
840 if msg:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
841 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
842 hint=_('set hostsecurity.%s:certfingerprints=%s '
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
843 '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
844 'insecurely') %
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
845 (host, nicefingerprint))