annotate mercurial/sslutil.py @ 29530:3239e2fdd2e2

chgserver: extract utility to bind unix domain socket to long path This is common problem of using sockaddr_un.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 21 May 2016 16:52:04 +0900
parents d65ec41b6384
children 5f8b36d5a6ec
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
1 # sslutil.py - SSL handling for mercurial
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
2 #
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
6 #
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
7 # This software may be used and distributed according to the terms of the
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
8 # GNU General Public License version 2 or any later version.
25977
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
9
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
10 from __future__ import absolute_import
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
11
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29334
diff changeset
12 import hashlib
25977
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
13 import os
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
14 import re
25977
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
15 import ssl
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
16 import sys
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
17
696f6e2be282 sslutil: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25432
diff changeset
18 from .i18n import _
28577
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
19 from . import (
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
20 error,
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
21 util,
7efff6ce9826 sslutil: use preferred formatting for import syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28525
diff changeset
22 )
24291
760a86865f80 ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents: 24290
diff changeset
23
28647
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
24 # Python 2.7.9+ overhauled the built-in SSL/TLS features of Python. It added
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
25 # support for TLS 1.1, TLS 1.2, SNI, system CA stores, etc. These features are
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
26 # all exposed via the "ssl" module.
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
27 #
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
28 # Depending on the version of Python being used, SSL/TLS support is either
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
29 # modern/secure or legacy/insecure. Many operations in this module have
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
30 # separate code paths depending on support in Python.
834d1c4ba749 sslutil: better document state of security/ssl module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28577
diff changeset
31
26622
9e15286609ae sslutil: expose attribute indicating whether SNI is supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
32 hassni = getattr(ssl, 'HAS_SNI', False)
9e15286609ae sslutil: expose attribute indicating whether SNI is supported
Gregory Szorc <gregory.szorc@gmail.com>
parents: 26587
diff changeset
33
28648
7fc787e5d8ec sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28647
diff changeset
34 try:
7fc787e5d8ec sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28647
diff changeset
35 OP_NO_SSLv2 = ssl.OP_NO_SSLv2
7fc787e5d8ec sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28647
diff changeset
36 OP_NO_SSLv3 = ssl.OP_NO_SSLv3
7fc787e5d8ec sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28647
diff changeset
37 except AttributeError:
7fc787e5d8ec sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28647
diff changeset
38 OP_NO_SSLv2 = 0x1000000
7fc787e5d8ec sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28647
diff changeset
39 OP_NO_SSLv3 = 0x2000000
7fc787e5d8ec sslutil: store OP_NO_SSL* constants in module scope
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28647
diff changeset
40
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
41 try:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
42 # ssl.SSLContext was added in 2.7.9 and presence indicates modern
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
43 # SSL/TLS features are available.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
44 SSLContext = ssl.SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
45 modernssl = True
28650
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28649
diff changeset
46 _canloaddefaultcerts = util.safehasattr(SSLContext, 'load_default_certs')
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
47 except AttributeError:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
48 modernssl = False
28650
737863b01d9f sslutil: move _canloaddefaultcerts logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28649
diff changeset
49 _canloaddefaultcerts = False
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
50
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
51 # We implement SSLContext using the interface from the standard library.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
52 class SSLContext(object):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
53 # ssl.wrap_socket gained the "ciphers" named argument in 2.7.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
54 _supportsciphers = sys.version_info >= (2, 7)
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
55
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
56 def __init__(self, protocol):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
57 # From the public interface of SSLContext
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
58 self.protocol = protocol
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
59 self.check_hostname = False
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
60 self.options = 0
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
61 self.verify_mode = ssl.CERT_NONE
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
62
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
63 # Used by our implementation.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
64 self._certfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
65 self._keyfile = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
66 self._certpassword = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
67 self._cacerts = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
68 self._ciphers = None
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
69
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
70 def load_cert_chain(self, certfile, keyfile=None, password=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
71 self._certfile = certfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
72 self._keyfile = keyfile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
73 self._certpassword = password
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
74
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
75 def load_default_certs(self, purpose=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
76 pass
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
77
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
78 def load_verify_locations(self, cafile=None, capath=None, cadata=None):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
79 if capath:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
80 raise error.Abort(_('capath not supported'))
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
81 if cadata:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
82 raise error.Abort(_('cadata not supported'))
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
83
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
84 self._cacerts = cafile
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
85
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
86 def set_ciphers(self, ciphers):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
87 if not self._supportsciphers:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
88 raise error.Abort(_('setting ciphers not supported'))
28649
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
89
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
90 self._ciphers = ciphers
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
91
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
92 def wrap_socket(self, socket, server_hostname=None, server_side=False):
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
93 # server_hostname is unique to SSLContext.wrap_socket and is used
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
94 # for SNI in that context. So there's nothing for us to do with it
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
95 # in this legacy code since we don't support SNI.
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
96
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
97 args = {
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
98 'keyfile': self._keyfile,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
99 'certfile': self._certfile,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
100 'server_side': server_side,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
101 'cert_reqs': self.verify_mode,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
102 'ssl_version': self.protocol,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
103 'ca_certs': self._cacerts,
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
104 }
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
105
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
106 if self._supportsciphers:
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
107 args['ciphers'] = self._ciphers
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
108
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
109 return ssl.wrap_socket(socket, **args)
7acab42ef184 sslutil: implement SSLContext class
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28648
diff changeset
110
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
111 def _hostsettings(ui, hostname):
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
112 """Obtain security settings for a hostname.
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
113
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
114 Returns a dict of settings relevant to that hostname.
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
115 """
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
116 s = {
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
117 # Whether we should attempt to load default/available CA certs
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
118 # if an explicit ``cafile`` is not defined.
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
119 'allowloaddefaultcerts': True,
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
120 # List of 2-tuple of (hash algorithm, hash).
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
121 'certfingerprints': [],
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
122 # Path to file containing concatenated CA certs. Used by
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
123 # SSLContext.load_verify_locations().
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
124 'cafile': None,
29287
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29286
diff changeset
125 # Whether certificate verification should be disabled.
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29286
diff changeset
126 'disablecertverification': False,
29268
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29267
diff changeset
127 # Whether the legacy [hostfingerprints] section has data for this host.
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29267
diff changeset
128 'legacyfingerprint': False,
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
129 # PROTOCOL_* constant to use for SSLContext.__init__.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
130 'protocol': None,
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
131 # ssl.CERT_* constant used by SSLContext.verify_mode.
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
132 'verifymode': None,
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
133 # Defines extra ssl.OP* bitwise options to set.
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
134 'ctxoptions': None,
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
135 }
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
136
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
137 # Despite its name, PROTOCOL_SSLv23 selects the highest protocol
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
138 # that both ends support, including TLS protocols. On legacy stacks,
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
139 # the highest it likely goes in TLS 1.0. On modern stacks, it can
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
140 # support TLS 1.2.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
141 #
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
142 # The PROTOCOL_TLSv* constants select a specific TLS version
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
143 # only (as opposed to multiple versions). So the method for
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
144 # supporting multiple TLS versions is to use PROTOCOL_SSLv23 and
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
145 # disable protocols via SSLContext.options and OP_NO_* constants.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
146 # However, SSLContext.options doesn't work unless we have the
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
147 # full/real SSLContext available to us.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
148 if modernssl:
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
149 s['protocol'] = ssl.PROTOCOL_SSLv23
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
150 else:
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
151 s['protocol'] = ssl.PROTOCOL_TLSv1
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
152
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
153 # SSLv2 and SSLv3 are broken. We ban them outright.
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
154 # WARNING: ctxoptions doesn't have an effect unless the modern ssl module
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
155 # is available. Be careful when adding flags!
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
156 s['ctxoptions'] = OP_NO_SSLv2 | OP_NO_SSLv3
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
157
29267
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
158 # Look for fingerprints in [hostsecurity] section. Value is a list
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
159 # of <alg>:<fingerprint> strings.
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
160 fingerprints = ui.configlist('hostsecurity', '%s:fingerprints' % hostname,
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
161 [])
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
162 for fingerprint in fingerprints:
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
163 if not (fingerprint.startswith(('sha1:', 'sha256:', 'sha512:'))):
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
164 raise error.Abort(_('invalid fingerprint for %s: %s') % (
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
165 hostname, fingerprint),
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
166 hint=_('must begin with "sha1:", "sha256:", '
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
167 'or "sha512:"'))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
168
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
169 alg, fingerprint = fingerprint.split(':', 1)
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
170 fingerprint = fingerprint.replace(':', '').lower()
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
171 s['certfingerprints'].append((alg, fingerprint))
f0ccb6cde3e5 sslutil: allow fingerprints to be specified in [hostsecurity]
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29262
diff changeset
172
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
173 # Fingerprints from [hostfingerprints] are always SHA-1.
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
174 for fingerprint in ui.configlist('hostfingerprints', hostname, []):
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
175 fingerprint = fingerprint.replace(':', '').lower()
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
176 s['certfingerprints'].append(('sha1', fingerprint))
29268
f200b58497f1 sslutil: reference appropriate config section in messaging
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29267
diff changeset
177 s['legacyfingerprint'] = True
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
178
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
179 # If a host cert fingerprint is defined, it is the only thing that
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
180 # matters. No need to validate CA certs.
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
181 if s['certfingerprints']:
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
182 s['verifymode'] = ssl.CERT_NONE
29447
13edc11eb7b7 sslutil: don't load default certificates when they aren't relevant
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29446
diff changeset
183 s['allowloaddefaultcerts'] = False
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
184
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
185 # If --insecure is used, don't take CAs into consideration.
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
186 elif ui.insecureconnections:
29287
fbccb334efe7 sslutil: store flag for whether cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29286
diff changeset
187 s['disablecertverification'] = True
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
188 s['verifymode'] = ssl.CERT_NONE
29447
13edc11eb7b7 sslutil: don't load default certificates when they aren't relevant
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29446
diff changeset
189 s['allowloaddefaultcerts'] = False
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
190
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
191 if ui.configbool('devel', 'disableloaddefaultcerts'):
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
192 s['allowloaddefaultcerts'] = False
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
193
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
194 # If both fingerprints and a per-host ca file are specified, issue a warning
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
195 # because users should not be surprised about what security is or isn't
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
196 # being performed.
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
197 cafile = ui.config('hostsecurity', '%s:verifycertsfile' % hostname)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
198 if s['certfingerprints'] and cafile:
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
199 ui.warn(_('(hostsecurity.%s:verifycertsfile ignored when host '
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
200 'fingerprints defined; using host fingerprints for '
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
201 'verification)\n') % hostname)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
202
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
203 # Try to hook up CA certificate validation unless something above
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
204 # makes it not necessary.
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
205 if s['verifymode'] is None:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
206 # Look at per-host ca file first.
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
207 if cafile:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
208 cafile = util.expandpath(cafile)
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
209 if not os.path.exists(cafile):
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
210 raise error.Abort(_('path specified by %s does not exist: %s') %
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
211 ('hostsecurity.%s:verifycertsfile' % hostname,
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
212 cafile))
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
213 s['cafile'] = cafile
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
214 else:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
215 # Find global certificates file in config.
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
216 cafile = ui.config('web', 'cacerts')
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
217
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
218 if cafile:
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
219 cafile = util.expandpath(cafile)
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
220 if not os.path.exists(cafile):
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
221 raise error.Abort(_('could not find web.cacerts: %s') %
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
222 cafile)
29484
53b7fc7cc2bb sslutil: don't attempt to find default CA certs file when told not to
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29483
diff changeset
223 elif s['allowloaddefaultcerts']:
29482
4e72995f6c9c sslutil: change comment and logged message for found ca cert file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29459
diff changeset
224 # CAs not defined in config. Try to find system bundles.
29483
918dce4b8c26 sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29482
diff changeset
225 cafile = _defaultcacerts(ui)
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
226 if cafile:
29482
4e72995f6c9c sslutil: change comment and logged message for found ca cert file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29459
diff changeset
227 ui.debug('using %s for CA file\n' % cafile)
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
228
29334
ecc9b788fd69 sslutil: per-host config option to define certificates
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29293
diff changeset
229 s['cafile'] = cafile
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
230
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
231 # Require certificate validation if CA certs are being loaded and
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
232 # verification hasn't been disabled above.
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
233 if cafile or (_canloaddefaultcerts and s['allowloaddefaultcerts']):
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
234 s['verifymode'] = ssl.CERT_REQUIRED
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
235 else:
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
236 # At this point we don't have a fingerprint, aren't being
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
237 # explicitly insecure, and can't load CA certs. Connecting
29411
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
238 # is insecure. We allow the connection and abort during
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
239 # validation (once we have the fingerprint to print to the
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
240 # user).
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
241 s['verifymode'] = ssl.CERT_NONE
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
242
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
243 assert s['protocol'] is not None
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
244 assert s['ctxoptions'] is not None
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
245 assert s['verifymode'] is not None
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
246
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
247 return s
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
248
29249
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29248
diff changeset
249 def wrapsocket(sock, keyfile, certfile, ui, serverhostname=None):
28653
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
250 """Add SSL/TLS to a socket.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
251
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
252 This is a glorified wrapper for ``ssl.wrap_socket()``. It makes sane
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
253 choices based on what security options are available.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
254
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
255 In addition to the arguments supported by ``ssl.wrap_socket``, we allow
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
256 the following additional arguments:
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
257
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
258 * serverhostname - The expected hostname of the remote server. If the
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
259 server (and client) support SNI, this tells the server which certificate
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
260 to use.
1eb0bd8adf39 sslutil: add docstring to wrapsocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28652
diff changeset
261 """
29224
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29115
diff changeset
262 if not serverhostname:
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 29341
diff changeset
263 raise error.Abort(_('serverhostname argument is required'))
29224
7424f4294199 sslutil: require serverhostname argument (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29115
diff changeset
264
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
265 settings = _hostsettings(ui, serverhostname)
29249
cca59ef27e60 sslutil: move sslkwargs logic into internal function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29248
diff changeset
266
29507
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
267 # TODO use ssl.create_default_context() on modernssl.
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
268 sslcontext = SSLContext(settings['protocol'])
97dcdcf75f4f sslutil: move protocol determination to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29501
diff changeset
269
29508
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
270 # This is a no-op unless using modern ssl.
d65ec41b6384 sslutil: move context options flags to _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29507
diff changeset
271 sslcontext.options |= settings['ctxoptions']
28651
4827d07073e6 sslutil: always use SSLContext
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28650
diff changeset
272
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
273 # This still works on our fake SSLContext.
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
274 sslcontext.verify_mode = settings['verifymode']
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
275
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
276 if certfile is not None:
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
277 def password():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
278 f = keyfile or certfile
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
279 return ui.getpass(_('passphrase for %s: ') % f, '')
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
280 sslcontext.load_cert_chain(certfile, keyfile, password)
28848
e330db205b20 sslutil: move and document verify_mode assignment
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28653
diff changeset
281
29260
70bc9912d83d sslutil: move CA file processing into _hostsettings()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29259
diff changeset
282 if settings['cafile'] is not None:
29446
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
283 try:
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
284 sslcontext.load_verify_locations(cafile=settings['cafile'])
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
285 except ssl.SSLError as e:
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
286 raise error.Abort(_('error loading CA file %s: %s') % (
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
287 settings['cafile'], e.args[1]),
2f7f1e10f840 sslutil: display a better error message when CA file loading fails
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29411
diff changeset
288 hint=_('file is empty or malformed?'))
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
289 caloaded = True
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
290 elif settings['allowloaddefaultcerts']:
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
291 # This is a no-op on old Python.
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
292 sslcontext.load_default_certs()
29288
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
293 caloaded = True
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
294 else:
7dee15dee53c sslutil: add devel.disableloaddefaultcerts to disable CA loading
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29287
diff changeset
295 caloaded = False
23834
bf07c19b4c82 https: support tls sni (server name indication) for https urls (issue3090)
Alex Orange <crazycasta@gmail.com>
parents: 23069
diff changeset
296
29449
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
297 try:
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
298 sslsocket = sslcontext.wrap_socket(sock, server_hostname=serverhostname)
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
299 except ssl.SSLError:
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
300 # If we're doing certificate verification and no CA certs are loaded,
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
301 # that is almost certainly the reason why verification failed. Provide
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
302 # a hint to the user.
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
303 # Only modern ssl module exposes SSLContext.get_ca_certs() so we can
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
304 # only show this warning if modern ssl is available.
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
305 if (caloaded and settings['verifymode'] == ssl.CERT_REQUIRED and
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
306 modernssl and not sslcontext.get_ca_certs()):
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
307 ui.warn(_('(an attempt was made to load CA certificates but none '
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
308 'were loaded; see '
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
309 'https://mercurial-scm.org/wiki/SecureConnections for '
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
310 'how to configure Mercurial to avoid this error)\n'))
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
311 raise
5b71a8d7f7ff sslutil: emit warning when no CA certificates loaded
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29447
diff changeset
312
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
313 # check if wrap_socket failed silently because socket had been
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
314 # closed
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
315 # - see http://bugs.python.org/issue13721
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
316 if not sslsocket.cipher():
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
317 raise error.Abort(_('ssl connection failed'))
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
318
29225
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29224
diff changeset
319 sslsocket._hgstate = {
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29224
diff changeset
320 'caloaded': caloaded,
29226
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29225
diff changeset
321 'hostname': serverhostname,
29259
ec247e8595f9 sslutil: move SSLContext.verify_mode value into _hostsettings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29258
diff changeset
322 'settings': settings,
29226
33006bd6a1d7 sslutil: store and use hostname and ui in socket instance
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29225
diff changeset
323 'ui': ui,
29225
b115eed11780 sslutil: use a dict for hanging hg state off the wrapped socket
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29224
diff changeset
324 }
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
325
28652
c617614aefd2 sslutil: remove indentation in wrapsocket declaration
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28651
diff changeset
326 return sslsocket
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
327
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
328 class wildcarderror(Exception):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
329 """Represents an error parsing wildcards in DNS name."""
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
330
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
331 def _dnsnamematch(dn, hostname, maxwildcards=1):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
332 """Match DNS names according RFC 6125 section 6.4.3.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
333
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
334 This code is effectively copied from CPython's ssl._dnsname_match.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
335
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
336 Returns a bool indicating whether the expected hostname matches
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
337 the value in ``dn``.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
338 """
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
339 pats = []
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
340 if not dn:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
341 return False
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
342
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
343 pieces = dn.split(r'.')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
344 leftmost = pieces[0]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
345 remainder = pieces[1:]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
346 wildcards = leftmost.count('*')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
347 if wildcards > maxwildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
348 raise wildcarderror(
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
349 _('too many wildcards in certificate DNS name: %s') % dn)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
350
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
351 # speed up common case w/o wildcards
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
352 if not wildcards:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
353 return dn.lower() == hostname.lower()
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
354
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
355 # RFC 6125, section 6.4.3, subitem 1.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
356 # The client SHOULD NOT attempt to match a presented identifier in which
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
357 # the wildcard character comprises a label other than the left-most label.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
358 if leftmost == '*':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
359 # When '*' is a fragment by itself, it matches a non-empty dotless
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
360 # fragment.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
361 pats.append('[^.]+')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
362 elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
363 # RFC 6125, section 6.4.3, subitem 3.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
364 # The client SHOULD NOT attempt to match a presented identifier
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
365 # where the wildcard character is embedded within an A-label or
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
366 # U-label of an internationalized domain name.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
367 pats.append(re.escape(leftmost))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
368 else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
369 # Otherwise, '*' matches any dotless string, e.g. www*
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
370 pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
371
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
372 # add the remaining fragments, ignore any wildcards
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
373 for frag in remainder:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
374 pats.append(re.escape(frag))
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
375
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
376 pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
377 return pat.match(hostname) is not None
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
378
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
379 def _verifycert(cert, hostname):
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
380 '''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
381 CRLs is not handled.
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
382
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
383 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
384 '''
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
385 if not cert:
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
386 return _('no certificate received')
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
387
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
388 dnsnames = []
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
389 san = cert.get('subjectAltName', [])
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
390 for key, value in san:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
391 if key == 'DNS':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
392 try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
393 if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
394 return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
395 except wildcarderror as e:
29460
a7d1532b26a1 sslutil: don't access message attribute in exception (issue5285)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29452
diff changeset
396 return e.args[0]
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
397
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
398 dnsnames.append(value)
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
399
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
400 if not dnsnames:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
401 # The subject is only checked when there is no DNS in subjectAltName.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
402 for sub in cert.get('subject', []):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
403 for key, value in sub:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
404 # According to RFC 2818 the most specific Common Name must
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
405 # be used.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
406 if key == 'commonName':
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
407 # 'subject' entries are unicide.
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
408 try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
409 value = value.encode('ascii')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
410 except UnicodeEncodeError:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
411 return _('IDN in certificate not supported')
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
412
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
413 try:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
414 if _dnsnamematch(value, hostname):
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
415 return
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
416 except wildcarderror as e:
29460
a7d1532b26a1 sslutil: don't access message attribute in exception (issue5285)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29452
diff changeset
417 return e.args[0]
29452
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
418
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
419 dnsnames.append(value)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
420
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
421 if len(dnsnames) > 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
422 return _('certificate is for %s') % ', '.join(dnsnames)
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
423 elif len(dnsnames) == 1:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
424 return _('certificate is for %s') % dnsnames[0]
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
425 else:
26a5d605b868 sslutil: synchronize hostname matching logic with CPython
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29042
diff changeset
426 return _('no commonName or subjectAltName found in certificate')
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
427
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
428 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
429 """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
430 * 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
431 system
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
432 * 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
433 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
434 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
435 """
24614
241d98d84aed ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents: 24291
diff changeset
436 if sys.platform != 'darwin' or util.mainfrozen() or not sys.executable:
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
437 return False
24614
241d98d84aed ssl: resolve symlink before checking for Apple python executable (issue4588)
Yuya Nishihara <yuya@tcha.org>
parents: 24291
diff changeset
438 exe = os.path.realpath(sys.executable).lower()
23042
2cd3fa4412dc ssl: only use the dummy cert hack if using an Apple Python (issue4410)
Mads Kiilerich <madski@unity3d.com>
parents: 22575
diff changeset
439 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
440 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
441
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
442 _systemcacertpaths = [
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
443 # RHEL, CentOS, and Fedora
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
444 '/etc/pki/tls/certs/ca-bundle.trust.crt',
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
445 # Debian, Ubuntu, Gentoo
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
446 '/etc/ssl/certs/ca-certificates.crt',
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
447 ]
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
448
29483
918dce4b8c26 sslutil: pass ui to _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29482
diff changeset
449 def _defaultcacerts(ui):
29488
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
450 """return path to default CA certificates or None.
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
451
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
452 It is assumed this function is called when the returned certificates
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
453 file will actually be used to validate connections. Therefore this
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
454 function may print warnings or debug messages assuming this usage.
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
455
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
456 We don't print a message when the Python is able to load default
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
457 CA certs because this scenario is detected at socket connect time.
29488
1c26b9ce66f8 sslutil: expand _defaultcacerts docstring to note calling assumptions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29487
diff changeset
458 """
29486
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
459 # The "certifi" Python package provides certificates. If it is installed,
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
460 # assume the user intends it to be used and use it.
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
461 try:
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
462 import certifi
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
463 certs = certifi.where()
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
464 ui.debug('using ca certificates from certifi\n')
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
465 return certs
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
466 except ImportError:
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
467 pass
a62c00f6dd04 sslutil: use certificates provided by certifi if available
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29484
diff changeset
468
29489
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
469 # On Windows, only the modern ssl module is capable of loading the system
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
470 # CA certificates. If we're not capable of doing that, emit a warning
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
471 # because we'll get a certificate verification error later and the lack
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
472 # of loaded CA certificates will be the reason why.
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
473 # Assertion: this code is only called if certificates are being verified.
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
474 if os.name == 'nt':
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
475 if not _canloaddefaultcerts:
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
476 ui.warn(_('(unable to load Windows CA certificates; see '
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
477 'https://mercurial-scm.org/wiki/SecureConnections for '
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
478 'how to configure Mercurial to avoid this message)\n'))
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
479
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
480 return None
54ad81b0665f sslutil: handle default CA certificate loading on Windows
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29488
diff changeset
481
29487
cdcb5747dc88 sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29486
diff changeset
482 # Apple's OpenSSL has patches that allow a specially constructed certificate
cdcb5747dc88 sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29486
diff changeset
483 # to load the system CA store. If we're running on Apple Python, use this
cdcb5747dc88 sslutil: document the Apple OpenSSL cert trick
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29486
diff changeset
484 # trick.
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
485 if _plainapplepython():
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
486 dummycert = os.path.join(os.path.dirname(__file__), 'dummycert.pem')
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
487 if os.path.exists(dummycert):
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
488 return dummycert
29107
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29106
diff changeset
489
29499
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
490 # The Apple OpenSSL trick isn't available to us. If Python isn't able to
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
491 # load system certs, we're out of luck.
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
492 if sys.platform == 'darwin':
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
493 # FUTURE Consider looking for Homebrew or MacPorts installed certs
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
494 # files. Also consider exporting the keychain certs to a file during
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
495 # Mercurial install.
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
496 if not _canloaddefaultcerts:
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
497 ui.warn(_('(unable to load CA certificates; see '
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
498 'https://mercurial-scm.org/wiki/SecureConnections for '
9c5325c79683 sslutil: issue warning when unable to load certificates on OS X
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29489
diff changeset
499 'how to configure Mercurial to avoid this message)\n'))
24291
760a86865f80 ssl: load CA certificates from system's store by default on Python 2.7.9
Yuya Nishihara <yuya@tcha.org>
parents: 24290
diff changeset
500 return None
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
501
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
502 # Try to find CA certificates in well-known locations. We print a warning
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
503 # when using a found file because we don't want too much silent magic
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
504 # for security settings. The expectation is that proper Mercurial
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
505 # installs will have the CA certs path defined at install time and the
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
506 # installer/packager will make an appropriate decision on the user's
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
507 # behalf. We only get here and perform this setting as a feature of
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
508 # last resort.
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
509 if not _canloaddefaultcerts:
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
510 for path in _systemcacertpaths:
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
511 if os.path.isfile(path):
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
512 ui.warn(_('(using CA certificates from %s; if you see this '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
513 'message, your Mercurial install is not properly '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
514 'configured; see '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
515 'https://mercurial-scm.org/wiki/SecureConnections '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
516 'for how to configure Mercurial to avoid this '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
517 'message)\n') % path)
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
518 return path
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
519
29500
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
520 ui.warn(_('(unable to load CA certificates; see '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
521 'https://mercurial-scm.org/wiki/SecureConnections for '
4b16a5bd9948 sslutil: try to find CA certficates in well-known locations
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29499
diff changeset
522 'how to configure Mercurial to avoid this message)\n'))
14204
5fa21960b2f4 sslutil: extracted ssl methods from httpsconnection in url.py
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
523
29107
c8fbfb9163ce sslutil: move code examining _canloaddefaultcerts out of _defaultcacerts
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29106
diff changeset
524 return None
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
525
29286
a05a91a3f120 sslutil: remove "strict" argument from validatesocket()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29268
diff changeset
526 def validatesocket(sock):
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
527 """Validate a socket meets security requiremnets.
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
528
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
529 The passed socket must have been created with ``wrapsocket()``.
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
530 """
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
531 host = sock._hgstate['hostname']
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
532 ui = sock._hgstate['ui']
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
533 settings = sock._hgstate['settings']
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
534
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
535 try:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
536 peercert = sock.getpeercert(True)
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
537 peercert2 = sock.getpeercert()
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
538 except AttributeError:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
539 raise error.Abort(_('%s ssl connection error') % host)
24288
922e087ba158 ssl: extract function that returns dummycert path on Apple python
Yuya Nishihara <yuya@tcha.org>
parents: 23851
diff changeset
540
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
541 if not peercert:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
542 raise error.Abort(_('%s certificate error: '
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
543 'no certificate received') % host)
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
544
29289
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
545 if settings['disablecertverification']:
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
546 # We don't print the certificate fingerprint because it shouldn't
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
547 # be necessary: if the user requested certificate verification be
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
548 # disabled, they presumably already saw a message about the inability
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
549 # to verify the certificate and this message would have printed the
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
550 # fingerprint. So printing the fingerprint here adds little to no
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
551 # value.
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
552 ui.warn(_('warning: connection security to %s is disabled per current '
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
553 'settings; communication is susceptible to eavesdropping '
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
554 'and tampering\n') % host)
3536673a25ae sslutil: move and change warning when cert verification is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29288
diff changeset
555 return
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
556
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
557 # If a certificate fingerprint is pinned, use it and only it to
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
558 # validate the remote cert.
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
559 peerfingerprints = {
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29334
diff changeset
560 'sha1': hashlib.sha1(peercert).hexdigest(),
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29334
diff changeset
561 'sha256': hashlib.sha256(peercert).hexdigest(),
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29334
diff changeset
562 'sha512': hashlib.sha512(peercert).hexdigest(),
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
563 }
18879
93b03a222c3e sslutil: try harder to avoid getpeercert problems
Matt Mackall <mpm@selenic.com>
parents: 16391
diff changeset
564
29290
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
565 def fmtfingerprint(s):
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
566 return ':'.join([s[x:x + 2] for x in range(0, len(s), 2)])
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
567
01248c37a68e sslutil: print SHA-256 fingerprint by default
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29289
diff changeset
568 nicefingerprint = 'sha256:%s' % fmtfingerprint(peerfingerprints['sha256'])
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
569
29258
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
570 if settings['certfingerprints']:
6315c1e14f75 sslutil: introduce a function for determining host-specific settings
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29253
diff changeset
571 for hash, fingerprint in settings['certfingerprints']:
29262
dfc4f08aa160 sslutil: calculate host fingerprints from additional algorithms
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29260
diff changeset
572 if peerfingerprints[hash].lower() == fingerprint:
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
573 ui.debug('%s certificate matched fingerprint %s:%s\n' %
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
574 (host, hash, fmtfingerprint(fingerprint)))
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
575 return
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
576
29293
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
577 # Pinned fingerprint didn't match. This is a fatal error.
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
578 if settings['legacyfingerprint']:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
579 section = 'hostfingerprint'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
580 nice = fmtfingerprint(peerfingerprints['sha1'])
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
581 else:
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
582 section = 'hostsecurity'
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
583 nice = '%s:%s' % (hash, fmtfingerprint(peerfingerprints[hash]))
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
584 raise error.Abort(_('certificate for %s has unexpected '
29293
1b3a0b0c414f sslutil: print the fingerprint from the last hash used
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29292
diff changeset
585 'fingerprint %s') % (host, nice),
29291
15e533b7909c sslutil: refactor code for fingerprint matching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29290
diff changeset
586 hint=_('check %s configuration') % section)
28850
3819c349b194 sslutil: document and slightly refactor validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28849
diff changeset
587
29411
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
588 # Security is enabled but no CAs are loaded. We can't establish trust
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
589 # for the cert so abort.
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
590 if not sock._hgstate['caloaded']:
29411
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
591 raise error.Abort(
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
592 _('unable to verify security of %s (no loaded CA certificates); '
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
593 'refusing to connect') % host,
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
594 hint=_('see https://mercurial-scm.org/wiki/SecureConnections for '
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
595 'how to configure Mercurial to avoid this error or set '
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
596 'hostsecurity.%s:fingerprints=%s to trust this server') %
e1778b9c8d53 sslutil: abort when unable to verify peer connection (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29410
diff changeset
597 (host, nicefingerprint))
29113
5b9577edf745 sslutil: use CA loaded state to drive validation logic
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29112
diff changeset
598
29227
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
599 msg = _verifycert(peercert2, host)
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
600 if msg:
dffe78d80a6c sslutil: convert socket validation from a class to a function (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29226
diff changeset
601 raise error.Abort(_('%s certificate error: %s') % (host, msg),
29292
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
602 hint=_('set hostsecurity.%s:certfingerprints=%s '
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
603 'config setting or use --insecure to connect '
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
604 'insecurely') %
bc5f55493397 sslutil: make cert fingerprints messages more actionable
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29291
diff changeset
605 (host, nicefingerprint))