[Python-Dev] More on server-side SSL support

Bill Janssen janssen at parc.com
Mon Aug 20 18:46:17 CEST 2007


All right, here's my current design :-).

We add to the socket module a subtype of socket.socket,
socket.SSLSocket.  It has the following constructor:

  SSLSocket (family=AF_INET, type=SOCK_STREAM, proto=0,
	     cert_filename=None, key_filename=None,
	     cert_policy=CERT_NONE, ssl_protocol=PROTOCOL_SSLv23)

where the options for "cert_policy" are:

  CERT_NONE -- no certificates will be required or verified
  CERT_OPTIONAL -- cert not required from peer, but if provided is verified
  CERT_REQUIRED -- verifiable cert required from peer

and the options for "ssl_protocol" are:

  PROTOCOL_SSLv2
  PROTOCOL_SSLv3
  PROTOCOL_SSLv23
  PROTOCOL_TLSv1

The "cert_filename" is optional for clients, required for servers; the
"key_filename" can be used to specify another file where the private key
for the certificate is stored, otherwise the key is presumed to be in
the cert file along with the certificate (or certicates; the cert file
may contain a chain of certificates).

In use, the application creates an "SSLSocket" instead of a regular
"socket" if it wishes to use SSL.  If it's client-side, when the
"connect" call is made on the socket, the SSL handshake is performed,
and subsequent reads from and writes to the socket are delegated to
the SSLObject that's returned from the handshake.  If it's
server-side, when the "accept" call is made, the socket returned is
another SSLSocket with the SSLObject already set, so that writes and
reads are processed via the SSLObject.  Actually, "recv", "recvinto",
"send" and "sendall" are the methods delegated; "recv_from" and
"send_to" raise exceptions (and I think using any flags on the other
methods should also raise exceptions).

An instance of SSLSocket will have a method called "getpeercert",
which will return either None, if the socket is not connected, or a
dict containing pertinent fields of the peer's certificate; empty if
the peer did not provide a cert or if the CERT_NONE option was
specified, or filled with fields like "subject", "issuer", etc. if it
did and the cert was verified.  (What fields, exactly?  Seems to me
that it should have subject, issuer, good_after, good_until, but what
else?)

The existing use of "socket.ssl" will continue to work, for backwards
compatibility.

This design should allow SSLSocket to be used in all the various
places where a regular socket is currently used, such as
SimpleHTTPServer, with only a few tweaks.  For instance, here's an SSL
version of TCPServer:

class MySSLTCPServer (TCPServer):

    def __init__(self, server_address, RequestHandlerClass, certfile,
	         bind_and_activate=True):
        """Constructor.  May be extended, do not override."""
        BaseServer.__init__(self, server_address, RequestHandlerClass)
        self.socket = socket.SSLSocket(self.address_family,
                                       self.socket_type,
                                       certfile=certfile)
        if bind_and_activate:
            self.server_bind()
            self.server_activate()

Bill




More information about the Python-Dev mailing list