Skip to content

Commit

Permalink
tests: Update SSL network tests to use SSLContext, and work on CPython.
Browse files Browse the repository at this point in the history
Changes are:
- use ssl.SSLContext.wrap_socket instead of ssl.wrap_socket
- disable check_hostname and call load_default_certs() where appropriate,
  to get CPython to run the tests correctly
- pass socket.AF_INET to getaddrinfo and socket.socket(), to force IPv4
- change tests to use github.com instead of google.com, because certificate
  validation was failing with google.com

Signed-off-by: Damien George <damien@micropython.org>
  • Loading branch information
dpgeorge committed Dec 12, 2023
1 parent ef996d1 commit bba8a67
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 44 deletions.
9 changes: 5 additions & 4 deletions tests/net_hosted/connect_nonblock_xfer.py
Expand Up @@ -27,11 +27,12 @@ def do_connect(peer_addr, tls, handshake):
print(" got", er.errno)
# wrap with ssl/tls if desired
if tls:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
if hasattr(ssl_context, "check_hostname"):
ssl_context.check_hostname = False

try:
if sys.implementation.name == "micropython":
s = ssl.wrap_socket(s, do_handshake=handshake)
else:
s = ssl.wrap_socket(s, do_handshake_on_connect=handshake)
s = ssl_context.wrap_socket(s, do_handshake_on_connect=handshake)
print("wrap: True")
except Exception as e:
dp(e)
Expand Down
28 changes: 16 additions & 12 deletions tests/net_inet/ssl_errors.py
@@ -1,12 +1,12 @@
# test that socket.connect() on a non-blocking socket raises EINPROGRESS
# and that an immediate write/send/read/recv does the right thing

import sys, errno, socket, ssl
import sys, errno, select, socket, ssl


def test(addr, hostname, block=True):
print("---", hostname or addr)
s = socket.socket()
print("---", hostname)
s = socket.socket(socket.AF_INET)
s.setblocking(block)
try:
s.connect(addr)
Expand All @@ -16,11 +16,15 @@ def test(addr, hostname, block=True):
raise
print("EINPROGRESS")

if sys.implementation.name != "micropython":
# in CPython we have to wait, otherwise wrap_socket is not happy
select.select([], [s], [])

ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.verify_mode = ssl.CERT_REQUIRED

try:
if sys.implementation.name == "micropython":
s = ssl.wrap_socket(s, do_handshake=block)
else:
s = ssl.wrap_socket(s, do_handshake_on_connect=block)
s = ssl_context.wrap_socket(s, do_handshake_on_connect=block, server_hostname=hostname)
print("wrap: True")
except OSError:
print("wrap: error")
Expand All @@ -36,11 +40,11 @@ def test(addr, hostname, block=True):

if __name__ == "__main__":
# connect to plain HTTP port, oops!
addr = socket.getaddrinfo("micropython.org", 80)[0][-1]
test(addr, None)
addr = socket.getaddrinfo("micropython.org", 80, socket.AF_INET)[0][-1]
test(addr, "micropython.org")
# connect to plain HTTP port, oops!
addr = socket.getaddrinfo("micropython.org", 80)[0][-1]
test(addr, None, False)
addr = socket.getaddrinfo("micropython.org", 80, socket.AF_INET)[0][-1]
test(addr, "micropython.org", False)
# connect to server with self-signed cert, oops!
addr = socket.getaddrinfo("test.mosquitto.org", 8883)[0][-1]
addr = socket.getaddrinfo("test.mosquitto.org", 8883, socket.AF_INET)[0][-1]
test(addr, "test.mosquitto.org")
26 changes: 15 additions & 11 deletions tests/net_inet/test_tls_nonblock.py
Expand Up @@ -2,12 +2,12 @@


def test_one(site, opts):
ai = socket.getaddrinfo(site, 443)
ai = socket.getaddrinfo(site, 443, socket.AF_INET)
addr = ai[0][-1]
print(addr)
print(site)

