Foundations of Python Network Programming

(WallPaper) #1

Chapter 6 ■ tLS/SSL


108


To make its reporting as complete as possible, the script in Listing 6-4 also attempts a bit of magic using ctypes
in a desperate attempt to learn the TLS protocol in use (which will ideally be a native feature of the ssl module by the
time Python 3.5 is released). By pulling these pieces together, Listing 6-4 lets you connect to a client or server that you
have constructed and learn what ciphers and protocols it will or will not negotiate.


Listing 6-4. Connect to Any TLS Endpoint and Report the Cipher Negotiated


#!/usr/bin/env python3


Foundations of Python Network Programming, Third Edition


https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter06/test_tls.py


Attempt a TLS connection and, if successful, report its properties


import argparse, socket, ssl, sys, textwrap
import ctypes
from pprint import pprint


def open_tls(context, address, server=False):
raw_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if server:
raw_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
raw_sock.bind(address)
raw_sock.listen(1)
say('Interface where we are listening', address)
raw_client_sock, address = raw_sock.accept()
say('Client has connected from address', address)
return context.wrap_socket(raw_client_sock, server_side=True)
else:
say('Address we want to talk to', address)
raw_sock.connect(address)
return context.wrap_socket(raw_sock)


def describe(ssl_sock, hostname, server=False, debug=False):
cert = ssl_sock.getpeercert()
if cert is None:
say('Peer certificate', 'none')
else:
say('Peer certificate', 'provided')
subject = cert.get('subject', [])
names = [name for names in subject for (key, name) in names
if key == 'commonName']
if 'subjectAltName' in cert:
names.extend(name for (key, name) in cert['subjectAltName']
if key == 'DNS')


say('Name(s) on peer certificate', *names or ['none'])
if (not server) and names:
try:
ssl.match_hostname(cert, hostname)
except ssl.CertificateError as e:
message = str(e)
else:
message = 'Yes'
say('Whether name(s) match the hostname', message)

Free download pdf