Beefing up socket.ssl(...)

Ed Phillips ed at UDel.Edu
Fri Jul 25 15:44:33 EDT 2003


>From looking at Modules/socketmodule.c in 2.2.2 and 2.2.3, it appears that
only a tiny bit of support for SSL has been added.  Specifically, unless
I'm misunderstanding the operation of the code, there's no way to verify
the certificate presented by a server.  The code necessary to cause such
verification is pretty straightforward for simple "verify the server
certificate" purposes so I hacked together some changes to 2.2.2
socketmodule.c to verify the certificates (see below).

So now, I can do something like this:

from socket import *

s = socket(AF_INET, SOCK_STREAM)
a = ('www.mycompany.net', 443)
s.connect(a)
v = ssl(s, '', 'mycacerts.pem')

...and the server certificate is verified according to the CA certs stored
in the file.  I'm not sure of the intent of the
SSL_CTX_use_PrivateKey_file() and SSL_CTX_use_certificate_chain_file()
calls in the original socketmodule.c ... they don't seem to do much that
is useful at the Python level AFAICT.  I guess if you were going to use
client certs, and your server requested peer authentication, then it would
somehow use private key file (which I guess would contain the client cert
and the client private key?) to initiate a client-auth process, but in the
normal "I just want to verify the server I'm connecting to has the correct
certificate" context, my version seems to be a sufficient starting point.
I also, I don't understand the motivation behind requiring both the
key_file and cert_file parms.

I'm not very good with Python extension modules yet (or OpenSSL for that
matter), so I have a printf() stuck in there just to get a meaningful
error about the verification process.  This could probably be changed to
mimic what PySSL_SetError(..) does and return an actual error code and
error string tuple, but that's just icing.

Also, I noticed that at line 2736 of socketmodule.c (original 2.2.2
version; line 2741 in the 2.2.3 version) there is a "return NULL;"
statement missing that may need to be fixed.  I don't know what to do with
this info. other than post it to this list...  maybe someone reading this
list will run with it...?

Do others beside me find SSL features lacking in Python?  Do you use some
other module to provide SSL features rather than the basic socket module?

Thanks,

	Ed

Ed Phillips <ed at udel.edu> University of Delaware (302) 831-6082
Systems Programmer III, Network and Systems Services
finger -l ed at polycut.nss.udel.edu for PGP public key

*** Modules/socketmodule.c_orig Thu Jul 24 12:26:16 2003
--- Modules/socketmodule.c      Thu Jul 24 17:08:36 2003
***************
*** 2760,2769 ****
--- 2760,2771 ----
        self->ctx = NULL;
        self->Socket = NULL;

+ /*
        if ((key_file && !cert_file) || (!key_file && cert_file)) {
                errstr = "Both the key & certificate files must be
specified";
                goto fail;
        }
+ */

        self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */
        if (self->ctx == NULL) {
***************
*** 2771,2788 ****
                goto fail;
        }

!       if (key_file) {
                if (SSL_CTX_use_PrivateKey_file(self->ctx, key_file,
                                                SSL_FILETYPE_PEM) < 1) {
                        errstr = "SSL_CTX_use_PrivateKey_file error";
                        goto fail;
                }

                if (SSL_CTX_use_certificate_chain_file(self->ctx,
                                                       cert_file) < 1) {
                        errstr = "SSL_CTX_use_certificate_chain_file
error";
                        goto fail;
                }
        }

        SSL_CTX_set_verify(self->ctx,
--- 2773,2799 ----
                goto fail;
        }

!       if (key_file && *key_file) {
                if (SSL_CTX_use_PrivateKey_file(self->ctx, key_file,
                                                SSL_FILETYPE_PEM) < 1) {
                        errstr = "SSL_CTX_use_PrivateKey_file error";
                        goto fail;
                }
+       }

+       if (cert_file && *cert_file) {
+               if (SSL_CTX_load_verify_locations(self->ctx, cert_file,
NULL)
+                       < 1) {
+                       errstr = "SSL_CTX_load_verify_locations error";
+                       goto fail;
+               }
+               /*
                if (SSL_CTX_use_certificate_chain_file(self->ctx,
                                                       cert_file) < 1) {
                        errstr = "SSL_CTX_use_certificate_chain_file
error";
                        goto fail;
                }
+               */
        }

        SSL_CTX_set_verify(self->ctx,
***************
*** 2805,2810 ****
--- 2816,2828 ----
                                  self->server, X509_NAME_MAXLEN);
                X509_NAME_oneline(X509_get_issuer_name(self->server_cert),
                                  self->issuer, X509_NAME_MAXLEN);
+               ret = SSL_get_verify_result(self->ssl);
+               if (ret != X509_V_OK) {
+                       /* errstr = "SSL_get_verify_result error"; */
+                       printf("SSL_get_verify_result returned %d\n",
ret);
+                       PySSL_SetError(self->ssl, ret);
+                       goto fail;
+               }
        }
        self->Socket = Sock;
        Py_INCREF(self->Socket);





More information about the Python-list mailing list