Chapter 6 ■ tLS/SSL
107
• ftplib: When you build an FTP_TLS object (see Chapter 17), you can use the constructor’s
context keyword to pass in an SSLContext with your own settings. Note that the first line or
two of the FTP conversation will always pass in the clear (such as the “220” welcome message
that often includes the server hostname) before you have the chance to turn on encryption.
An FTP_TLS object will automatically turn on encryption before the login() method sends a
username and password. If you are not logging in to the remote server but want encryption
turned on anyway, you will have to call the auth() method manually as the first action you
take after connecting.
• nntplib: Although the NNTP network news (Usenet) protocol is not covered in this book, I
should note that it too can be secured. If you build an NNTP_SSL, you can use the constructor’s
ssl_context keyword to pass in an SSLContext with your own settings. If instead you create
a plain NNTP object and only later call its starttls() method, then you would provide the
context parameter to that method call.
Note that the common theme running across nearly all of these protocols is that an older plain-text protocol
can be extended with TLS in one of two different ways. One way is for a new command to be added to the protocol
that allows an upgrade to TLS in mid-conversation, after an old-fashioned plain-text connection is made using the
protocol’s traditional port number. The other approach is for the Internet standard to allocate a second well-defined
TCP port number specifically for the TLS-protected version of the protocol, in which case TLS negotiation can happen
immediately upon connecting without having to ask. Most of the previously mentioned protocols support both
options, but HTTP opted for only the second because the protocol is stateless by design.
If you are connecting to a server configured by another team or organization that supports the TLS version of
one of the previous protocols, then you may simply have to test (in the absence of any documentation that they might
offer) to determine whether they opened the protocol’s new TLS port or simply support TLS upgrades atop the old
plain-text protocol.
If instead of relying on the Standard Library for your network communication you are using a third-party package
that you learned about either from this book or elsewhere, you will want to consult its documentation for how to
provide your own SSLContext. If no mechanism is provided—and, as I type this, even popular third-party libraries
are typically not yet offering this ability for users of Python 3.4 and newer—then you will have to experiment with
whatever knobs and settings the package does provide and test the result (perhaps using Listing 6-4, introduced in
the next section) to see whether the third-party library guarantees a strong enough protocol and cipher for the privacy
required by your data.
Learning Details
To help you learn more about the TLS protocol version and cipher choices that your clients and servers can make,
Listing 6-4 offers a Python 3.4 script that makes an encrypted connection and then reports on its features. To do this,
it uses several recent features of the Standard Library ssl module’s SSLSocket object that now allow Python scripts to
introspect the state of their OpenSSL-powered connections to see how they are configured.
The methods that it uses to perform its reporting are as follows:
• getpeercert(): A long-standing feature of SSLSocket that is available in several previous
Python versions, this method returns a Python dictionary of fields picked out of the X.509
certificate of the peer to which the TLS session is connected. But recent Python versions have
been expanding the range of certificate features that are exposed.
• cipher(): Returns the name of the cipher that OpenSSL and the peer’s TLS implementation
finally agreed upon and that is currently in use over the connection.
• compression(): Returns the name of the compression algorithm in use or else the Python
singleton None.