annotate mercurial/sslutil.py @ 33044:976681123416

transaction: introduce "changes" dictionary to precisely track updates The transaction is already tracking some data intended for hooks (in 'hookargs'). However, that information is minimal as we optimise for passing data to other processes through environment variables. There are multiple places were we could use more complete and lower level information locally (eg: cache update, better report of changes to hooks, etc...). For this purpose we introduces a 'changes' dictionary on the transaction. It is intended to track every changes happening to the repository (eg: new revs, bookmarks move, phases move, obs-markers, etc). For now we just adds the 'changes' dictionary. We'll adds more tracking and usages over time.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Tue, 02 May 2017 18:31:18 +0200
parents e05cfb4a6a8e
children 2e455cbeac50
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
14205
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.
26561
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25966
diff changeset
9
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25966
diff changeset
10 from __future__ import absolute_import
14205
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
11
30091
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 30084
diff changeset
12 import hashlib
26561
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25966
diff changeset
13 import os
30213
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
14 import re
26561
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25966
diff changeset
15 import ssl
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25966
diff changeset
16
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25966
diff changeset
17 from .i18n import _
29318
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29196
diff changeset
18 from . import (
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29196
diff changeset
19 error,
31418
d524c88511a7 py3: replace os.name with pycompat.osname (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31111
diff changeset
20 pycompat,
29318
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29196
diff changeset
21 util,
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29196
diff changeset
22 )
24398
760a86865f80 ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents: 24397
diff changeset
23
29388
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29318
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: 29318
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: 29318
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: 29318
diff changeset
27 #
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29318
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: 29318
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: 29318
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: 29318
diff changeset
31
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
32 configprotocols = set([
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
33 'tls1.0',
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
34 'tls1.1',
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
35 'tls1.2',
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
36 ])
27262
9e15286609ae sslutil: expose attribute indicating whether SNI is supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27227
diff changeset
37
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
38 hassni = getattr(ssl, 'HAS_SNI', False)
29389
7fc787e5d8ec sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29388
diff changeset
39
30362
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
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: 30339
diff changeset
41 # against doesn't support them.
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
42 supportedprotocols = set(['tls1.0'])
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
43 if util.safehasattr(ssl, 'PROTOCOL_TLSv1_1'):
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
44 supportedprotocols.add('tls1.1')
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
45 if util.safehasattr(ssl, 'PROTOCOL_TLSv1_2'):
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
46 supportedprotocols.add('tls1.2')
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
47
29390
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
48 try:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
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: 29389
diff changeset
50 # SSL/TLS features are available.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
51 SSLContext = ssl.SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
52 modernssl = True
29391
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29390
diff changeset
53 _canloaddefaultcerts = util.safehasattr(SSLContext, 'load_default_certs')
29390
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
54 except AttributeError:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
55 modernssl = False
29391
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29390
diff changeset
56 _canloaddefaultcerts = False
29390
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
57
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
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: 29389
diff changeset
59 class SSLContext(object):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
60 def __init__(self, protocol):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
61 # From the public interface of SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
62 self.protocol = protocol
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
63 self.check_hostname = False
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
64 self.options = 0
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
65 self.verify_mode = ssl.CERT_NONE
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
66
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
67 # Used by our implementation.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
68 self._certfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
69 self._keyfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
70 self._certpassword = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
71 self._cacerts = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
72 self._ciphers = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
73
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
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: 29389
diff changeset
75 self._certfile = certfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
76 self._keyfile = keyfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
77 self._certpassword = password
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
78
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
79 def load_default_certs(self, purpose=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
80 pass
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
81
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
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: 29389
diff changeset
83 if capath:
30150
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 30091
diff changeset
84 raise error.Abort(_('capath not supported'))
29390
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
85 if cadata:
30150
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 30091
diff changeset
86 raise error.Abort(_('cadata not supported'))
29390
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
87
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
88 self._cacerts = cafile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
89
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
90 def set_ciphers(self, ciphers):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
91 self._ciphers = ciphers
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
92
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
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: 29389
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: 29389
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: 29389
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: 29389
diff changeset
97
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
98 args = {
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
99 'keyfile': self._keyfile,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
100 'certfile': self._certfile,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
101 'server_side': server_side,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
102 'cert_reqs': self.verify_mode,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
103 'ssl_version': self.protocol,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
104 'ca_certs': self._cacerts,
33030
e05cfb4a6a8e sslutil: remove conditional cipher code needed for Python 2.6
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32977
diff changeset
105 'ciphers': self._ciphers,
29390
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
106 }
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
107
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
108 return ssl.wrap_socket(socket, **args)
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29389
diff changeset
109
30008
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
110 def _hostsettings(ui, hostname):
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
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: 30003
diff changeset
112
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
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: 30003
diff changeset
114 """
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
115 s = {
30038
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30037
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: 30037
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: 30037
diff changeset
118 'allowloaddefaultcerts': True,
30008
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
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: 30003
diff changeset
120 'certfingerprints': [],
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
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: 30009
diff changeset
122 # SSLContext.load_verify_locations().
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
123 'cafile': None,
30037
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30036
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: 30036
diff changeset
125 'disablecertverification': False,
30018
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30017
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: 30017
diff changeset
127 'legacyfingerprint': False,
30268
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30262
diff changeset
128 # PROTOCOL_* constant to use for SSLContext.__init__.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30262
diff changeset
129 'protocol': None,
30379
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30378
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: 30378
diff changeset
131 # presentation.
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30378
diff changeset
132 'protocolui': None,
30009
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
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: 30008
diff changeset
134 'verifymode': None,
30269
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30268
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: 30268
diff changeset
136 'ctxoptions': None,
30338
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
137 # OpenSSL Cipher List to use (instead of default).
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
138 'ciphers': None,
30008
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
139 }
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
140
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
142 def validateprotocol(protocol, key):
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
143 if protocol not in configprotocols:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
144 raise error.Abort(
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
146 (key, protocol),
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
147 hint=_('valid protocols: %s') %
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
148 ' '.join(sorted(configprotocols)))
30268
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30262
diff changeset
149
30362
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
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: 30339
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: 30339
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: 30339
diff changeset
153 if 'tls1.1' in supportedprotocols:
30321
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30320
diff changeset
154 defaultprotocol = 'tls1.1'
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30320
diff changeset
155 else:
30362
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
156 # Let people know they are borderline secure.
30322
1a782fabf80d sslutil: print a warning when using TLS 1.0 on legacy Python
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30321
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: 30321
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: 30321
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: 30321
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: 30321
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: 30321
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: 30321
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: 30321
diff changeset
164 'more info\n') % hostname)
30321
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30320
diff changeset
165 defaultprotocol = 'tls1.0'
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30320
diff changeset
166
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
167 key = 'minimumprotocol'
30321
303e9300772a sslutil: require TLS 1.1+ when supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30320
diff changeset
168 protocol = ui.config('hostsecurity', key, defaultprotocol)
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
169 validateprotocol(protocol, key)
30269
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30268
diff changeset
170
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
171 key = '%s:minimumprotocol' % hostname
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
173 validateprotocol(protocol, key)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
174
30378
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30362
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: 30362
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: 30362
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: 30362
diff changeset
178 if ui.insecureconnections:
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30362
diff changeset
179 protocol = 'tls1.0'
2960ceee1948 sslutil: allow TLS 1.0 when --insecure is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30362
diff changeset
180
30379
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30378
diff changeset
181 s['protocol'], s['ctxoptions'], s['protocolui'] = protocolsettings(protocol)
30319
a935cd7d51a6 sslutil: prevent CRIME
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30318
diff changeset
182
30338
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
183 ciphers = ui.config('hostsecurity', 'ciphers')
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
184 ciphers = ui.config('hostsecurity', '%s:ciphers' % hostname, ciphers)
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
185 s['ciphers'] = ciphers
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
186
30017
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
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: 30012
diff changeset
188 # of <alg>:<fingerprint> strings.
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
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: 30012
diff changeset
190 [])
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
diff changeset
191 for fingerprint in fingerprints:
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
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: 30012
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: 30012
diff changeset
194 hostname, fingerprint),
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
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: 30012
diff changeset
196 'or "sha512:"'))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
diff changeset
197
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
diff changeset
198 alg, fingerprint = fingerprint.split(':', 1)
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
diff changeset
199 fingerprint = fingerprint.replace(':', '').lower()
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
diff changeset
200 s['certfingerprints'].append((alg, fingerprint))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30012
diff changeset
201
30008
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
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: 30003
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: 30003
diff changeset
204 fingerprint = fingerprint.replace(':', '').lower()
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
205 s['certfingerprints'].append(('sha1', fingerprint))
30018
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30017
diff changeset
206 s['legacyfingerprint'] = True
30008
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
207
30009
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
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: 30008
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: 30008
diff changeset
210 if s['certfingerprints']:
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
diff changeset
211 s['verifymode'] = ssl.CERT_NONE
30208
13edc11eb7b7 sslutil: don't load default certificates when they aren't relevant
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30207
diff changeset
212 s['allowloaddefaultcerts'] = False
30009
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
diff changeset
213
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
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: 30008
diff changeset
215 elif ui.insecureconnections:
30037
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30036
diff changeset
216 s['disablecertverification'] = True
30009
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
diff changeset
217 s['verifymode'] = ssl.CERT_NONE
30208
13edc11eb7b7 sslutil: don't load default certificates when they aren't relevant
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30207
diff changeset
218 s['allowloaddefaultcerts'] = False
30009
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
diff changeset
219
30038
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30037
diff changeset
220 if ui.configbool('devel', 'disableloaddefaultcerts'):
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30037
diff changeset
221 s['allowloaddefaultcerts'] = False
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30037
diff changeset
222
30084
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
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: 30043
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: 30043
diff changeset
225 # being performed.
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
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: 30043
diff changeset
227 if s['certfingerprints'] and cafile:
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
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: 30043
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: 30043
diff changeset
230 'verification)\n') % hostname)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
diff changeset
231
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
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: 30009
diff changeset
233 # makes it not necessary.
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
234 if s['verifymode'] is None:
30084
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
diff changeset
235 # Look at per-host ca file first.
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
236 if cafile:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
237 cafile = util.expandpath(cafile)
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
238 if not os.path.exists(cafile):
30084
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
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: 30043
diff changeset
240 ('hostsecurity.%s:verifycertsfile' % hostname,
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
diff changeset
241 cafile))
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
diff changeset
242 s['cafile'] = cafile
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
243 else:
30084
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
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: 30043
diff changeset
245 cafile = ui.config('web', 'cacerts')
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
diff changeset
246
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
247 if cafile:
30084
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
diff changeset
248 cafile = util.expandpath(cafile)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
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: 30043
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: 30043
diff changeset
251 cafile)
30245
53b7fc7cc2bb sslutil: don't attempt to find default CA certs file when told not to
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30244
diff changeset
252 elif s['allowloaddefaultcerts']:
30243
4e72995f6c9c sslutil: change comment and logged message for found ca cert file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30220
diff changeset
253 # CAs not defined in config. Try to find system bundles.
30244
918dce4b8c26 sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30243
diff changeset
254 cafile = _defaultcacerts(ui)
30084
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
diff changeset
255 if cafile:
30243
4e72995f6c9c sslutil: change comment and logged message for found ca cert file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30220
diff changeset
256 ui.debug('using %s for CA file\n' % cafile)
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
257
30084
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30043
diff changeset
258 s['cafile'] = cafile
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
259
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
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: 30009
diff changeset
261 # verification hasn't been disabled above.
30038
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30037
diff changeset
262 if cafile or (_canloaddefaultcerts and s['allowloaddefaultcerts']):
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
263 s['verifymode'] = ssl.CERT_REQUIRED
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
264 else:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
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: 30009
diff changeset
266 # explicitly insecure, and can't load CA certs. Connecting
30172
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30171
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: 30171
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: 30171
diff changeset
269 # user).
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
270 s['verifymode'] = ssl.CERT_NONE
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
271
30268
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30262
diff changeset
272 assert s['protocol'] is not None
30269
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30268
diff changeset
273 assert s['ctxoptions'] is not None
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
274 assert s['verifymode'] is not None
30009
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
diff changeset
275
30008
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
276 return s
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
277
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
278 def protocolsettings(protocol):
30379
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30378
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: 30378
diff changeset
280
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30378
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: 30378
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: 30378
diff changeset
283 of the ``minimumprotocol`` config option equivalent.
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30378
diff changeset
284 """
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
285 if protocol not in configprotocols:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
287
30339
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30338
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: 30338
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: 30338
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: 30338
diff changeset
291 # support TLS 1.2.
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30338
diff changeset
292 #
4a4b8d3b4e43 sslutil: move comment about protocol constants
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30338
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: 30338
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: 30338
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: 30338
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: 30338
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: 30338
diff changeset
298 # full/real SSLContext available to us.
30362
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
299 if supportedprotocols == set(['tls1.0']):
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
300 if protocol != 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
302 'setting %s') % protocol,
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
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: 30319
diff changeset
305
30379
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30378
diff changeset
306 return ssl.PROTOCOL_TLSv1, 0, 'tls1.0'
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
307
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
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: 30319
diff changeset
310
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
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: 30319
diff changeset
313
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
314 if protocol == 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
316 pass
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
317 elif protocol == 'tls1.1':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
318 options |= ssl.OP_NO_TLSv1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
319 elif protocol == 'tls1.2':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
321 else:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
323
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
324 # Prevent CRIME.
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
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: 30319
diff changeset
327
30379
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30378
diff changeset
328 return ssl.PROTOCOL_SSLv23, options, protocol
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
329
29999
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29998
diff changeset
330 def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None):
29394
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29393
diff changeset
331 """Add SSL/TLS to a socket.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29393
diff changeset
332
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29393
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: 29393
diff changeset
334 choices based on what security options are available.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29393
diff changeset
335
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29393
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: 29393
diff changeset
337 the following additional arguments:
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29393
diff changeset
338
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29393
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: 29393
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: 29393
diff changeset
341 to use.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29393
diff changeset
342 """
29974
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29865
diff changeset
343 if not serverhostname:
30150
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 30091
diff changeset
344 raise error.Abort(_('serverhostname argument is required'))
29974
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29865
diff changeset
345
30009
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
diff changeset
346 settings = _hostsettings(ui, serverhostname)
29999
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29998
diff changeset
347
30318
53de8255ec4e sslutil: update comment about create_default_context()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30315
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: 30315
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: 30315
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: 30315
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: 30315
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: 30315
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: 30315
diff changeset
354 # choice.
30268
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30262
diff changeset
355 sslcontext = SSLContext(settings['protocol'])
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30262
diff changeset
356
30269
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30268
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: 30268
diff changeset
358 sslcontext.options |= settings['ctxoptions']
29392
4827d07073e6 sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29391
diff changeset
359
29598
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29394
diff changeset
360 # This still works on our fake SSLContext.
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
361 sslcontext.verify_mode = settings['verifymode']
29598
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29394
diff changeset
362
30338
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
363 if settings['ciphers']:
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
364 try:
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
365 sslcontext.set_ciphers(settings['ciphers'])
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
366 except ssl.SSLError as e:
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
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: 30322
diff changeset
368 hint=_('change cipher string (%s) in config') %
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
369 settings['ciphers'])
9654ef41f7cc sslutil: support defining cipher list
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30322
diff changeset
370
29393
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
diff changeset
371 if certfile is not None:
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
diff changeset
372 def password():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
diff changeset
373 f = keyfile or certfile
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
diff changeset
374 return ui.getpass(_('passphrase for %s: ') % f, '')
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
diff changeset
375 sslcontext.load_cert_chain(certfile, keyfile, password)
29598
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29394
diff changeset
376
30010
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30009
diff changeset
377 if settings['cafile'] is not None:
30207
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30172
diff changeset
378 try:
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30172
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: 30172
diff changeset
380 except ssl.SSLError as e:
30697
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30392
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: 30392
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: 30392
diff changeset
383 else:
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30392
diff changeset
384 msg = e.args[1]
30207
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30172
diff changeset
385 raise error.Abort(_('error loading CA file %s: %s') % (
30697
799e36749f1a ssl: handle a difference in SSLError with pypy (issue5348)
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30392
diff changeset
386 settings['cafile'], msg),
30207
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30172
diff changeset
387 hint=_('file is empty or malformed?'))
29863
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29862
diff changeset
388 caloaded = True
30038
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30037
diff changeset
389 elif settings['allowloaddefaultcerts']:
29393
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
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: 29392
diff changeset
391 sslcontext.load_default_certs()
30038
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30037
diff changeset
392 caloaded = True
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30037
diff changeset
393 else:
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30037
diff changeset
394 caloaded = False
23846
bf07c19b4c82 https: support tls sni (server name indication) for https urls (issue3090)
Alex Orange <crazycasta@gmail.com>
parents: 23069
diff changeset
395
30210
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30208
diff changeset
396 try:
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30208
diff changeset
397 sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname)
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
398 except ssl.SSLError as e:
30210
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30208
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: 30208
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: 30208
diff changeset
401 # a hint to the user.
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30208
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: 30208
diff changeset
403 # only show this warning if modern ssl is available.
32504
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 32069
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: 32069
diff changeset
405 # https://bugs.python.org/issue20916#msg213479. (See issues5313.)
c777b12cdc9b sslutil: clarify internal documentation
Matt Harbison <matt_harbison@yahoo.com>
parents: 32069
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: 32069
diff changeset
407 # non-empty list, but the following conditional is otherwise True.
30392
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30380
diff changeset
408 try:
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30380
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: 30380
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: 30380
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: 30380
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: 30380
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: 30380
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: 30380
diff changeset
415 'error)\n'))
387bdd53c77e sslutil: work around SSLContext.get_ca_certs bug on Windows (issue5313)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30380
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: 30380
diff changeset
417 pass
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
419 if util.safehasattr(e, 'reason'):
30380
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
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: 30379
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: 30379
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: 30379
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: 30379
diff changeset
424 # reason, try to emit an actionable warning.
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
425 if e.reason == 'UNSUPPORTED_PROTOCOL':
30380
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
426 # We attempted TLS 1.0+.
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
427 if settings['protocolui'] == 'tls1.0':
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
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: 30379
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: 30379
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: 30379
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: 30379
diff changeset
432 # several years from when this comment was written).
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
433 if supportedprotocols != set(['tls1.0']):
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
434 ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
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: 30379
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: 30379
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: 30379
diff changeset
438 'server; see '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
439 'https://mercurial-scm.org/wiki/SecureConnections '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
440 'for more info)\n') % (
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
441 serverhostname,
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
442 ', '.join(sorted(supportedprotocols))))
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
443 else:
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
444 ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
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: 30379
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: 30379
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: 30379
diff changeset
448 'vulnerabilities; see '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
449 'https://mercurial-scm.org/wiki/SecureConnections '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
450 'for more info)\n') % serverhostname)
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
451 else:
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
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: 30379
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: 30379
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: 30379
diff changeset
455 # offer.
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
456 ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
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: 30379
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: 30379
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: 30379
diff changeset
460 settings['protocolui'], serverhostname))
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
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: 30379
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: 30379
diff changeset
463 'protocol versions; or, set '
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
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: 30379
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: 30379
diff changeset
466 'communicating with this server)\n') %
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
467 serverhostname)
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
diff changeset
468 ui.warn(_(
53e80179bd6a sslutil: improve messaging around unsupported protocols (issue5303)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30379
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: 30379
diff changeset
470 'for more info)\n'))
30210
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30208
diff changeset
471 raise
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30208
diff changeset
472
29393
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
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: 29392
diff changeset
474 # closed
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
diff changeset
475 # - see http://bugs.python.org/issue13721
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
diff changeset
476 if not sslsocket.cipher():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
diff changeset
477 raise error.Abort(_('ssl connection failed'))
29863
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29862
diff changeset
478
29975
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29974
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: 29974
diff changeset
480 'caloaded': caloaded,
29976
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29975
diff changeset
481 'hostname': serverhostname,
30009
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30008
diff changeset
482 'settings': settings,
29976
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29975
diff changeset
483 'ui': ui,
29975
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29974
diff changeset
484 }
29863
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29862
diff changeset
485
29393
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29392
diff changeset
486 return sslsocket
14205
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
487
30315
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
488 def wrapserversocket(sock, ui, certfile=None, keyfile=None, cafile=None,
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
489 requireclientcert=False):
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
490 """Wrap a socket for use by servers.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
491
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
492 ``certfile`` and ``keyfile`` specify the files containing the certificate's
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
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: 30298
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: 30298
diff changeset
495
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
496 ``cafile`` defines the path to certificate authorities.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
497
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
498 ``requireclientcert`` specifies whether to require client certificates.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
499
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
500 Typically ``cafile`` is only defined if ``requireclientcert`` is true.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
501 """
30379
fbf4adc0d8f2 sslutil: capture string string representation of protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30378
diff changeset
502 protocol, options, _protocolui = protocolsettings('tls1.0')
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
503
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
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: 30319
diff changeset
506 exactprotocol = ui.config('devel', 'serverexactprotocol')
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
507 if exactprotocol == 'tls1.0':
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
508 protocol = ssl.PROTOCOL_TLSv1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
509 elif exactprotocol == 'tls1.1':
30362
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
510 if 'tls1.1' not in supportedprotocols:
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
511 raise error.Abort(_('TLS 1.1 not supported by this Python'))
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
512 protocol = ssl.PROTOCOL_TLSv1_1
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
513 elif exactprotocol == 'tls1.2':
30362
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
514 if 'tls1.2' not in supportedprotocols:
6cff2ac0ccb9 sslutil: more robustly detect protocol support
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30339
diff changeset
515 raise error.Abort(_('TLS 1.2 not supported by this Python'))
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
516 protocol = ssl.PROTOCOL_TLSv1_2
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
517 elif exactprotocol:
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
diff changeset
519 exactprotocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
520
30315
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
521 if modernssl:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
522 # We /could/ use create_default_context() here since it doesn't load
30320
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
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: 30319
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: 30319
diff changeset
525 sslcontext = SSLContext(protocol)
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
526 sslcontext.options |= options
7dec5e441bf7 sslutil: config option to specify TLS protocol version
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30319
diff changeset
527
30315
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
528 # Improve forward secrecy.
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
529 sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
530 sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
531
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
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: 30298
diff changeset
533 if util.safehasattr(ssl, '_RESTRICTED_SERVER_CIPHERS'):
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
534 sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
535 sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
536 else:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
537 sslcontext = SSLContext(ssl.PROTOCOL_TLSv1)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
538
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
539 if requireclientcert:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
540 sslcontext.verify_mode = ssl.CERT_REQUIRED
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
541 else:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
542 sslcontext.verify_mode = ssl.CERT_NONE
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
543
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
544 if certfile or keyfile:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
545 sslcontext.load_cert_chain(certfile=certfile, keyfile=keyfile)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
546
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
547 if cafile:
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
548 sslcontext.load_verify_locations(cafile=cafile)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
549
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
550 return sslcontext.wrap_socket(sock, server_side=True)
4a7b0c696fbc sslutil: implement wrapserversocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30298
diff changeset
551
30213
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
552 class wildcarderror(Exception):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
554
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
555 def _dnsnamematch(dn, hostname, maxwildcards=1):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
557
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
559
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
561 the value in ``dn``.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
562 """
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
563 pats = []
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
564 if not dn:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
565 return False
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
566
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
567 pieces = dn.split(r'.')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
568 leftmost = pieces[0]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
569 remainder = pieces[1:]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
570 wildcards = leftmost.count('*')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
571 if wildcards > maxwildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
572 raise wildcarderror(
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
574
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
576 if not wildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
577 return dn.lower() == hostname.lower()
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
578
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
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: 29792
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: 29792
diff changeset
582 if leftmost == '*':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
584 # fragment.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
585 pats.append('[^.]+')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
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: 29792
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: 29792
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: 29792
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: 29792
diff changeset
591 pats.append(re.escape(leftmost))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
592 else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
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: 29792
diff changeset
595
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
597 for frag in remainder:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
598 pats.append(re.escape(frag))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
599
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
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: 29792
diff changeset
602
14205
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
30213
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
612 dnsnames = []
14205
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
613 san = cert.get('subjectAltName', [])
30213
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
614 for key, value in san:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
615 if key == 'DNS':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
616 try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
617 if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
618 return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
619 except wildcarderror as e:
30221
a7d1532b26a1 sslutil: don't access message attribute in exception (issue5285)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30213
diff changeset
620 return e.args[0]
30213
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
621
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
622 dnsnames.append(value)
14205
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
623
30213
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
624 if not dnsnames:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
626 for sub in cert.get('subject', []):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
627 for key, value in sub:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
629 # be used.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
630 if key == 'commonName':
31111
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 31007
diff changeset
631 # 'subject' entries are unicode.
30213
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
632 try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
633 value = value.encode('ascii')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
634 except UnicodeEncodeError:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
635 return _('IDN in certificate not supported')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
636
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
637 try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
638 if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
639 return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
640 except wildcarderror as e:
30221
a7d1532b26a1 sslutil: don't access message attribute in exception (issue5285)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30213
diff changeset
641 return e.args[0]
30213
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
642
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
643 dnsnames.append(value)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
644
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
645 if len(dnsnames) > 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
647 elif len(dnsnames) == 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
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: 29792
diff changeset
649 else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
650 return _('no commonName or subjectAltName found in certificate')
14205
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 """
31420
16b5df5792a8 py3: replace sys.platform with pycompat.sysplatform (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31418
diff changeset
660 if (pycompat.sysplatform != 'darwin' or
31448
10b17ed9b591 py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31420
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
31448
10b17ed9b591 py3: replace sys.executable with pycompat.sysexecutable
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31420
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
30261
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
diff changeset
667 _systemcacertpaths = [
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
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: 30260
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: 30260
diff changeset
670 # Debian, Ubuntu, Gentoo
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
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: 30260
diff changeset
672 ]
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
diff changeset
673
30244
918dce4b8c26 sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30243
diff changeset
674 def _defaultcacerts(ui):
30249
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30248
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: 30248
diff changeset
676
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30248
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: 30248
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: 30248
diff changeset
679 function may print warnings or debug messages assuming this usage.
30261
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
diff changeset
680
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
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: 30260
diff changeset
682 CA certs because this scenario is detected at socket connect time.
30249
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30248
diff changeset
683 """
31007
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30697
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: 30697
diff changeset
685 # and usable, assume the user intends it to be used and use it.
30247
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30245
diff changeset
686 try:
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30245
diff changeset
687 import certifi
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30245
diff changeset
688 certs = certifi.where()
31007
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30697
diff changeset
689 if os.path.exists(certs):
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30697
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: 30697
diff changeset
691 return certs
b9f7b0c10027 sslutil: guard against broken certifi installations (issue5406)
Gábor Stefanik <gabor.stefanik@nng.com>
parents: 30697
diff changeset
692 except (ImportError, AttributeError):
30247
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30245
diff changeset
693 pass
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30245
diff changeset
694
30250
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30249
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: 30249
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: 30249
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: 30249
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: 30249
diff changeset
699 # Assertion: this code is only called if certificates are being verified.
31418
d524c88511a7 py3: replace os.name with pycompat.osname (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31111
diff changeset
700 if pycompat.osname == 'nt':
30250
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30249
diff changeset
701 if not _canloaddefaultcerts:
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30249
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: 30249
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: 30249
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: 30249
diff changeset
705
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30249
diff changeset
706 return None
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30249
diff changeset
707
30248
cdcb5747dc88 sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30247
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: 30247
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: 30247
diff changeset
710 # trick.
24395
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23863
diff changeset
711 if _plainapplepython():
31853
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31448
diff changeset
712 dummycert = os.path.join(
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31448
diff changeset
713 os.path.dirname(pycompat.fsencode(__file__)), 'dummycert.pem')
24395
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23863
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: 23863
diff changeset
715 return dummycert
29857
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29856
diff changeset
716
30260
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30250
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: 30250
diff changeset
718 # load system certs, we're out of luck.
31420
16b5df5792a8 py3: replace sys.platform with pycompat.sysplatform (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31418
diff changeset
719 if pycompat.sysplatform == 'darwin':
30260
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30250
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: 30250
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: 30250
diff changeset
722 # Mercurial install.
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30250
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: 30250
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: 30250
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: 30250
diff changeset
726 'how to configure Mercurial to avoid this message)\n'))
24398
760a86865f80 ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents: 24397
diff changeset
727 return None
24395
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23863
diff changeset
728
30298
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30269
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: 30269
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: 30269
diff changeset
731 # by non-admin users.
31418
d524c88511a7 py3: replace os.name with pycompat.osname (part 1 of 2)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 31111
diff changeset
732 assert pycompat.osname != 'nt'
30298
5f8b36d5a6ec sslutil: add assertion to prevent accidental CA usage on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30269
diff changeset
733
30261
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
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: 30260
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: 30260
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: 30260
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: 30260
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: 30260
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: 30260
diff changeset
740 # last resort.
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
diff changeset
741 if not _canloaddefaultcerts:
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
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: 30260
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: 30260
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: 30260
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: 30260
diff changeset
746 'configured; see '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
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: 30260
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: 30260
diff changeset
749 'message)\n') % path)
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
diff changeset
750 return path
14205
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
751
30261
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30260
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: 30260
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: 30260
diff changeset
754 'how to configure Mercurial to avoid this message)\n'))
14205
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
755
29857
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29856
diff changeset
756 return None
24395
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23863
diff changeset
757
30036
a05a91a3f120 sslutil: remove "strict" argument from validatesocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30018
diff changeset
758 def validatesocket(sock):
31111
318a24b52eeb spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com>
parents: 31007
diff changeset
759 """Validate a socket meets security requirements.
18881
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
760
29977
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
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: 29976
diff changeset
762 """
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
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: 29976
diff changeset
764 ui = sock._hgstate['ui']
30008
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
765 settings = sock._hgstate['settings']
18881
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
766
29977
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
diff changeset
767 try:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
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: 29976
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: 29976
diff changeset
770 except AttributeError:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
diff changeset
771 raise error.Abort(_('%s ssl connection error') % host)
24395
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23863
diff changeset
772
29977
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
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: 29976
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: 29976
diff changeset
775 'no certificate received') % host)
18881
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
776
30039
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30038
diff changeset
777 if settings['disablecertverification']:
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30038
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: 30038
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: 30038
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: 30038
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: 30038
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: 30038
diff changeset
783 # value.
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30038
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: 30038
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: 30038
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: 30038
diff changeset
787 return
18881
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
788
29977
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
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: 29976
diff changeset
790 # validate the remote cert.
30012
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30010
diff changeset
791 peerfingerprints = {
30091
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 30084
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: 30084
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: 30084
diff changeset
794 'sha512': hashlib.sha512(peercert).hexdigest(),
30012
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30010
diff changeset
795 }
18881
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
796
30040
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30039
diff changeset
797 def fmtfingerprint(s):
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30039
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: 30039
diff changeset
799
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30039
diff changeset
800 nicefingerprint = 'sha256:%s' % fmtfingerprint(peerfingerprints['sha256'])
29600
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29599
diff changeset
801
30008
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
802 if settings['certfingerprints']:
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30003
diff changeset
803 for hash, fingerprint in settings['certfingerprints']:
30012
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30010
diff changeset
804 if peerfingerprints[hash].lower() == fingerprint:
30041
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30040
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: 30040
diff changeset
806 (host, hash, fmtfingerprint(fingerprint)))
32069
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31853
diff changeset
807 if settings['legacyfingerprint']:
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31853
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: 31853
diff changeset
809 '[hostfingerprints] section; '
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31853
diff changeset
810 'if you trust this fingerprint, set the '
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31853
diff changeset
811 'following config value in [hostsecurity] and '
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31853
diff changeset
812 'remove the old one from [hostfingerprints] '
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31853
diff changeset
813 'to upgrade to a more secure SHA-256 '
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31853
diff changeset
814 'fingerprint: '
32977
9a86d936670f sslutil: reference fingerprints config option properly (issue5559)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32504
diff changeset
815 '%s:fingerprints=%s)\n') % (
32069
f819aa9dbbf9 sslutil: issue warning when [hostfingerprint] is used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 31853
diff changeset
816 host, host, nicefingerprint))
30041
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30040
diff changeset
817 return
29600
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29599
diff changeset
818
30043
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30042
diff changeset
819 # 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: 30042
diff changeset
820 if settings['legacyfingerprint']:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30042
diff changeset
821 section = 'hostfingerprint'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30042
diff changeset
822 nice = fmtfingerprint(peerfingerprints['sha1'])
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30042
diff changeset
823 else:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30042
diff changeset
824 section = 'hostsecurity'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30042
diff changeset
825 nice = '%s:%s' % (hash, fmtfingerprint(peerfingerprints[hash]))
30041
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30040
diff changeset
826 raise error.Abort(_('certificate for %s has unexpected '
30043
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30042
diff changeset
827 'fingerprint %s') % (host, nice),
30041
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30040
diff changeset
828 hint=_('check %s configuration') % section)
29600
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29599
diff changeset
829
30172
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30171
diff changeset
830 # 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: 30171
diff changeset
831 # for the cert so abort.
29977
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
diff changeset
832 if not sock._hgstate['caloaded']:
30172
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30171
diff changeset
833 raise error.Abort(
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30171
diff changeset
834 _('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: 30171
diff changeset
835 'refusing to connect') % host,
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30171
diff changeset
836 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: 30171
diff changeset
837 '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: 30171
diff changeset
838 '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: 30171
diff changeset
839 (host, nicefingerprint))
29863
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29862
diff changeset
840
29977
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
diff changeset
841 msg = _verifycert(peercert2, host)
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
diff changeset
842 if msg:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29976
diff changeset
843 raise error.Abort(_('%s certificate error: %s') % (host, msg),
30042
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30041
diff changeset
844 hint=_('set hostsecurity.%s:certfingerprints=%s '
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30041
diff changeset
845 'config setting or use --insecure to connect '
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30041
diff changeset
846 'insecurely') %
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30041
diff changeset
847 (host, nicefingerprint))