blob: 6bf7f6548703794e37feef52826b547d7a6f7d79 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * connection.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
5 *
6 * SSL Connection objects and methods.
7 * See the file RATIONALE for a short explanation of why this module was written.
8 *
9 * Reviewed 2001-07-23
10 */
11#include <Python.h>
Jean-Paul Calderone12ea9a02008-02-22 12:24:39 -050012
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050013
14#ifndef MS_WINDOWS
15# include <sys/socket.h>
16# include <netinet/in.h>
17# if !(defined(__BEOS__) || defined(__CYGWIN__))
18# include <netinet/tcp.h>
19# endif
20#else
21# include <winsock.h>
Jean-Paul Calderone12ea9a02008-02-22 12:24:39 -050022# include <wincrypt.h>
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050023#endif
24
Jean-Paul Calderone12ea9a02008-02-22 12:24:39 -050025#define SSL_MODULE
26#include <openssl/err.h>
27
28
29#include "ssl.h"
30
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050031static char *CVSid = "@(#) $Id: connection.c,v 1.28 2004/08/06 10:21:56 martin Exp $";
32
33
34/**
35 * If we are on UNIX, fine, just use PyErr_SetFromErrno. If we are on Windows,
36 * apply some black winsock voodoo. This is basically just copied from Python's
37 * socketmodule.c
38 *
39 * Arguments: None
40 * Returns: None
41 */
42static void
43syscall_from_errno(void)
44{
45#ifdef MS_WINDOWS
46 int errnum = WSAGetLastError();
47 if (errnum)
48 {
49 static struct { int num; const char *msg; } *msgp, msgs[] = {
50 { WSAEINTR, "Interrupted system call" },
51 { WSAEBADF, "Bad file descriptor" },
52 { WSAEACCES, "Permission denied" },
53 { WSAEFAULT, "Bad address" },
54 { WSAEINVAL, "Invalid argument" },
55 { WSAEMFILE, "Too many open files" },
56 { WSAEWOULDBLOCK, "The socket operation could not complete "
57 "without blocking" },
58 { WSAEINPROGRESS, "Operation now in progress" },
59 { WSAEALREADY, "Operation already in progress" },
60 { WSAENOTSOCK, "Socket operation on non-socket" },
61 { WSAEDESTADDRREQ, "Destination address required" },
62 { WSAEMSGSIZE, "Message too long" },
63 { WSAEPROTOTYPE, "Protocol wrong type for socket" },
64 { WSAENOPROTOOPT, "Protocol not available" },
65 { WSAEPROTONOSUPPORT, "Protocol not supported" },
66 { WSAESOCKTNOSUPPORT, "Socket type not supported" },
67 { WSAEOPNOTSUPP, "Operation not supported" },
68 { WSAEPFNOSUPPORT, "Protocol family not supported" },
69 { WSAEAFNOSUPPORT, "Address family not supported" },
70 { WSAEADDRINUSE, "Address already in use" },
71 { WSAEADDRNOTAVAIL, "Can't assign requested address" },
72 { WSAENETDOWN, "Network is down" },
73 { WSAENETUNREACH, "Network is unreachable" },
74 { WSAENETRESET, "Network dropped connection on reset" },
75 { WSAECONNABORTED, "Software caused connection abort" },
76 { WSAECONNRESET, "Connection reset by peer" },
77 { WSAENOBUFS, "No buffer space available" },
78 { WSAEISCONN, "Socket is already connected" },
79 { WSAENOTCONN, "Socket is not connected" },
80 { WSAESHUTDOWN, "Can't send after socket shutdown" },
81 { WSAETOOMANYREFS, "Too many references: can't splice" },
82 { WSAETIMEDOUT, "Operation timed out" },
83 { WSAECONNREFUSED, "Connection refused" },
84 { WSAELOOP, "Too many levels of symbolic links" },
85 { WSAENAMETOOLONG, "File name too long" },
86 { WSAEHOSTDOWN, "Host is down" },
87 { WSAEHOSTUNREACH, "No route to host" },
88 { WSAENOTEMPTY, "Directory not empty" },
89 { WSAEPROCLIM, "Too many processes" },
90 { WSAEUSERS, "Too many users" },
91 { WSAEDQUOT, "Disc quota exceeded" },
92 { WSAESTALE, "Stale NFS file handle" },
93 { WSAEREMOTE, "Too many levels of remote in path" },
94 { WSASYSNOTREADY, "Network subsystem is unvailable" },
95 { WSAVERNOTSUPPORTED, "WinSock version is not supported" },
96 { WSANOTINITIALISED, "Successful WSAStartup() not yet performed" },
97 { WSAEDISCON, "Graceful shutdown in progress" },
98 /* Resolver errors */
99 { WSAHOST_NOT_FOUND, "No such host is known" },
100 { WSATRY_AGAIN, "Host not found, or server failed" },
101 { WSANO_RECOVERY, "Unexpected server error encountered" },
102 { WSANO_DATA, "Valid name without requested data" },
103 { WSANO_ADDRESS, "No address, look for MX record" },
104 { 0, NULL }
105 };
106 PyObject *v;
107 const char *msg = "winsock error";
108
109 for (msgp = msgs; msgp->msg; msgp++)
110 {
111 if (errnum == msgp->num)
112 {
113 msg = msgp->msg;
114 break;
115 }
116 }
117
118 v = Py_BuildValue("(is)", errnum, msg);
119 if (v != NULL)
120 {
121 PyErr_SetObject(ssl_SysCallError, v);
122 Py_DECREF(v);
123 }
124 return;
125 }
126#else
127 PyErr_SetFromErrno(ssl_SysCallError);
128#endif
129}
130
131/*
132 * Handle errors raised by SSL I/O functions. NOTE: Not SSL_shutdown ;)
133 *
134 * Arguments: ssl - The SSL object
135 * err - The return code from SSL_get_error
136 * ret - The return code from the SSL I/O function
137 * Returns: None, the calling function should return NULL
138 */
139static void
140handle_ssl_errors(SSL *ssl, int err, int ret)
141{
142 switch (err)
143 {
144 /*
145 * Strange as it may seem, ZeroReturn is not an error per se. It means
146 * that the SSL Connection has been closed correctly (note, not the
147 * transport layer!), i.e. closure alerts have been exchanged. This is
148 * an exception since
149 * + There's an SSL "error" code for it
150 * + You have to deal with it in any case, close the transport layer
151 * etc
152 */
153 case SSL_ERROR_ZERO_RETURN:
154 PyErr_SetNone(ssl_ZeroReturnError);
155 break;
156
157 /*
158 * The WantXYZ exceptions don't mean that there's an error, just that
159 * nothing could be read/written just now, maybe because the transport
160 * layer would block on the operation, or that there's not enough data
161 * available to fill an entire SSL record.
162 */
163 case SSL_ERROR_WANT_READ:
164 PyErr_SetNone(ssl_WantReadError);
165 break;
166
167 case SSL_ERROR_WANT_WRITE:
168 PyErr_SetNone(ssl_WantWriteError);
169 break;
170
171 case SSL_ERROR_WANT_X509_LOOKUP:
172 PyErr_SetNone(ssl_WantX509LookupError);
173 break;
174
175 case SSL_ERROR_SYSCALL:
176 if (ERR_peek_error() == 0)
177 {
178 if (ret < 0)
179 {
180 syscall_from_errno();
181 }
182 else
183 {
184 PyObject *v;
185
186 v = Py_BuildValue("(is)", -1, "Unexpected EOF");
187 if (v != NULL)
188 {
189 PyErr_SetObject(ssl_SysCallError, v);
190 Py_DECREF(v);
191 }
192 }
193 break;
194 }
195
196 /* NOTE: Fall-through here, we don't want to duplicate code, right? */
197
198 case SSL_ERROR_SSL:
199 ;
200 default:
201 exception_from_error_queue();
202 break;
203 }
204}
205
206/*
207 * Here be member methods of the Connection "class"
208 */
209
210static char ssl_Connection_get_context_doc[] = "\n\
211Get session context\n\
212\n\
213Arguments: self - The Connection object\n\
214 args - The Python argument tuple, should be empty\n\
215Returns: A Context object\n\
216";
217static PyObject *
218ssl_Connection_get_context(ssl_ConnectionObj *self, PyObject *args)
219{
220 if (!PyArg_ParseTuple(args, ":get_context"))
221 return NULL;
222
223 Py_INCREF(self->context);
224 return (PyObject *)self->context;
225}
226
227static char ssl_Connection_pending_doc[] = "\n\
228Get the number of bytes that can be safely read from the connection\n\
229\n\
230Arguments: self - The Connection object\n\
231 args - The Python argument tuple, should be empty\n\
232Returns: \n\
233";
234static PyObject *
235ssl_Connection_pending(ssl_ConnectionObj *self, PyObject *args)
236{
237 int ret;
238
239 if (!PyArg_ParseTuple(args, ":pending"))
240 return NULL;
241
242 ret = SSL_pending(self->ssl);
243 return PyInt_FromLong((long)ret);
244}
245
246static char ssl_Connection_send_doc[] = "\n\
247Send data on the connection. NOTE: If you get one of the WantRead,\n\
248WantWrite or WantX509Lookup exceptions on this, you have to call the\n\
249method again with the SAME buffer.\n\
250\n\
251Arguments: self - The Connection object\n\
252 args - The Python argument tuple, should be:\n\
253 buf - The string to send\n\
254 flags - (optional) Included for compatability with the socket\n\
255 API, the value is ignored\n\
256Returns: The number of bytes written\n\
257";
258static PyObject *
259ssl_Connection_send(ssl_ConnectionObj *self, PyObject *args)
260{
261 char *buf;
262 int len, ret, err, flags;
263
264 if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags))
265 return NULL;
266
267 MY_BEGIN_ALLOW_THREADS(self->tstate)
268 ret = SSL_write(self->ssl, buf, len);
269 MY_END_ALLOW_THREADS(self->tstate)
270
271 if (PyErr_Occurred())
272 {
273 flush_error_queue();
274 return NULL;
275 }
276
277 err = SSL_get_error(self->ssl, ret);
278 if (err == SSL_ERROR_NONE)
279 {
280 return PyInt_FromLong((long)ret);
281 }
282 else
283 {
284 handle_ssl_errors(self->ssl, err, ret);
285 return NULL;
286 }
287}
288
289static char ssl_Connection_sendall_doc[] = "\n\
290Send \"all\" data on the connection. This calls send() repeatedly until\n\
291all data is sent. If an error occurs, it's impossible to tell how much data\n\
292has been sent.\n\
293\n\
294Arguments: self - The Connection object\n\
295 args - The Python argument tuple, should be:\n\
296 buf - The string to send\n\
297 flags - (optional) Included for compatability with the socket\n\
298 API, the value is ignored\n\
299Returns: The number of bytes written\n\
300";
301static PyObject *
302ssl_Connection_sendall(ssl_ConnectionObj *self, PyObject *args)
303{
304 char *buf;
305 int len, ret, err, flags;
306 PyObject *pyret = Py_None;
307
308 if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags))
309 return NULL;
310
311 do {
312 MY_BEGIN_ALLOW_THREADS(self->tstate)
313 ret = SSL_write(self->ssl, buf, len);
314 MY_END_ALLOW_THREADS(self->tstate)
315 if (PyErr_Occurred())
316 {
317 flush_error_queue();
318 pyret = NULL;
319 break;
320 }
321 err = SSL_get_error(self->ssl, ret);
322 if (err == SSL_ERROR_NONE)
323 {
324 buf += ret;
325 len -= ret;
326 }
327 else if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL ||
328 err == SSL_ERROR_ZERO_RETURN)
329 {
330 handle_ssl_errors(self->ssl, err, ret);
331 pyret = NULL;
332 break;
333 }
334 } while (len > 0);
335
336 Py_XINCREF(pyret);
337 return pyret;
338}
339
340static char ssl_Connection_recv_doc[] = "\n\
341Receive data on the connection. NOTE: If you get one of the WantRead,\n\
342WantWrite or WantX509Lookup exceptions on this, you have to call the\n\
343method again with the SAME buffer.\n\
344\n\
345Arguments: self - The Connection object\n\
346 args - The Python argument tuple, should be:\n\
347 bufsiz - The maximum number of bytes to read\n\
348 flags - (optional) Included for compatability with the socket\n\
349 API, the value is ignored\n\
350Returns: The number of bytes read\n\
351";
352static PyObject *
353ssl_Connection_recv(ssl_ConnectionObj *self, PyObject *args)
354{
355 int bufsiz, ret, err, flags;
356 PyObject *buf;
357
358 if (!PyArg_ParseTuple(args, "i|i:recv", &bufsiz, &flags))
359 return NULL;
360
361 buf = PyString_FromStringAndSize(NULL, bufsiz);
362 if (buf == NULL)
363 return NULL;
364
365 MY_BEGIN_ALLOW_THREADS(self->tstate)
366 ret = SSL_read(self->ssl, PyString_AsString(buf), bufsiz);
367 MY_END_ALLOW_THREADS(self->tstate)
368
369 if (PyErr_Occurred())
370 {
371 Py_DECREF(buf);
372 flush_error_queue();
373 return NULL;
374 }
375
376 err = SSL_get_error(self->ssl, ret);
377 if (err == SSL_ERROR_NONE)
378 {
379 if (ret != bufsiz && _PyString_Resize(&buf, ret) < 0)
380 return NULL;
381 return buf;
382 }
383 else
384 {
385 handle_ssl_errors(self->ssl, err, ret);
386 Py_DECREF(buf);
387 return NULL;
388 }
389}
390
391static char ssl_Connection_renegotiate_doc[] = "\n\
392Renegotiate the session\n\
393\n\
394Arguments: self - The Connection object\n\
395 args - The Python argument tuple, should be empty\n\
396Returns: True if the renegotiation can be started, false otherwise\n\
397";
398static PyObject *
399ssl_Connection_renegotiate(ssl_ConnectionObj *self, PyObject *args)
400{
401 int ret;
402
403 if (!PyArg_ParseTuple(args, ":renegotiate"))
404 return NULL;
405
406 MY_BEGIN_ALLOW_THREADS(self->tstate);
407 ret = SSL_renegotiate(self->ssl);
408 MY_END_ALLOW_THREADS(self->tstate);
409
410 if (PyErr_Occurred())
411 {
412 flush_error_queue();
413 return NULL;
414 }
415
416 return PyInt_FromLong((long)ret);
417}
418
419static char ssl_Connection_do_handshake_doc[] = "\n\
420Perform an SSL handshake (usually called after renegotiate() or one of\n\
421set_*_state()). This can raise the same exceptions as send and recv.\n\
422\n\
423Arguments: self - The Connection object\n\
424 args - The Python argument tuple, should be empty\n\
425Returns: None.\n\
426";
427static PyObject *
428ssl_Connection_do_handshake(ssl_ConnectionObj *self, PyObject *args)
429{
430 int ret, err;
431
432 if (!PyArg_ParseTuple(args, ":do_handshake"))
433 return NULL;
434
435 MY_BEGIN_ALLOW_THREADS(self->tstate);
436 ret = SSL_do_handshake(self->ssl);
437 MY_END_ALLOW_THREADS(self->tstate);
438
439 if (PyErr_Occurred())
440 {
441 flush_error_queue();
442 return NULL;
443 }
444
445 err = SSL_get_error(self->ssl, ret);
446 if (err == SSL_ERROR_NONE)
447 {
448 Py_INCREF(Py_None);
449 return Py_None;
450 }
451 else
452 {
453 handle_ssl_errors(self->ssl, err, ret);
454 return NULL;
455 }
456}
457
458#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x00907000L
459static char ssl_Connection_renegotiate_pending_doc[] = "\n\
460Check if there's a renegotiation in progress, it will return false once\n\
461a renegotiation is finished.\n\
462\n\
463Arguments: self - The Connection object\n\
464 args - The Python argument tuple, should be empty\n\
465Returns: Whether there's a renegotiation in progress\n\
466";
467static PyObject *
468ssl_Connection_renegotiate_pending(ssl_ConnectionObj *self, PyObject *args)
469{
470 if (!PyArg_ParseTuple(args, ":renegotiate_pending"))
471 return NULL;
472
473 return PyInt_FromLong((long)SSL_renegotiate_pending(self->ssl));
474}
475#endif
476
477static char ssl_Connection_total_renegotiations_doc[] = "\n\
478Find out the total number of renegotiations.\n\
479\n\
480Arguments: self - The Connection object\n\
481 args - The Python argument tuple, should be empty\n\
482Returns: The number of renegotiations.\n\
483";
484static PyObject *
485ssl_Connection_total_renegotiations(ssl_ConnectionObj *self, PyObject *args)
486{
487 if (!PyArg_ParseTuple(args, ":total_renegotiations"))
488 return NULL;
489
490 return PyInt_FromLong(SSL_total_renegotiations(self->ssl));
491}
492
493static char ssl_Connection_set_accept_state_doc[] = "\n\
494Set the connection to work in server mode. The handshake will be handled\n\
495automatically by read/write.\n\
496\n\
497Arguments: self - The Connection object\n\
498 args - The Python argument tuple, should be empty\n\
499Returns: None\n\
500";
501static PyObject *
502ssl_Connection_set_accept_state(ssl_ConnectionObj *self, PyObject *args)
503{
504 if (!PyArg_ParseTuple(args, ":set_accept_state"))
505 return NULL;
506
507 SSL_set_accept_state(self->ssl);
508
509 Py_INCREF(Py_None);
510 return Py_None;
511}
512
513static char ssl_Connection_set_connect_state_doc[] = "\n\
514Set the connection to work in client mode. The handshake will be handled\n\
515automatically by read/write.\n\
516\n\
517Arguments: self - The Connection object\n\
518 args - The Python argument tuple, should be empty\n\
519Returns: None\n\
520";
521static PyObject *
522ssl_Connection_set_connect_state(ssl_ConnectionObj *self, PyObject *args)
523{
524 if (!PyArg_ParseTuple(args, ":set_connect_state"))
525 return NULL;
526
527 SSL_set_connect_state(self->ssl);
528
529 Py_INCREF(Py_None);
530 return Py_None;
531}
532
533static char ssl_Connection_connect_doc[] = "\n\
534Connect to remote host and set up client-side SSL\n\
535\n\
536Arguments: self - The Connection object\n\
537 args - The Python argument tuple, should be:\n\
538 addr - A remote address\n\
539Returns: What the socket's connect method returns\n\
540";
541static PyObject *
542ssl_Connection_connect(ssl_ConnectionObj *self, PyObject *args)
543{
544 PyObject *meth, *ret;
545
546 if ((meth = PyObject_GetAttrString(self->socket, "connect")) == NULL)
547 return NULL;
548
549 SSL_set_connect_state(self->ssl);
550
551 ret = PyEval_CallObject(meth, args);
552 Py_DECREF(meth);
553 if (ret == NULL)
554 return NULL;
555
556 return ret;
557}
558
559static char ssl_Connection_connect_ex_doc[] = "\n\
560Connect to remote host and set up client-side SSL. Note that if the socket's\n\
561connect_ex method doesn't return 0, SSL won't be initialized.\n\
562\n\
563Arguments: self - The Connection object\n\
564 args - The Python argument tuple, should be:\n\
565 addr - A remove address\n\
566Returns: What the socket's connect_ex method returns\n\
567";
568static PyObject *
569ssl_Connection_connect_ex(ssl_ConnectionObj *self, PyObject *args)
570{
571 PyObject *meth, *ret;
572
573 if ((meth = PyObject_GetAttrString(self->socket, "connect_ex")) == NULL)
574 return NULL;
575
576 SSL_set_connect_state(self->ssl);
577
578 ret = PyEval_CallObject(meth, args);
579 Py_DECREF(meth);
580 if (ret == NULL)
581 return NULL;
582 if (PyInt_Check(ret) && PyInt_AsLong(ret) != 0)
583 return ret;
584
585 return ret;
586}
587
588static char ssl_Connection_accept_doc[] = "\n\
589Accept incoming connection and set up SSL on it\n\
590\n\
591Arguments: self - The Connection object\n\
592 args - The Python argument tuple, should be empty\n\
593Returns: A (conn,addr) pair where conn is a Connection and addr is an\n\
594 address\n\
595";
596static PyObject *
597ssl_Connection_accept(ssl_ConnectionObj *self, PyObject *args)
598{
599 PyObject *tuple, *socket, *address, *meth;
600 ssl_ConnectionObj *conn;
601
602 if ((meth = PyObject_GetAttrString(self->socket, "accept")) == NULL)
603 return NULL;
604 tuple = PyEval_CallObject(meth, args);
605 Py_DECREF(meth);
606 if (tuple == NULL)
607 return NULL;
608
609 socket = PyTuple_GetItem(tuple, 0);
610 Py_INCREF(socket);
611 address = PyTuple_GetItem(tuple, 1);
612 Py_INCREF(address);
613 Py_DECREF(tuple);
614
615 conn = ssl_Connection_New(self->context, socket);
616 Py_DECREF(socket);
617 if (conn == NULL)
618 {
619 Py_DECREF(address);
620 return NULL;
621 }
622
623 SSL_set_accept_state(conn->ssl);
624
625 tuple = Py_BuildValue("(OO)", conn, address);
626
627 Py_DECREF(conn);
628 Py_DECREF(address);
629
630 return tuple;
631}
632
633static char ssl_Connection_shutdown_doc[] = "\n\
634Send closure alert\n\
635\n\
636Arguments: self - The Connection object\n\
637 args - The Python argument tuple, should be empty\n\
638Returns: True if the shutdown completed successfully (i.e. both sides\n\
639 have sent closure alerts), false otherwise (i.e. you have to\n\
640 wait for a ZeroReturnError on a recv() method call\n\
641";
642static PyObject *
643ssl_Connection_shutdown(ssl_ConnectionObj *self, PyObject *args)
644{
645 int ret;
646
647 if (!PyArg_ParseTuple(args, ":shutdown"))
648 return NULL;
649
650 MY_BEGIN_ALLOW_THREADS(self->tstate)
651 ret = SSL_shutdown(self->ssl);
652 MY_END_ALLOW_THREADS(self->tstate)
653
654 if (PyErr_Occurred())
655 {
656 flush_error_queue();
657 return NULL;
658 }
659
660 if (ret < 0)
661 {
662 exception_from_error_queue();
663 return NULL;
664 }
665 else if (ret > 0)
666 {
667 Py_INCREF(Py_True);
668 return Py_True;
669 }
670 else
671 {
672 Py_INCREF(Py_False);
673 return Py_False;
674 }
675}
676
677static char ssl_Connection_get_cipher_list_doc[] = "\n\
678Get the session cipher list\n\
679WARNING: API change! This used to take an optional argument, and return a\n\
680string.\n\
681\n\
682Arguments: self - The Connection object\n\
683 args - The Python argument tuple, should be empty\n\
684Returns: A list of cipher strings\n\
685";
686static PyObject *
687ssl_Connection_get_cipher_list(ssl_ConnectionObj *self, PyObject *args)
688{
689 int idx = 0;
690 const char *ret;
691 PyObject *lst, *item;
692
693 if (!PyArg_ParseTuple(args, ":get_cipher_list"))
694 return NULL;
695
696 lst = PyList_New(0);
697 while ((ret = SSL_get_cipher_list(self->ssl, idx)) != NULL)
698 {
699 item = PyString_FromString(ret);
700 PyList_Append(lst, item);
701 Py_DECREF(item);
702 idx++;
703 }
704 return lst;
705}
706
707static char ssl_Connection_makefile_doc[] = "\n\
708The makefile() method is not implemented, since there is no dup semantics\n\
709for SSL connections\n\
710XXX: Return self instead?\n\
711\n\
712Arguments: self - The Connection object\n\
713 args - The Python argument tuple, should be empty\n\
714Returns: NULL\n\
715";
716static PyObject *
717ssl_Connection_makefile(ssl_ConnectionObj *self, PyObject *args)
718{
719 PyErr_SetString(PyExc_NotImplementedError, "Cannot make file object of SSL.Connection");
720 return NULL;
721}
722
723static char ssl_Connection_get_app_data_doc[] = "\n\
724Get application data\n\
725\n\
726Arguments: self - The Connection object\n\
727 args - The Python argument tuple, should be empty\n\
728Returns: The application data\n\
729";
730static PyObject *
731ssl_Connection_get_app_data(ssl_ConnectionObj *self, PyObject *args)
732{
733 if (!PyArg_ParseTuple(args, ":get_app_data"))
734 return NULL;
735
736 Py_INCREF(self->app_data);
737 return self->app_data;
738}
739
740static char ssl_Connection_set_app_data_doc[] = "\n\
741Set application data\n\
742\n\
743Arguments: self - The Connection object\n\
744 args - The Python argument tuple, should be\n\
745 data - The application data\n\
746Returns: None\n\
747";
748static PyObject *
749ssl_Connection_set_app_data(ssl_ConnectionObj *self, PyObject *args)
750{
751 PyObject *data;
752
753 if (!PyArg_ParseTuple(args, "O:set_app_data", &data))
754 return NULL;
755
756 Py_DECREF(self->app_data);
757 Py_INCREF(data);
758 self->app_data = data;
759
760 Py_INCREF(Py_None);
761 return Py_None;
762}
763
Jean-Paul Calderone72b8f0f2008-02-21 23:57:40 -0500764static char ssl_Connection_get_shutdown_doc[] = "\n\
765Get shutdown state\n\
766\n\
767Arguments: self - The Connection object\n\
768 args - The Python argument tuple, should be empty\n\
769Returns: The shutdown state, a bitmask of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.\n\
770";
771static PyObject *
772ssl_Connection_get_shutdown(ssl_ConnectionObj *self, PyObject *args)
773{
774 if (!PyArg_ParseTuple(args, ":get_shutdown"))
775 return NULL;
776
777 return PyInt_FromLong((long)SSL_get_shutdown(self->ssl));
778}
779
780static char ssl_Connection_set_shutdown_doc[] = "\n\
781Set shutdown state\n\
782\n\
783Arguments: self - The Connection object\n\
784 args - The Python argument tuple, should be\n\
785 shutdown state - bitmask of SENT_SHUTDOWN, RECEIVED_SHUTDOWN.\n\
786Returns: None\n\
787";
788static PyObject *
789ssl_Connection_set_shutdown(ssl_ConnectionObj *self, PyObject *args)
790{
791 int shutdown;
792
793 if (!PyArg_ParseTuple(args, "i:set_shutdown", &shutdown))
794 return NULL;
795
796 SSL_set_shutdown(self->ssl, shutdown);
797 Py_INCREF(Py_None);
798 return Py_None;
799}
800
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500801static char ssl_Connection_state_string_doc[] = "\n\
802Get a verbose state description\n\
803\n\
804Arguments: self - The Connection object\n\
805 args - The Python argument tuple, should be empty\n\
806Returns: A string representing the state\n\
807";
808static PyObject *
809ssl_Connection_state_string(ssl_ConnectionObj *self, PyObject *args)
810{
811 if (!PyArg_ParseTuple(args, ":state_string"))
812 return NULL;
813
814 return PyString_FromString(SSL_state_string_long(self->ssl));
815}
816
817static char ssl_Connection_sock_shutdown_doc[] = "\n\
818See shutdown(2)\n\
819\n\
820Arguments: self - The Connection object\n\
821 args - The Python argument tuple, should be whatever the\n\
822 socket's shutdown() method expects\n\
823Returns: What the socket's shutdown() method returns\n\
824";
825static PyObject *
826ssl_Connection_sock_shutdown(ssl_ConnectionObj *self, PyObject *args)
827{
828 PyObject *meth, *ret;
829
830 if ((meth = PyObject_GetAttrString(self->socket, "shutdown")) == NULL)
831 return NULL;
832 ret = PyEval_CallObject(meth, args);
833 Py_DECREF(meth);
834 return ret;
835}
836
837static char ssl_Connection_get_peer_certificate_doc[] = "\n\
838Retrieve the other side's certificate (if any)\n\
839\n\
840Arguments: self - The Connection object\n\
841 args - The Python argument tuple, should be empty\n\
842Returns: The peer's certificate\n\
843";
844static PyObject *
845ssl_Connection_get_peer_certificate(ssl_ConnectionObj *self, PyObject *args)
846{
847 X509 *cert;
848
849 if (!PyArg_ParseTuple(args, ":get_peer_certificate"))
850 return NULL;
851
852 cert = SSL_get_peer_certificate(self->ssl);
853 if (cert != NULL)
854 {
855 return (PyObject *)crypto_X509_New(cert, 1);
856 }
857 else
858 {
859 Py_INCREF(Py_None);
860 return Py_None;
861 }
862}
863
864static char ssl_Connection_want_read_doc[] = "\n\
865Checks if more data has to be read from the transport layer to complete an\n\
866operation.\n\
867\n\
868Arguments: self - The Connection object\n\
869 args - The Python argument tuple, should be empty\n\
870Returns: True iff more data has to be read\n\
871";
872static PyObject *
873ssl_Connection_want_read(ssl_ConnectionObj *self, PyObject *args)
874{
875 if (!PyArg_ParseTuple(args, ":want_read"))
876 return NULL;
877
878 return PyInt_FromLong((long)SSL_want_read(self->ssl));
879}
880
881static char ssl_Connection_want_write_doc[] = "\n\
882Checks if there is data to write to the transport layer to complete an\n\
883operation.\n\
884\n\
885Arguments: self - The Connection object\n\
886 args - The Python argument tuple, should be empty\n\
887Returns: True iff there is data to write\n\
888";
889static PyObject *
890ssl_Connection_want_write(ssl_ConnectionObj *self, PyObject *args)
891{
892 if (!PyArg_ParseTuple(args, ":want_write"))
893 return NULL;
894
895 return PyInt_FromLong((long)SSL_want_write(self->ssl));
896}
897
898/*
899 * Member methods in the Connection object
900 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
901 * { 'name', (PyCFunction)ssl_Connection_name, METH_VARARGS }
902 * for convenience
903 * ADD_ALIAS(name,real) creates an "alias" of the ssl_Connection_real
904 * function with the name 'name'
905 */
906#define ADD_METHOD(name) \
907 { #name, (PyCFunction)ssl_Connection_##name, METH_VARARGS, ssl_Connection_##name##_doc }
908#define ADD_ALIAS(name,real) \
909 { #name, (PyCFunction)ssl_Connection_##real, METH_VARARGS, ssl_Connection_##real##_doc }
910static PyMethodDef ssl_Connection_methods[] =
911{
912 ADD_METHOD(get_context),
913 ADD_METHOD(pending),
914 ADD_METHOD(send),
915 ADD_ALIAS (write, send),
916 ADD_METHOD(sendall),
917 ADD_METHOD(recv),
918 ADD_ALIAS (read, recv),
919 ADD_METHOD(renegotiate),
920 ADD_METHOD(do_handshake),
921#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x00907000L
922 ADD_METHOD(renegotiate_pending),
923#endif
924 ADD_METHOD(total_renegotiations),
925 ADD_METHOD(connect),
926 ADD_METHOD(connect_ex),
927 ADD_METHOD(accept),
928 ADD_METHOD(shutdown),
929 ADD_METHOD(get_cipher_list),
930 ADD_METHOD(makefile),
931 ADD_METHOD(get_app_data),
932 ADD_METHOD(set_app_data),
Jean-Paul Calderone72b8f0f2008-02-21 23:57:40 -0500933 ADD_METHOD(get_shutdown),
934 ADD_METHOD(set_shutdown),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500935 ADD_METHOD(state_string),
936 ADD_METHOD(sock_shutdown),
937 ADD_METHOD(get_peer_certificate),
938 ADD_METHOD(want_read),
939 ADD_METHOD(want_write),
940 ADD_METHOD(set_accept_state),
941 ADD_METHOD(set_connect_state),
942 { NULL, NULL }
943};
944#undef ADD_ALIAS
945#undef ADD_METHOD
946
947
948/*
949 * Constructor for Connection objects
950 *
951 * Arguments: ctx - An SSL Context to use for this connection
952 * sock - The socket to use for transport layer
953 * Returns: The newly created Connection object
954 */
955ssl_ConnectionObj *
956ssl_Connection_New(ssl_ContextObj *ctx, PyObject *sock)
957{
958 ssl_ConnectionObj *self;
959 int fd;
960
961 self = PyObject_GC_New(ssl_ConnectionObj, &ssl_Connection_Type);
962 if (self == NULL)
963 return NULL;
964
965 Py_INCREF(ctx);
966 self->context = ctx;
967
968 Py_INCREF(sock);
969 self->socket = sock;
970
971 self->ssl = NULL;
972
973 Py_INCREF(Py_None);
974 self->app_data = Py_None;
975
976 self->tstate = NULL;
977
978 fd = PyObject_AsFileDescriptor(self->socket);
979 if (fd < 0)
980 {
981 Py_DECREF(self);
982 return NULL;
983 }
984
985 self->ssl = SSL_new(self->context->ctx);
986 SSL_set_app_data(self->ssl, self);
987 SSL_set_fd(self->ssl, (SOCKET_T)fd);
988
989 PyObject_GC_Track(self);
990
991 return self;
992}
993
994/*
995 * Find attribute
996 *
997 * Arguments: self - The Connection object
998 * name - The attribute name
999 * Returns: A Python object for the attribute, or NULL if something went
1000 * wrong
1001 */
1002static PyObject *
1003ssl_Connection_getattr(ssl_ConnectionObj *self, char *name)
1004{
1005 PyObject *meth;
1006
1007 meth = Py_FindMethod(ssl_Connection_methods, (PyObject *)self, name);
1008
1009 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_AttributeError))
1010 {
1011 PyErr_Clear();
1012 /* Try looking it up in the "socket" instead. */
1013 meth = PyObject_GetAttrString(self->socket, name);
1014 }
1015
1016 return meth;
1017}
1018
1019/*
1020 * Call the visitproc on all contained objects.
1021 *
1022 * Arguments: self - The Connection object
1023 * visit - Function to call
1024 * arg - Extra argument to visit
1025 * Returns: 0 if all goes well, otherwise the return code from the first
1026 * call that gave non-zero result.
1027 */
1028static int
1029ssl_Connection_traverse(ssl_ConnectionObj *self, visitproc visit, void *arg)
1030{
1031 int ret = 0;
1032
1033 if (ret == 0 && self->context != NULL)
1034 ret = visit((PyObject *)self->context, arg);
1035 if (ret == 0 && self->socket != NULL)
1036 ret = visit(self->socket, arg);
1037 if (ret == 0 && self->app_data != NULL)
1038 ret = visit(self->app_data, arg);
1039 return ret;
1040}
1041
1042/*
1043 * Decref all contained objects and zero the pointers.
1044 *
1045 * Arguments: self - The Connection object
1046 * Returns: Always 0.
1047 */
1048static int
1049ssl_Connection_clear(ssl_ConnectionObj *self)
1050{
1051 Py_XDECREF(self->context);
1052 self->context = NULL;
1053 Py_XDECREF(self->socket);
1054 self->socket = NULL;
1055 Py_XDECREF(self->app_data);
1056 self->app_data = NULL;
1057 return 0;
1058}
1059
1060/*
1061 * Deallocate the memory used by the Connection object
1062 *
1063 * Arguments: self - The Connection object
1064 * Returns: None
1065 */
1066static void
1067ssl_Connection_dealloc(ssl_ConnectionObj *self)
1068{
1069 PyObject_GC_UnTrack(self);
1070 if (self->ssl != NULL)
1071 SSL_free(self->ssl);
1072 ssl_Connection_clear(self);
1073 PyObject_GC_Del(self);
1074}
1075
1076PyTypeObject ssl_Connection_Type = {
1077 PyObject_HEAD_INIT(NULL)
1078 0,
1079 "Connection",
1080 sizeof(ssl_ConnectionObj),
1081 0,
1082 (destructor)ssl_Connection_dealloc,
1083 NULL, /* print */
1084 (getattrfunc)ssl_Connection_getattr,
1085 NULL, /* setattr */
1086 NULL, /* compare */
1087 NULL, /* repr */
1088 NULL, /* as_number */
1089 NULL, /* as_sequence */
1090 NULL, /* as_mapping */
1091 NULL, /* hash */
1092 NULL, /* call */
1093 NULL, /* str */
1094 NULL, /* getattro */
1095 NULL, /* setattro */
1096 NULL, /* as_buffer */
1097 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1098 NULL, /* doc */
1099 (traverseproc)ssl_Connection_traverse,
1100 (inquiry)ssl_Connection_clear,
1101};
1102
1103
1104/*
1105 * Initiailze the Connection part of the SSL sub module
1106 *
1107 * Arguments: dict - Dictionary of the OpenSSL.SSL module
1108 * Returns: 1 for success, 0 otherwise
1109 */
1110int
1111init_ssl_connection(PyObject *dict)
1112{
1113 ssl_Connection_Type.ob_type = &PyType_Type;
1114 Py_INCREF(&ssl_Connection_Type);
1115 if (PyDict_SetItemString(dict, "ConnectionType", (PyObject *)&ssl_Connection_Type) != 0)
1116 return 0;
1117
1118 return 1;
1119}
1120