Foundations of Python Network Programming

(WallPaper) #1

Chapter 6 ■ tLS/SSL


10 4


•    It is woefully permissive with respect to the weak ciphers that it will allow because of the
promise of backward compatibility with versions of Python that are now a decade old.

•    And, finally, it fails to provide actual security because it performs no hostname
checking! Unless you remember to follow up after a “successful” connection by running
match_hostname(), you will not even know whether the certificate that your peer has offered
is even for the same hostname to which you think you are connected.

For all of these reasons, you should avoid ssl.wrap_socket() and be prepared to migrate away from it in any old
code that you might be maintaining. Instead, use practices like those shown in Listing 6-3.
The other major shortcut you will see is wrapping a socket before it is connected, by wrapping either a client
socket before it runs connect() or a server socket before it runs accept(). In both cases, the wrapped socket cannot
really negotiate TLS immediately, but it will wait until the socket is connected to perform TLS negotiation. Obviously,
this will work only for protocols such as HTTPS that do their TLS activation as the first step after connecting.
A protocol like SMTP that needs to start the conversation with some cleartext cannot use this approach, so a keyword
option do_handshake_on_connect is available when wrapping, which you can set to False if you want to wait until
later to trigger TLS negotiation with the socket’s do_handshake() method.
It is true that prewrapping a socket does not by itself reduce your security, but I recommend against it for these
three reasons involving code readability:


•    First, it puts the wrapping call somewhere else in your code than where the actual TLS
negotiation takes place, which can hide from someone reading your eventual connect() or
accept() call that the TLS protocol is even involved.

•    Related to the previous problem is the fact that connect() and accept() will now be able
to fail not only with their usual socket or DNS exceptions but also with TLS errors if the
negotiation goes poorly. Any try...except clause wrapping those calls will now have to worry
about two entirely separate classes of error because two quite different operations will be
hidden under the covers of a single method call.

•    Finally, you will find that you now possess an SSLSocket object that might not, in fact, be
doing any encryption. Only once a connection is made or when an explicit do_handshake() is
called (if you turned autonegotiation off ) will the so-called SSLSocket be providing any actual
encryption! In contrast, the pattern offered in the program listings in this book transitions
to an SSLSocket only at the moment that encryption actually becomes active, making a far
cleaner semantic link between the class of your current socket object and the state of the
underlying connection.

The only case in which I have seen prewrapping put to interesting use is when trying to use an old, naïve library
that only supports cleartext communication. By providing a prewrapped socket and leaving the do_handshakeon
connect keyword argument set to its default value of True, you can provide TLS protection to the protocol without its
even knowing. However, this is a special case and is better handled (if possible) by making the underlying library
TLS-aware and able to accept a TLS context as an argument.


Hand-Picked Ciphers and Perfect Forward Security


If you are picky about data security, then you might find yourself wanting to specify exactly the ciphers that OpenSSL
can use instead of relying on the defaults provided by the create_default_context() function.
As the field of encryption continues to advance, there will doubtless be concerns, vulnerabilities, and
countermeasures of which we do not yet dream. But one important concern as this book is going to press is the
question of Perfect Forward Security (PFS), that is, the question of whether someone who in the future acquires
(or cracks) an old private key of yours will then be able to read old TLS conversations that they captured and kept
archived for future decryption. The most popular ciphers today are those that protect against this possibility by using
an ephemeral (temporary) key to perform the encryption of each new socket. The desire to guarantee PFS is one of the
most popular reasons for wanting to hand-specify the properties of your context object.

Free download pdf