Skip to content

Instantly share code, notes, and snippets.

@tiran
Last active May 14, 2018 21:00
Show Gist options
  • Save tiran/d0de26bfeaba4458837909dbda41ab56 to your computer and use it in GitHub Desktop.
Save tiran/d0de26bfeaba4458837909dbda41ab56 to your computer and use it in GitHub Desktop.
TLS 1.3 shutdown reproducer
#! ./python
"""TLS 1.3 shutdown issue reproducer
./configure -C --with-pydebug
make
./python Tools/ssl/multissltests.py --openssl 1.1.1-pre6 --steps modules
./python shutdown.py --server
./python shutdown.py
"""
import argparse
import ssl
import socket
if ssl.OPENSSL_VERSION_INFO < (1, 1, 1):
raise ValueError(('OpenSSL 1.1.1 required', ssl.OPENSSL_VERSION))
CERT = 'Lib/test/keycert3.pem'
CA = 'Lib/test/pycacert.pem'
HOSTNAME = 'localhost'
PORT = 4433
parser = argparse.ArgumentParser("SSL shutdown test")
parser.add_argument('--ca', default=CA)
parser.add_argument('--cert', default=CERT)
parser.add_argument('--key', default=None)
parser.add_argument('--no-shutdown', dest='shutdown', action='store_false')
parser.add_argument('--port', type=int, default=PORT)
parser.add_argument('-hostname', default=HOSTNAME)
parser.add_argument('--server', action='store_true')
parser.add_argument('--no-tls13', action='store_true')
def client(args):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
if args.no_tls13:
ctx.options |= ssl.OP_NO_TLSv1_3
ctx.load_verify_locations(args.ca)
with ctx.wrap_socket(socket.socket(), server_hostname=args.hostname) as s:
s.connect((args.hostname, args.port))
print(s.version(), s)
if args.shutdown:
s = s.unwrap()
print(s.recv())
print('DONE')
def server(args):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
if args.no_tls13:
ctx.options |= ssl.OP_NO_TLSv1_3
ctx.load_verify_locations(args.ca)
ctx.load_cert_chain(args.cert, args.key)
srv = socket.socket()
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
srv.bind((args.hostname, args.port))
srv.listen(1)
print('SERVER listening:', args.hostname, args.port)
while True:
conn, addr = srv.accept()
with ctx.wrap_socket(conn, server_side=True) as s:
print(s.version(), s)
if args.shutdown:
s = s.unwrap()
s.sendall(b'EOF')
print('DONE')
if __name__ == '__main__':
args = parser.parse_args()
print(args)
if args.server:
server(args)
else:
client(args)
@tiran
Copy link
Author

tiran commented May 14, 2018

server

$ ./shutdown.py --server
Namespace(ca='Lib/test/pycacert.pem', cert='Lib/test/keycert3.pem', hostname='localhost', key=None, no_tls13=False, port=4433, server=True, shutdown=True)
SERVER listening: localhost 4433
TLSv1.3 <ssl.SSLSocket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 4433), raddr=('127.0.0.1', 52738)>
TLSv1.2 <ssl.SSLSocket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 4433), raddr=('127.0.0.1', 52740)>

client

$ ./shutdown.py 
Namespace(ca='Lib/test/pycacert.pem', cert='Lib/test/keycert3.pem', hostname='localhost', key=None, no_tls13=False, port=4433, server=False, shutdown=True)
TLSv1.3 <ssl.SSLSocket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 52738), raddr=('127.0.0.1', 4433)>
Traceback (most recent call last):
  File "./shutdown.py", line 73, in <module>
    client(args)
  File "./shutdown.py", line 45, in client
    s.unwrap()
  File "Lib/ssl.py", line 1091, in unwrap
    s = self._sslobj.shutdown()
OSError: [Errno 0] Error

$ ./shutdown.py --no-tls13
Namespace(ca='Lib/test/pycacert.pem', cert='Lib/test/keycert3.pem', hostname='localhost', key=None, no_tls13=True, port=4433, server=False, shutdown=True)
TLSv1.2 <ssl.SSLSocket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 52740), raddr=('127.0.0.1', 4433)>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment