31 |
31 |
32 # Python 2.7.9+ overhauled the built-in SSL/TLS features of Python. It added |
32 # Python 2.7.9+ overhauled the built-in SSL/TLS features of Python. It added |
33 # support for TLS 1.1, TLS 1.2, SNI, system CA stores, etc. These features are |
33 # support for TLS 1.1, TLS 1.2, SNI, system CA stores, etc. These features are |
34 # all exposed via the "ssl" module. |
34 # all exposed via the "ssl" module. |
35 # |
35 # |
36 # Depending on the version of Python being used, SSL/TLS support is either |
36 # We require in setup.py the presence of ssl.SSLContext, which indicates modern |
37 # modern/secure or legacy/insecure. Many operations in this module have |
37 # SSL/TLS support. |
38 # separate code paths depending on support in Python. |
|
39 |
38 |
40 configprotocols = { |
39 configprotocols = { |
41 b'tls1.0', |
40 b'tls1.0', |
42 b'tls1.1', |
41 b'tls1.1', |
43 b'tls1.2', |
42 b'tls1.2', |
51 if util.safehasattr(ssl, b'PROTOCOL_TLSv1_1'): |
50 if util.safehasattr(ssl, b'PROTOCOL_TLSv1_1'): |
52 supportedprotocols.add(b'tls1.1') |
51 supportedprotocols.add(b'tls1.1') |
53 if util.safehasattr(ssl, b'PROTOCOL_TLSv1_2'): |
52 if util.safehasattr(ssl, b'PROTOCOL_TLSv1_2'): |
54 supportedprotocols.add(b'tls1.2') |
53 supportedprotocols.add(b'tls1.2') |
55 |
54 |
56 try: |
55 modernssl = True |
57 # ssl.SSLContext was added in 2.7.9 and presence indicates modern |
56 _canloaddefaultcerts = True |
58 # SSL/TLS features are available. |
|
59 SSLContext = ssl.SSLContext |
|
60 modernssl = True |
|
61 _canloaddefaultcerts = True |
|
62 except AttributeError: |
|
63 modernssl = False |
|
64 _canloaddefaultcerts = False |
|
65 |
|
66 # We implement SSLContext using the interface from the standard library. |
|
67 class SSLContext(object): |
|
68 def __init__(self, protocol): |
|
69 # From the public interface of SSLContext |
|
70 self.protocol = protocol |
|
71 self.check_hostname = False |
|
72 self.options = 0 |
|
73 self.verify_mode = ssl.CERT_NONE |
|
74 |
|
75 # Used by our implementation. |
|
76 self._certfile = None |
|
77 self._keyfile = None |
|
78 self._certpassword = None |
|
79 self._cacerts = None |
|
80 self._ciphers = None |
|
81 |
|
82 def load_cert_chain(self, certfile, keyfile=None, password=None): |
|
83 self._certfile = certfile |
|
84 self._keyfile = keyfile |
|
85 self._certpassword = password |
|
86 |
|
87 def load_default_certs(self, purpose=None): |
|
88 pass |
|
89 |
|
90 def load_verify_locations(self, cafile=None, capath=None, cadata=None): |
|
91 if capath: |
|
92 raise error.Abort(_(b'capath not supported')) |
|
93 if cadata: |
|
94 raise error.Abort(_(b'cadata not supported')) |
|
95 |
|
96 self._cacerts = cafile |
|
97 |
|
98 def set_ciphers(self, ciphers): |
|
99 self._ciphers = ciphers |
|
100 |
|
101 def wrap_socket(self, socket, server_hostname=None, server_side=False): |
|
102 # server_hostname is unique to SSLContext.wrap_socket and is used |
|
103 # for SNI in that context. So there's nothing for us to do with it |
|
104 # in this legacy code since we don't support SNI. |
|
105 |
|
106 args = { |
|
107 'keyfile': self._keyfile, |
|
108 'certfile': self._certfile, |
|
109 'server_side': server_side, |
|
110 'cert_reqs': self.verify_mode, |
|
111 'ssl_version': self.protocol, |
|
112 'ca_certs': self._cacerts, |
|
113 'ciphers': self._ciphers, |
|
114 } |
|
115 |
|
116 return ssl.wrap_socket(socket, **args) |
|
117 |
57 |
118 |
58 |
119 def _hostsettings(ui, hostname): |
59 def _hostsettings(ui, hostname): |
120 """Obtain security settings for a hostname. |
60 """Obtain security settings for a hostname. |
121 |
61 |
412 # have explicit control over CA loading because implicitly loading |
352 # have explicit control over CA loading because implicitly loading |
413 # CAs may undermine the user's intent. For example, a user may define a CA |
353 # CAs may undermine the user's intent. For example, a user may define a CA |
414 # bundle with a specific CA cert removed. If the system/default CA bundle |
354 # bundle with a specific CA cert removed. If the system/default CA bundle |
415 # is loaded and contains that removed CA, you've just undone the user's |
355 # is loaded and contains that removed CA, you've just undone the user's |
416 # choice. |
356 # choice. |
417 sslcontext = SSLContext(settings[b'protocol']) |
357 sslcontext = ssl.SSLContext(settings[b'protocol']) |
418 |
358 |
419 # This is a no-op unless using modern ssl. |
359 # This is a no-op unless using modern ssl. |
420 sslcontext.options |= settings[b'ctxoptions'] |
360 sslcontext.options |= settings[b'ctxoptions'] |
421 |
361 |
422 # This still works on our fake SSLContext. |
362 # This still works on our fake SSLContext. |
640 |
580 |
641 if modernssl: |
581 if modernssl: |
642 # We /could/ use create_default_context() here since it doesn't load |
582 # We /could/ use create_default_context() here since it doesn't load |
643 # CAs when configured for client auth. However, it is hard-coded to |
583 # CAs when configured for client auth. However, it is hard-coded to |
644 # use ssl.PROTOCOL_SSLv23 which may not be appropriate here. |
584 # use ssl.PROTOCOL_SSLv23 which may not be appropriate here. |
645 sslcontext = SSLContext(protocol) |
585 sslcontext = ssl.SSLContext(protocol) |
646 sslcontext.options |= options |
586 sslcontext.options |= options |
647 |
587 |
648 # Improve forward secrecy. |
588 # Improve forward secrecy. |
649 sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0) |
589 sslcontext.options |= getattr(ssl, 'OP_SINGLE_DH_USE', 0) |
650 sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0) |
590 sslcontext.options |= getattr(ssl, 'OP_SINGLE_ECDH_USE', 0) |
652 # Use the list of more secure ciphers if found in the ssl module. |
592 # Use the list of more secure ciphers if found in the ssl module. |
653 if util.safehasattr(ssl, b'_RESTRICTED_SERVER_CIPHERS'): |
593 if util.safehasattr(ssl, b'_RESTRICTED_SERVER_CIPHERS'): |
654 sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0) |
594 sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0) |
655 sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS) |
595 sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS) |
656 else: |
596 else: |
657 sslcontext = SSLContext(ssl.PROTOCOL_TLSv1) |
597 sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1) |
658 |
598 |
659 if requireclientcert: |
599 if requireclientcert: |
660 sslcontext.verify_mode = ssl.CERT_REQUIRED |
600 sslcontext.verify_mode = ssl.CERT_REQUIRED |
661 else: |
601 else: |
662 sslcontext.verify_mode = ssl.CERT_NONE |
602 sslcontext.verify_mode = ssl.CERT_NONE |