48 # 3.7. Prior to CPython commit 6e8cda91d92da72800d891b2fc2073ecbc134d98 |
48 # 3.7. Prior to CPython commit 6e8cda91d92da72800d891b2fc2073ecbc134d98 |
49 # (backported to the 3.7 branch), ssl.PROTOCOL_TLSv1_1 / ssl.PROTOCOL_TLSv1_2 |
49 # (backported to the 3.7 branch), ssl.PROTOCOL_TLSv1_1 / ssl.PROTOCOL_TLSv1_2 |
50 # were defined only if compiled against a OpenSSL version with TLS 1.1 / 1.2 |
50 # were defined only if compiled against a OpenSSL version with TLS 1.1 / 1.2 |
51 # support. At the mentioned commit, they were unconditionally defined. |
51 # support. At the mentioned commit, they were unconditionally defined. |
52 supportedprotocols = set() |
52 supportedprotocols = set() |
53 if getattr(ssl, 'HAS_TLSv1', util.safehasattr(ssl, 'PROTOCOL_TLSv1')): |
53 if getattr(ssl, 'HAS_TLSv1', hasattr(ssl, 'PROTOCOL_TLSv1')): |
54 supportedprotocols.add(b'tls1.0') |
54 supportedprotocols.add(b'tls1.0') |
55 if getattr(ssl, 'HAS_TLSv1_1', util.safehasattr(ssl, 'PROTOCOL_TLSv1_1')): |
55 if getattr(ssl, 'HAS_TLSv1_1', hasattr(ssl, 'PROTOCOL_TLSv1_1')): |
56 supportedprotocols.add(b'tls1.1') |
56 supportedprotocols.add(b'tls1.1') |
57 if getattr(ssl, 'HAS_TLSv1_2', util.safehasattr(ssl, 'PROTOCOL_TLSv1_2')): |
57 if getattr(ssl, 'HAS_TLSv1_2', hasattr(ssl, 'PROTOCOL_TLSv1_2')): |
58 supportedprotocols.add(b'tls1.2') |
58 supportedprotocols.add(b'tls1.2') |
59 |
59 |
60 |
60 |
61 def _hostsettings(ui, hostname): |
61 def _hostsettings(ui, hostname): |
62 """Obtain security settings for a hostname. |
62 """Obtain security settings for a hostname. |
310 # CAs may undermine the user's intent. For example, a user may define a CA |
310 # CAs may undermine the user's intent. For example, a user may define a CA |
311 # bundle with a specific CA cert removed. If the system/default CA bundle |
311 # bundle with a specific CA cert removed. If the system/default CA bundle |
312 # is loaded and contains that removed CA, you've just undone the user's |
312 # is loaded and contains that removed CA, you've just undone the user's |
313 # choice. |
313 # choice. |
314 |
314 |
315 if util.safehasattr(ssl, 'TLSVersion'): |
315 if hasattr(ssl, 'TLSVersion'): |
316 # python 3.7+ |
316 # python 3.7+ |
317 sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
317 sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
318 minimumprotocol = settings[b'minimumprotocol'] |
318 minimumprotocol = settings[b'minimumprotocol'] |
319 if minimumprotocol == b'tls1.0': |
319 if minimumprotocol == b'tls1.0': |
320 with warnings.catch_warnings(): |
320 with warnings.catch_warnings(): |
417 ) |
417 ) |
418 except ssl.SSLError: |
418 except ssl.SSLError: |
419 pass |
419 pass |
420 |
420 |
421 # Try to print more helpful error messages for known failures. |
421 # Try to print more helpful error messages for known failures. |
422 if util.safehasattr(e, 'reason'): |
422 if hasattr(e, 'reason'): |
423 # This error occurs when the client and server don't share a |
423 # This error occurs when the client and server don't share a |
424 # common/supported SSL/TLS protocol. We've disabled SSLv2 and SSLv3 |
424 # common/supported SSL/TLS protocol. We've disabled SSLv2 and SSLv3 |
425 # outright. Hopefully the reason for this error is that we require |
425 # outright. Hopefully the reason for this error is that we require |
426 # TLS 1.1+ and the server only supports TLS 1.0. Whatever the |
426 # TLS 1.1+ and the server only supports TLS 1.0. Whatever the |
427 # reason, try to emit an actionable warning. |
427 # reason, try to emit an actionable warning. |
544 if f and not os.path.exists(f): |
544 if f and not os.path.exists(f): |
545 raise error.Abort( |
545 raise error.Abort( |
546 _(b'referenced certificate file (%s) does not exist') % f |
546 _(b'referenced certificate file (%s) does not exist') % f |
547 ) |
547 ) |
548 |
548 |
549 if util.safehasattr(ssl, 'TLSVersion'): |
549 if hasattr(ssl, 'TLSVersion'): |
550 # python 3.7+ |
550 # python 3.7+ |
551 sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
551 sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
552 sslcontext.options |= getattr(ssl, 'OP_NO_COMPRESSION', 0) |
552 sslcontext.options |= getattr(ssl, 'OP_NO_COMPRESSION', 0) |
553 |
553 |
554 # This config option is intended for use in tests only. It is a giant |
554 # This config option is intended for use in tests only. It is a giant |
626 |
626 |
627 # In tests, allow insecure ciphers |
627 # In tests, allow insecure ciphers |
628 # Otherwise, use the list of more secure ciphers if found in the ssl module. |
628 # Otherwise, use the list of more secure ciphers if found in the ssl module. |
629 if exactprotocol: |
629 if exactprotocol: |
630 sslcontext.set_ciphers('DEFAULT:@SECLEVEL=0') |
630 sslcontext.set_ciphers('DEFAULT:@SECLEVEL=0') |
631 elif util.safehasattr(ssl, '_RESTRICTED_SERVER_CIPHERS'): |
631 elif hasattr(ssl, '_RESTRICTED_SERVER_CIPHERS'): |
632 sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0) |
632 sslcontext.options |= getattr(ssl, 'OP_CIPHER_SERVER_PREFERENCE', 0) |
633 # pytype: disable=module-attr |
633 # pytype: disable=module-attr |
634 sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS) |
634 sslcontext.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS) |
635 # pytype: enable=module-attr |
635 # pytype: enable=module-attr |
636 |
636 |