summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorChristian Heimes <christian@python.org>2018-01-27 14:51:38 (GMT)
committerGitHub <noreply@github.com>2018-01-27 14:51:38 (GMT)
commit61d478c71c5341cdc54e6bfb4ace4252852fd972 (patch)
tree5ad17242b4c341df03664ee5cde87cdb80b0ee50 /Lib/test
parent746cc75541f31278864a10b995e7d009bd2ff053 (diff)
downloadcpython-61d478c71c5341cdc54e6bfb4ace4252852fd972.zip
cpython-61d478c71c5341cdc54e6bfb4ace4252852fd972.tar.gz
cpython-61d478c71c5341cdc54e6bfb4ace4252852fd972.tar.bz2
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 <christian@python.org>
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/test_asyncio/test_events.py6
-rw-r--r--Lib/test/test_ftplib.py3
-rw-r--r--Lib/test/test_imaplib.py6
-rw-r--r--Lib/test/test_poplib.py3
-rw-r--r--Lib/test/test_ssl.py28
-rw-r--r--Lib/test/test_urllib2_localnet.py2
6 files changed, 41 insertions, 7 deletions
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
index e4b0536..cf21753 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -1148,11 +1148,13 @@ class EventLoopTestsMixin:
with test_utils.disable_logger():
with self.assertRaisesRegex(
ssl.CertificateError,
- "hostname '127.0.0.1' doesn't match 'localhost'"):
+ "IP address mismatch, certificate is not valid for "
+ "'127.0.0.1'"):
self.loop.run_until_complete(f_c)
# close connection
- proto.transport.close()
+ # transport is None because TLS ALERT aborted the handshake
+ self.assertIsNone(proto.transport)
server.close()
@support.skip_unless_bind_unix_socket
diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py
index f1b0185..bb5a67f 100644
--- a/Lib/test/test_ftplib.py
+++ b/Lib/test/test_ftplib.py
@@ -330,6 +330,9 @@ if ssl is not None:
return
elif err.args[0] == ssl.SSL_ERROR_EOF:
return self.handle_close()
+ # TODO: SSLError does not expose alert information
+ elif "SSLV3_ALERT_BAD_CERTIFICATE" in err.args[1]:
+ return self.handle_close()
raise
except OSError as err:
if err.args[0] == errno.ECONNABORTED:
diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py
index 4a45be6..f16bacd 100644
--- a/Lib/test/test_imaplib.py
+++ b/Lib/test/test_imaplib.py
@@ -485,7 +485,8 @@ class NewIMAPSSLTests(NewIMAPTestsMixin, unittest.TestCase):
ssl_context.load_verify_locations(CAFILE)
with self.assertRaisesRegex(ssl.CertificateError,
- "hostname '127.0.0.1' doesn't match 'localhost'"):
+ "IP address mismatch, certificate is not valid for "
+ "'127.0.0.1'"):
_, server = self._setup(SimpleIMAPHandler)
client = self.imap_class(*server.server_address,
ssl_context=ssl_context)
@@ -874,7 +875,8 @@ class ThreadedNetworkedTestsSSL(ThreadedNetworkedTests):
with self.assertRaisesRegex(
ssl.CertificateError,
- "hostname '127.0.0.1' doesn't match 'localhost'"):
+ "IP address mismatch, certificate is not valid for "
+ "'127.0.0.1'"):
with self.reaped_server(SimpleIMAPHandler) as server:
client = self.imap_class(*server.server_address,
ssl_context=ssl_context)
diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py
index 9ba678f..4d7a439 100644
--- a/Lib/test/test_poplib.py
+++ b/Lib/test/test_poplib.py
@@ -176,6 +176,9 @@ class DummyPOP3Handler(asynchat.async_chat):
return
elif err.args[0] == ssl.SSL_ERROR_EOF:
return self.handle_close()
+ # TODO: SSLError does not expose alert information
+ elif "SSLV3_ALERT_BAD_CERTIFICATE" in err.args[1]:
+ return self.handle_close()
raise
except OSError as err:
if err.args[0] == errno.ECONNABORTED:
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index e3fa423..fdf727f 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -988,6 +988,19 @@ class ContextTests(unittest.TestCase):
self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
self.assertTrue(ctx.check_hostname)
+ def test_hostname_checks_common_name(self):
+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
+ self.assertTrue(ctx.hostname_checks_common_name)
+ if ssl.HAS_NEVER_CHECK_COMMON_NAME:
+ ctx.hostname_checks_common_name = True
+ self.assertTrue(ctx.hostname_checks_common_name)
+ ctx.hostname_checks_common_name = False
+ self.assertFalse(ctx.hostname_checks_common_name)
+ ctx.hostname_checks_common_name = True
+ self.assertTrue(ctx.hostname_checks_common_name)
+ else:
+ with self.assertRaises(AttributeError):
+ ctx.hostname_checks_common_name = True
@unittest.skipUnless(have_verify_flags(),
"verify_flags need OpenSSL > 0.9.8")
@@ -1511,6 +1524,16 @@ class SSLErrorTests(unittest.TestCase):
ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
server_hostname="xn--.com")
+ def test_bad_server_hostname(self):
+ ctx = ssl.create_default_context()
+ with self.assertRaises(ValueError):
+ ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
+ server_hostname="")
+ with self.assertRaises(ValueError):
+ ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(),
+ server_hostname=".example.org")
+
+
class MemoryBIOTests(unittest.TestCase):
def test_read_write(self):
@@ -2536,8 +2559,9 @@ class ThreadedTests(unittest.TestCase):
with server:
with client_context.wrap_socket(socket.socket(),
server_hostname="invalid") as s:
- with self.assertRaisesRegex(ssl.CertificateError,
- "hostname 'invalid' doesn't match 'localhost'"):
+ with self.assertRaisesRegex(
+ ssl.CertificateError,
+ "Hostname mismatch, certificate is not valid for 'invalid'."):
s.connect((HOST, server.port))
# missing server_hostname arg should cause an exception, too
diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py
index b2d1e5f..52c897a 100644
--- a/Lib/test/test_urllib2_localnet.py
+++ b/Lib/test/test_urllib2_localnet.py
@@ -573,7 +573,7 @@ class TestUrlopen(unittest.TestCase):
cafile=CERT_fakehostname)
# Good cert, but mismatching hostname
handler = self.start_https_server(certfile=CERT_fakehostname)
- with self.assertRaises(ssl.CertificateError) as cm:
+ with self.assertRaises(urllib.error.URLError) as cm:
self.urlopen("https://localhost:%s/bizarre" % handler.port,
cafile=CERT_fakehostname)