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