From 61d478c71c5341cdc54e6bfb4ace4252852fd972 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Sat, 27 Jan 2018 15:51:38 +0100 Subject: bpo-31399: Let OpenSSL verify hostname and IP address (#3462) bpo-31399: Let OpenSSL verify hostname and IP The ssl module now uses OpenSSL's X509_VERIFY_PARAM_set1_host() and X509_VERIFY_PARAM_set1_ip() API to verify hostname and IP addresses. * Remove match_hostname calls * Check for libssl with set1_host, libssl must provide X509_VERIFY_PARAM_set1_host() * Add documentation for OpenSSL 1.0.2 requirement * Don't support OpenSSL special mode with a leading dot, e.g. ".example.org" matches "www.example.org". It's not standard conform. * Add hostname_checks_common_name Signed-off-by: Christian Heimes --- Lib/ssl.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'Lib/ssl.py') diff --git a/Lib/ssl.py b/Lib/ssl.py index 7c4cccf4c0..5f972e1d3d 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -148,7 +148,6 @@ _IntEnum._convert( lambda name: name.startswith('CERT_'), source=_ssl) - PROTOCOL_SSLv23 = _SSLMethod.PROTOCOL_SSLv23 = _SSLMethod.PROTOCOL_TLS _PROTOCOL_NAMES = {value: name for name, value in _SSLMethod.__members__.items()} @@ -172,6 +171,8 @@ if _ssl.HAS_TLS_UNIQUE: else: CHANNEL_BINDING_TYPES = [] +HAS_NEVER_CHECK_COMMON_NAME = hasattr(_ssl, 'HOSTFLAG_NEVER_CHECK_SUBJECT') + # Disable weak or insecure ciphers by default # (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL') @@ -216,9 +217,7 @@ _RESTRICTED_SERVER_CIPHERS = ( '!aNULL:!eNULL:!MD5:!DSS:!RC4:!3DES' ) - -class CertificateError(ValueError): - pass +CertificateError = SSLCertVerificationError def _dnsname_match(dn, hostname): @@ -473,6 +472,23 @@ class SSLContext(_SSLContext): def options(self, value): super(SSLContext, SSLContext).options.__set__(self, value) + if hasattr(_ssl, 'HOSTFLAG_NEVER_CHECK_SUBJECT'): + @property + def hostname_checks_common_name(self): + ncs = self._host_flags & _ssl.HOSTFLAG_NEVER_CHECK_SUBJECT + return ncs != _ssl.HOSTFLAG_NEVER_CHECK_SUBJECT + + @hostname_checks_common_name.setter + def hostname_checks_common_name(self, value): + if value: + self._host_flags &= ~_ssl.HOSTFLAG_NEVER_CHECK_SUBJECT + else: + self._host_flags |= _ssl.HOSTFLAG_NEVER_CHECK_SUBJECT + else: + @property + def hostname_checks_common_name(self): + return True + @property def verify_flags(self): return VerifyFlags(super().verify_flags) @@ -699,11 +715,6 @@ class SSLObject: def do_handshake(self): """Start the SSL/TLS handshake.""" self._sslobj.do_handshake() - if self.context.check_hostname: - if not self.server_hostname: - raise ValueError("check_hostname needs server_hostname " - "argument") - match_hostname(self.getpeercert(), self.server_hostname) def unwrap(self): """Start the SSL shutdown handshake.""" -- cgit v1.2.1