blob: 1b05e40e6eaa57e1997e3cd87e387eda0e189624 [file] [log] [blame]
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +00001/* SSL socket module
2
3 SSL support based on patches by Brian E Gallew and Laszlo Kovacs.
4
5 This module is imported by socket.py. It should *not* be used
6 directly.
7
8*/
9
10#include "Python.h"
Martin v. Löwis6af3e2d2002-04-20 07:47:40 +000011enum py_ssl_error {
12 /* these mirror ssl.h */
13 PY_SSL_ERROR_NONE,
14 PY_SSL_ERROR_SSL,
15 PY_SSL_ERROR_WANT_READ,
16 PY_SSL_ERROR_WANT_WRITE,
17 PY_SSL_ERROR_WANT_X509_LOOKUP,
18 PY_SSL_ERROR_SYSCALL, /* look at error stack/return value/errno */
19 PY_SSL_ERROR_ZERO_RETURN,
20 PY_SSL_ERROR_WANT_CONNECT,
21 /* start of non ssl.h errorcodes */
22 PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */
23 PY_SSL_ERROR_INVALID_ERROR_CODE
24};
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +000025
26/* Include symbols from _socket module */
27#include "socketmodule.h"
28
29/* Include OpenSSL header files */
30#include "openssl/rsa.h"
31#include "openssl/crypto.h"
32#include "openssl/x509.h"
33#include "openssl/pem.h"
34#include "openssl/ssl.h"
35#include "openssl/err.h"
36#include "openssl/rand.h"
37
38/* SSL error object */
39static PyObject *PySSLErrorObject;
40
41/* SSL socket object */
42
43#define X509_NAME_MAXLEN 256
44
45/* RAND_* APIs got added to OpenSSL in 0.9.5 */
46#if OPENSSL_VERSION_NUMBER >= 0x0090500fL
47# define HAVE_OPENSSL_RAND 1
48#else
49# undef HAVE_OPENSSL_RAND
50#endif
51
52typedef struct {
53 PyObject_HEAD
54 PySocketSockObject *Socket; /* Socket on which we're layered */
55 SSL_CTX* ctx;
56 SSL* ssl;
57 X509* server_cert;
58 BIO* sbio;
59 char server[X509_NAME_MAXLEN];
60 char issuer[X509_NAME_MAXLEN];
61
62} PySSLObject;
63
64staticforward PyTypeObject PySSL_Type;
65staticforward PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args);
66staticforward PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args);
67
68#define PySSLObject_Check(v) ((v)->ob_type == &PySSL_Type)
69
70/* XXX It might be helpful to augment the error message generated
71 below with the name of the SSL function that generated the error.
72 I expect it's obvious most of the time.
73*/
74
75static PyObject *
76PySSL_SetError(PySSLObject *obj, int ret)
77{
78 PyObject *v, *n, *s;
79 char *errstr;
80 int err;
Martin v. Löwis6af3e2d2002-04-20 07:47:40 +000081 enum py_ssl_error p;
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +000082
83 assert(ret <= 0);
84
85 err = SSL_get_error(obj->ssl, ret);
Martin v. Löwis6af3e2d2002-04-20 07:47:40 +000086
87 switch (err) {
88 case SSL_ERROR_ZERO_RETURN:
89 errstr = "TLS/SSL connection has been closed";
90 p=PY_SSL_ERROR_ZERO_RETURN;
91 break;
92 case SSL_ERROR_WANT_READ:
93 errstr = "The operation did not complete (read)";
94 p=PY_SSL_ERROR_WANT_READ;
95 break;
96 case SSL_ERROR_WANT_WRITE:
97 p=PY_SSL_ERROR_WANT_WRITE;
98 errstr = "The operation did not complete (write)";
99 break;
100 case SSL_ERROR_WANT_X509_LOOKUP:
101 p=PY_SSL_ERROR_WANT_X509_LOOKUP;
102 errstr = "The operation did not complete (X509 lookup)";
103 break;
104 case SSL_ERROR_WANT_CONNECT:
105 p=PY_SSL_ERROR_WANT_CONNECT;
106 errstr = "The operation did not complete (connect)";
107 break;
108 case SSL_ERROR_SYSCALL:
109 {
110 unsigned long e = ERR_get_error();
111 if(e==0){
112 if(ret==0){
113 p=PY_SSL_ERROR_EOF;
114 errstr = "EOF occurred in violation of protocol";
115 }else if(ret==-1){
116 /* the underlying BIO reported an I/O error */
117 return obj->Socket->errorhandler();
118 }else{ /* possible? */
119 p=PY_SSL_ERROR_SYSCALL;
120 errstr = "Some I/O error occurred";
121 }
122 } else {
123 p=PY_SSL_ERROR_SYSCALL;
124 /* XXX Protected by global interpreter lock */
125 errstr = ERR_error_string(e, NULL);
126 }
127 break;
128 }
129 case SSL_ERROR_SSL:
130 {
131 unsigned long e = ERR_get_error();
132 p=PY_SSL_ERROR_SSL;
133 if (e !=0) {
134 /* XXX Protected by global interpreter lock */
135 errstr = ERR_error_string(e, NULL);
136 } else { /* possible? */
137 errstr="A failure in the SSL library occurred";
138 }
139 break;
140 }
141 default:
142 p=PY_SSL_ERROR_INVALID_ERROR_CODE;
143 errstr = "Invalid error code";
144 }
145 n = PyInt_FromLong((long) p);
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000146 if (n == NULL)
147 return NULL;
148 v = PyTuple_New(2);
149 if (v == NULL) {
150 Py_DECREF(n);
151 return NULL;
152 }
153
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000154 s = PyString_FromString(errstr);
155 if (s == NULL) {
156 Py_DECREF(v);
157 Py_DECREF(n);
158 }
159 PyTuple_SET_ITEM(v, 0, n);
160 PyTuple_SET_ITEM(v, 1, s);
161 PyErr_SetObject(PySSLErrorObject, v);
162 return NULL;
163}
164
165/* This is a C function to be called for new object initialization */
166static PySSLObject *
167newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file)
168{
169 PySSLObject *self;
170 char *errstr = NULL;
171 int ret;
172
173 self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */
174 if (self == NULL){
175 errstr = "newPySSLObject error";
176 goto fail;
177 }
178 memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN);
179 memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN);
180 self->server_cert = NULL;
181 self->ssl = NULL;
182 self->ctx = NULL;
183 self->Socket = NULL;
184
185 if ((key_file && !cert_file) || (!key_file && cert_file)) {
186 errstr = "Both the key & certificate files must be specified";
187 goto fail;
188 }
189
190 self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */
191 if (self->ctx == NULL) {
192 errstr = "SSL_CTX_new error";
193 goto fail;
194 }
195
196 if (key_file) {
197 if (SSL_CTX_use_PrivateKey_file(self->ctx, key_file,
198 SSL_FILETYPE_PEM) < 1) {
199 errstr = "SSL_CTX_use_PrivateKey_file error";
200 goto fail;
201 }
202
203 if (SSL_CTX_use_certificate_chain_file(self->ctx,
204 cert_file) < 1) {
205 errstr = "SSL_CTX_use_certificate_chain_file error";
206 goto fail;
207 }
208 }
209
210 SSL_CTX_set_verify(self->ctx,
211 SSL_VERIFY_NONE, NULL); /* set verify lvl */
212 self->ssl = SSL_new(self->ctx); /* New ssl struct */
213 SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */
214 SSL_set_connect_state(self->ssl);
215
216 /* Actually negotiate SSL connection */
217 /* XXX If SSL_connect() returns 0, it's also a failure. */
218 ret = SSL_connect(self->ssl);
219 if (ret <= 0) {
220 PySSL_SetError(self, ret);
221 goto fail;
222 }
223 self->ssl->debug = 1;
224
225 if ((self->server_cert = SSL_get_peer_certificate(self->ssl))) {
226 X509_NAME_oneline(X509_get_subject_name(self->server_cert),
227 self->server, X509_NAME_MAXLEN);
228 X509_NAME_oneline(X509_get_issuer_name(self->server_cert),
229 self->issuer, X509_NAME_MAXLEN);
230 }
231 self->Socket = Sock;
232 Py_INCREF(self->Socket);
233 return self;
234 fail:
235 if (errstr)
236 PyErr_SetString(PySSLErrorObject, errstr);
237 Py_DECREF(self);
238 return NULL;
239}
240
241/* This is the Python function called for new object initialization */
242static PyObject *
243PySocket_ssl(PyObject *self, PyObject *args)
244{
245 PySSLObject *rv;
246 PySocketSockObject *Sock;
247 char *key_file = NULL;
248 char *cert_file = NULL;
249
250 if (!PyArg_ParseTuple(args, "O!|zz:ssl",
251 PySocketModule.Sock_Type,
252 (PyObject*)&Sock,
253 &key_file, &cert_file))
254 return NULL;
255
256 rv = newPySSLObject(Sock, key_file, cert_file);
257 if (rv == NULL)
258 return NULL;
259 return (PyObject *)rv;
260}
261
262static char ssl_doc[] =
263"ssl(socket, [keyfile, certfile]) -> sslobject";
264
265/* SSL object methods */
266
267static PyObject *
268PySSL_server(PySSLObject *self)
269{
270 return PyString_FromString(self->server);
271}
272
273static PyObject *
274PySSL_issuer(PySSLObject *self)
275{
276 return PyString_FromString(self->issuer);
277}
278
279
280static void PySSL_dealloc(PySSLObject *self)
281{
282 if (self->server_cert) /* Possible not to have one? */
283 X509_free (self->server_cert);
284 if (self->ssl)
285 SSL_free(self->ssl);
286 if (self->ctx)
287 SSL_CTX_free(self->ctx);
288 Py_XDECREF(self->Socket);
289 PyObject_Del(self);
290}
291
292static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
293{
294 char *data;
295 int len;
296
297 if (!PyArg_ParseTuple(args, "s#:write", &data, &len))
298 return NULL;
299
300 Py_BEGIN_ALLOW_THREADS
301 len = SSL_write(self->ssl, data, len);
302 Py_END_ALLOW_THREADS
303 if (len > 0)
304 return PyInt_FromLong(len);
305 else
306 return PySSL_SetError(self, len);
307}
308
309static char PySSL_SSLwrite_doc[] =
310"write(s) -> len\n\
311\n\
312Writes the string s into the SSL object. Returns the number\n\
313of bytes written.";
314
315static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
316{
317 PyObject *buf;
318 int count = 0;
319 int len = 1024;
320
321 if (!PyArg_ParseTuple(args, "|i:read", &len))
322 return NULL;
323
324 if (!(buf = PyString_FromStringAndSize((char *) 0, len)))
325 return NULL;
326
327 Py_BEGIN_ALLOW_THREADS
328 count = SSL_read(self->ssl, PyString_AsString(buf), len);
329 Py_END_ALLOW_THREADS
330 if (count <= 0) {
331 Py_DECREF(buf);
332 return PySSL_SetError(self, count);
333 }
Tim Peters5de98422002-04-27 18:44:32 +0000334 if (count != len)
335 _PyString_Resize(&buf, count);
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000336 return buf;
337}
338
339static char PySSL_SSLread_doc[] =
340"read([len]) -> string\n\
341\n\
342Read up to len bytes from the SSL socket.";
343
344static PyMethodDef PySSLMethods[] = {
345 {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS,
346 PySSL_SSLwrite_doc},
347 {"read", (PyCFunction)PySSL_SSLread, METH_VARARGS,
348 PySSL_SSLread_doc},
349 {"server", (PyCFunction)PySSL_server, METH_NOARGS},
350 {"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS},
351 {NULL, NULL}
352};
353
354static PyObject *PySSL_getattr(PySSLObject *self, char *name)
355{
356 return Py_FindMethod(PySSLMethods, (PyObject *)self, name);
357}
358
359staticforward PyTypeObject PySSL_Type = {
360 PyObject_HEAD_INIT(NULL)
361 0, /*ob_size*/
362 "socket.SSL", /*tp_name*/
363 sizeof(PySSLObject), /*tp_basicsize*/
364 0, /*tp_itemsize*/
365 /* methods */
366 (destructor)PySSL_dealloc, /*tp_dealloc*/
367 0, /*tp_print*/
368 (getattrfunc)PySSL_getattr, /*tp_getattr*/
369 0, /*tp_setattr*/
370 0, /*tp_compare*/
371 0, /*tp_repr*/
372 0, /*tp_as_number*/
373 0, /*tp_as_sequence*/
374 0, /*tp_as_mapping*/
375 0, /*tp_hash*/
376};
377
378#ifdef HAVE_OPENSSL_RAND
379
380/* helper routines for seeding the SSL PRNG */
381static PyObject *
382PySSL_RAND_add(PyObject *self, PyObject *args)
383{
384 char *buf;
385 int len;
386 double entropy;
387
388 if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy))
389 return NULL;
390 RAND_add(buf, len, entropy);
391 Py_INCREF(Py_None);
392 return Py_None;
393}
394
395static char PySSL_RAND_add_doc[] =
396"RAND_add(string, entropy)\n\
397\n\
398Mix string into the OpenSSL PRNG state. entropy (a float) is a lower\n\
399bound on the entropy contained in string.";
400
401static PyObject *
402PySSL_RAND_status(PyObject *self)
403{
404 return PyInt_FromLong(RAND_status());
405}
406
407static char PySSL_RAND_status_doc[] =
408"RAND_status() -> 0 or 1\n\
409\n\
410Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n\
411It is necessary to seed the PRNG with RAND_add() on some platforms before\n\
412using the ssl() function.";
413
414static PyObject *
415PySSL_RAND_egd(PyObject *self, PyObject *arg)
416{
417 int bytes;
418
419 if (!PyString_Check(arg))
420 return PyErr_Format(PyExc_TypeError,
421 "RAND_egd() expected string, found %s",
422 arg->ob_type->tp_name);
423 bytes = RAND_egd(PyString_AS_STRING(arg));
424 if (bytes == -1) {
425 PyErr_SetString(PySSLErrorObject,
426 "EGD connection failed or EGD did not return "
427 "enough data to seed the PRNG");
428 return NULL;
429 }
430 return PyInt_FromLong(bytes);
431}
432
433static char PySSL_RAND_egd_doc[] =
434"RAND_egd(path) -> bytes\n\
435\n\
436Queries the entropy gather daemon (EGD) on socket path. Returns number\n\
437of bytes read. Raises socket.sslerror if connection to EGD fails or\n\
438if it does provide enough data to seed PRNG.";
439
440#endif
441
442/* List of functions exported by this module. */
443
444static PyMethodDef PySSL_methods[] = {
445 {"ssl", PySocket_ssl,
446 METH_VARARGS, ssl_doc},
447#ifdef HAVE_OPENSSL_RAND
448 {"RAND_add", PySSL_RAND_add, METH_VARARGS,
449 PySSL_RAND_add_doc},
450 {"RAND_egd", PySSL_RAND_egd, METH_O,
451 PySSL_RAND_egd_doc},
452 {"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS,
453 PySSL_RAND_status_doc},
454#endif
455 {NULL, NULL} /* Sentinel */
456};
457
458
459static char module_doc[] =
460"Implementation module for SSL socket operations. See the socket module\n\
461for documentation.";
462
463DL_EXPORT(void)
464init_ssl(void)
465{
466 PyObject *m, *d;
467
468 PySSL_Type.ob_type = &PyType_Type;
469
470 m = Py_InitModule3("_ssl", PySSL_methods, module_doc);
471 d = PyModule_GetDict(m);
472
473 /* Load _socket module and its C API */
474 if (PySocketModule_ImportModuleAndAPI())
475 return;
476
477 /* Init OpenSSL */
478 SSL_load_error_strings();
479 SSLeay_add_ssl_algorithms();
480
481 /* Add symbols to module dict */
482 PySSLErrorObject = PyErr_NewException("socket.sslerror", NULL, NULL);
483 if (PySSLErrorObject == NULL)
484 return;
485 PyDict_SetItemString(d, "sslerror", PySSLErrorObject);
486 if (PyDict_SetItemString(d, "SSLType",
487 (PyObject *)&PySSL_Type) != 0)
488 return;
489 PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN",
Martin v. Löwis6af3e2d2002-04-20 07:47:40 +0000490 PY_SSL_ERROR_ZERO_RETURN);
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000491 PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ",
Martin v. Löwis6af3e2d2002-04-20 07:47:40 +0000492 PY_SSL_ERROR_WANT_READ);
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000493 PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE",
Martin v. Löwis6af3e2d2002-04-20 07:47:40 +0000494 PY_SSL_ERROR_WANT_WRITE);
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000495 PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP",
Martin v. Löwis6af3e2d2002-04-20 07:47:40 +0000496 PY_SSL_ERROR_WANT_X509_LOOKUP);
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000497 PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL",
Martin v. Löwis6af3e2d2002-04-20 07:47:40 +0000498 PY_SSL_ERROR_SYSCALL);
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000499 PyModule_AddIntConstant(m, "SSL_ERROR_SSL",
Martin v. Löwis6af3e2d2002-04-20 07:47:40 +0000500 PY_SSL_ERROR_SSL);
501 PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT",
502 PY_SSL_ERROR_WANT_CONNECT);
503 /* non ssl.h errorcodes */
504 PyModule_AddIntConstant(m, "SSL_ERROR_EOF",
505 PY_SSL_ERROR_EOF);
506 PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE",
507 PY_SSL_ERROR_INVALID_ERROR_CODE);
508
Marc-André Lemburga5d2b4c2002-02-16 18:23:30 +0000509}