226
Although there are several solutions available for Python, M2Crypto is the most popular, the most complete, and not surprisingly, the most mature. It is written and maintained by Ng Pheng Siong
ngpspost1.com and can be found on the Web at
http:www.post1.comhomengpsm2 . It
requires SWIG, which can be found on the Web at http:swig.sourceforge.net
. At the time of writing, the latest version of M2Crypto is Version 0.06 and requires OpenSSL 0.9.6 or later and
SWIG 1.3.6. Its been tested and known to work on Unix and Windows with Python Versions 1.5.2, 2.0, and 2.1.
Although it is the most mature Python solution available, M2Crypto is barely a year old. Unfortunately, it is sorely lacking in documentation. Luckily, included in the distribution is a
sizable collection of examples as well as a suite of unit test scripts that also serve as excellent examples of how to use the modules. M2Crypto contains not only a large set of low-level bindings
to the OpenSSL C library functions, but a set of high-level classes that provide a far cleaner interface to SSL as well.
9.2.1 Low-Level Bindings
A significant number of the OpenSSL C library functions are directly bound. Many others are still available, although wrapped with a slightly different name, and their arguments may have changed
slightly. These wrappers typically make the functions easier to use from Python and do a little extra work under the hood that may be necessary for everything to work properly for Python.
You can make the low-level bindings to OpenSSL available in your program with t he following statement:
from M2Crypto import m2
All of the low-level functions are named entirely in lowercase, and the OpenSSL C functions are normally named in a combination of uppercase and lowercase. For example, the OpenSSL C
function named
SSL_CTX_new
would become
m2.ssl_ctx_new
in Python. We will not include a complete list of the low-level bindings in this chapter; however, the M2Crypto package
contains one. We dont recommend that you use the low-level bindings in your own programs, at least not
without also using the high-level classes. The primary reason for this is that many of the SSL subsystems require some additional setup calls from Python to make them work properly. For
example, to use the BIO functionality, you need to call
m2.bio_init
, an internal M2Crypto function, properly. If youre using the high-level classes, such calls are made for you, and you can
generally feel free to extend the classes if you need to.
9.2.2 High-Level Classes
M2Crypto contains a reasonably complete set of high-level classes that you can use in your programs. Use of the high-level classes is encouraged over the low-level bindings for a couple of
reasons. The primary reason that we cited in the earlier section on the low-level interface is a good one. As M2Crypto evolves and matures, its possible that its internals will change, breaking your
programs in the process. Another reason is because Python is primarily an object-oriented language, and the low-level interface is not object-oriented at all. A third reason is that OpenSSLs
C library functions are often cumbersome to use. The high-level classes provide a much cleaner, easier-to-use interface to OpenSSLs functionality.
There are several submodules, all of which can be imported from the M2Crypto module to access the various groupings of functions that all make up the OpenSSL C API. Several of them are still
works in progress, but the most commonly used SSL functionality is available.
9.2.2.1 M2Crypto.SSL
227
from M2Crypto import SSL
The SSL module contains several classes that provide the most basic interface to the OpenSSL C library. Included among them are
Context
,
Connection
,
Session
,
SSLServer
,
ForkingSSLServer
, and
ThreadingSSLServer
. The first,
Context
, is a wrapper around the C interfaces
SSL_CTX
object. All of OpenSSLs connection-oriented services require a context on which to operate.
When a context is created, the version of the protocol that it will support must be supplied. You cannot change a contexts protocol once it has been created. The
Context
classs constructor takes an optional parameter that specifies the protocol to use. The protocol can be
sslv2
,
sslv3
,
tlsv1
, or
sslv23
. If you do not specify a protocol, the default is
sslv23
, which indicates that SSLv2, SSLv3, or TLSv1 should be negotiated during the initial handshake. As we mentioned in
Chapter 1 , you should avoid supporting v2 in your applications.
Once a context object has been created, it can be used to establish an SSL connection. The class contains many methods that allow you to set and query the various attributes a context may have
that are supported by OpenSSL itself. Operations include assigning a certificate and private key, loading CA certificates, and specifying criteria to determine whether a peers certificate is
acceptable or not.
The
Connection
class combines OpenSSL with sockets to provide an all-in-one object for establishing both client and server connections, as well as transferring data bi-directionally over
the connection. This class is little more than a convenience object, since it does all of the tedious work of setting up a socket and establishing an SSL connection for you. All that you need to do is
create a
Context
and set it up to meet your needs. For example, to establish a connection using TLSv1 for the protocol, your code might look a little something like this:
from M2Crypto import SSL ctx = SSL.Contexttlsv1
conn = SSL.Connectionctx conn.connect127.0.0.1, 443
The
Session
class is not one that you would typically create yourself. There are two ways to get a
Session
object. The first is from an existing
Connection
object by calling its
get_session
method. The second is by loading a saved session from a file via
SSL.load_session
. Once you have a
Session
object, you can dump it to a file using its
write_bio
method. The last three classes,
SSLServer
,
ForkingSSLServer
, and
ThreadingSSLServer
, are SSL versions of the Python
TCPServer
class found in the SocketServer module. They all work in the same manner, except the constructor for each class requires an additional argument that is a
Context
object. You are of course required to create the
Context
object and set it up to meet your needs.
9.2.2.2 M2Crypto.BIO