# Connect the raw socket
s = socket.socket()
s = socket.socket(socket.AF_INET)
s.setblocking(False)
try:
s.connect(addr)
Expand All @@ -16,17 +16,22 @@ def test_one(site, opts):
if e.errno != errno.EINPROGRESS:
raise

# Create SSLContext.
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

# CPython compatibility:
# - disable check_hostname
# - load default system certificate chain
# - must wait for socket to be writable before calling wrap_socket
if sys.implementation.name != "micropython":
# in CPython we have to wait, otherwise wrap_socket is not happy
ssl_context.check_hostname = False
ssl_context.load_default_certs()
select.select([], [s], [])

try:
# Wrap with SSL
try:
if sys.implementation.name == "micropython":
s = ssl.wrap_socket(s, do_handshake=False)
else:
s = ssl.wrap_socket(s, do_handshake_on_connect=False)
s = ssl_context.wrap_socket(s, do_handshake_on_connect=False)
except OSError as e:
if e.errno != errno.EINPROGRESS:
raise
Expand Down Expand Up @@ -87,8 +92,7 @@ def test_one(site, opts):


SITES = [
"google.com",
{"host": "www.google.com"},
"www.github.com",
"micropython.org",
"pypi.org",
{"host": "api.pushbullet.com", "sni": True},
Expand All @@ -105,7 +109,7 @@ def main():
test_one(site, opts)
print(site, "ok")
except Exception as e:
print(site, "error")
print(site, "error", e)
print("DONE")


Expand Down
29 changes: 19 additions & 10 deletions tests/net_inet/test_tls_sites.py
@@ -1,24 +1,34 @@
import sys
import select
import socket
import ssl

# CPython only supports server_hostname with SSLContext
if hasattr(ssl, "SSLContext"):
ssl = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)


def test_one(site, opts):
ai = socket.getaddrinfo(site, 443)
ai = socket.getaddrinfo(site, 443, socket.AF_INET)
addr = ai[0][-1]

s = socket.socket()
s = socket.socket(socket.AF_INET)

# Create SSLContext.
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

# CPython compatibility:
# - disable check_hostname
# - load default system certificate chain
# - must wait for socket to be writable before calling wrap_socket
if sys.implementation.name != "micropython":
ssl_context.check_hostname = False
ssl_context.load_default_certs()
select.select([], [s], [])

try:
s.connect(addr)

if "sni" in opts:
s = ssl.wrap_socket(s, server_hostname=opts["host"])
s = ssl_context.wrap_socket(s, server_hostname=opts["host"])
else:
s = ssl.wrap_socket(s)
s = ssl_context.wrap_socket(s)

s.write(b"GET / HTTP/1.0\r\nHost: %s\r\n\r\n" % bytes(site, "latin"))
resp = s.read(4096)
Expand All @@ -31,8 +41,7 @@ def test_one(site, opts):


SITES = [
"google.com",
"www.google.com",
"www.github.com",
"micropython.org",
"pypi.org",
{"host": "api.pushbullet.com", "sni": True},
Expand Down
5 changes: 0 additions & 5 deletions tests/net_inet/test_tls_sites.py.exp

This file was deleted.

8 changes: 6 additions & 2 deletions tests/net_inet/tls_text_errors.py
@@ -1,13 +1,17 @@
# test that modtls produces a text error message

import socket, ssl, sys
import socket, ssl


def test(addr):
s = socket.socket()
s.connect(addr)
try:
s = ssl.wrap_socket(s)
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
if hasattr(ssl_context, "check_hostname"):
# Disable hostname check on CPython.
ssl_context.check_hostname = False
s = ssl_context.wrap_socket(s)
print("wrap: no exception")
except OSError as e:
# mbedtls produces "mbedtls -0x7200: SSL - An invalid SSL record was received"
Expand Down

0 comments on commit bba8a67

Please sign in to comment.