diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-05-05 15:53:45 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-05-05 15:53:45 (GMT) |
commit | a4c2a5c9a0dd12bafa3d36c7ced1d6faed6892d0 (patch) | |
tree | 580756a9c229e916ae9a7064b45db801768fc88a | |
parent | 91165c0b4213112c7706f83e1efc2cc5eb24d0ac (diff) | |
download | cpython-a4c2a5c9a0dd12bafa3d36c7ced1d6faed6892d0.zip cpython-a4c2a5c9a0dd12bafa3d36c7ced1d6faed6892d0.tar.gz cpython-a4c2a5c9a0dd12bafa3d36c7ced1d6faed6892d0.tar.bz2 |
Untabify Modules/_ssl.c
-rw-r--r-- | Modules/_ssl.c | 2692 |
1 files changed, 1346 insertions, 1346 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 44f9386..fe7e8e8 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -19,14 +19,14 @@ #ifdef WITH_THREAD #include "pythread.h" #define PySSL_BEGIN_ALLOW_THREADS { \ - PyThreadState *_save = NULL; \ - if (_ssl_locks_count>0) {_save = PyEval_SaveThread();} -#define PySSL_BLOCK_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save)}; -#define PySSL_UNBLOCK_THREADS if (_ssl_locks_count>0){_save = PyEval_SaveThread()}; -#define PySSL_END_ALLOW_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save);} \ - } + PyThreadState *_save = NULL; \ + if (_ssl_locks_count>0) {_save = PyEval_SaveThread();} +#define PySSL_BLOCK_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save)}; +#define PySSL_UNBLOCK_THREADS if (_ssl_locks_count>0){_save = PyEval_SaveThread()}; +#define PySSL_END_ALLOW_THREADS if (_ssl_locks_count>0){PyEval_RestoreThread(_save);} \ + } -#else /* no WITH_THREAD */ +#else /* no WITH_THREAD */ #define PySSL_BEGIN_ALLOW_THREADS #define PySSL_BLOCK_THREADS @@ -36,36 +36,36 @@ #endif enum py_ssl_error { - /* these mirror ssl.h */ - PY_SSL_ERROR_NONE, - PY_SSL_ERROR_SSL, - PY_SSL_ERROR_WANT_READ, - PY_SSL_ERROR_WANT_WRITE, - PY_SSL_ERROR_WANT_X509_LOOKUP, - PY_SSL_ERROR_SYSCALL, /* look at error stack/return value/errno */ - PY_SSL_ERROR_ZERO_RETURN, - PY_SSL_ERROR_WANT_CONNECT, - /* start of non ssl.h errorcodes */ - PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */ - PY_SSL_ERROR_INVALID_ERROR_CODE + /* these mirror ssl.h */ + PY_SSL_ERROR_NONE, + PY_SSL_ERROR_SSL, + PY_SSL_ERROR_WANT_READ, + PY_SSL_ERROR_WANT_WRITE, + PY_SSL_ERROR_WANT_X509_LOOKUP, + PY_SSL_ERROR_SYSCALL, /* look at error stack/return value/errno */ + PY_SSL_ERROR_ZERO_RETURN, + PY_SSL_ERROR_WANT_CONNECT, + /* start of non ssl.h errorcodes */ + PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */ + PY_SSL_ERROR_INVALID_ERROR_CODE }; enum py_ssl_server_or_client { - PY_SSL_CLIENT, - PY_SSL_SERVER + PY_SSL_CLIENT, + PY_SSL_SERVER }; enum py_ssl_cert_requirements { - PY_SSL_CERT_NONE, - PY_SSL_CERT_OPTIONAL, - PY_SSL_CERT_REQUIRED + PY_SSL_CERT_NONE, + PY_SSL_CERT_OPTIONAL, + PY_SSL_CERT_REQUIRED }; enum py_ssl_version { - PY_SSL_VERSION_SSL2, - PY_SSL_VERSION_SSL3, - PY_SSL_VERSION_SSL23, - PY_SSL_VERSION_TLS1 + PY_SSL_VERSION_SSL2, + PY_SSL_VERSION_SSL3, + PY_SSL_VERSION_SSL23, + PY_SSL_VERSION_TLS1 }; /* Include symbols from _socket module */ @@ -111,14 +111,14 @@ static unsigned int _ssl_locks_count = 0; #endif typedef struct { - PyObject_HEAD - PySocketSockObject *Socket; /* Socket on which we're layered */ - SSL_CTX* ctx; - SSL* ssl; - X509* peer_cert; - char server[X509_NAME_MAXLEN]; - char issuer[X509_NAME_MAXLEN]; - int shutdown_seen_zero; + PyObject_HEAD + PySocketSockObject *Socket; /* Socket on which we're layered */ + SSL_CTX* ctx; + SSL* ssl; + X509* peer_cert; + char server[X509_NAME_MAXLEN]; + char issuer[X509_NAME_MAXLEN]; + int shutdown_seen_zero; } PySSLObject; @@ -126,19 +126,19 @@ static PyTypeObject PySSL_Type; static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args); static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args); static int check_socket_and_wait_for_timeout(PySocketSockObject *s, - int writing); + int writing); static PyObject *PySSL_peercert(PySSLObject *self, PyObject *args); static PyObject *PySSL_cipher(PySSLObject *self); -#define PySSLObject_Check(v) (Py_TYPE(v) == &PySSL_Type) +#define PySSLObject_Check(v) (Py_TYPE(v) == &PySSL_Type) typedef enum { - SOCKET_IS_NONBLOCKING, - SOCKET_IS_BLOCKING, - SOCKET_HAS_TIMED_OUT, - SOCKET_HAS_BEEN_CLOSED, - SOCKET_TOO_LARGE_FOR_SELECT, - SOCKET_OPERATION_OK + SOCKET_IS_NONBLOCKING, + SOCKET_IS_BLOCKING, + SOCKET_HAS_TIMED_OUT, + SOCKET_HAS_BEEN_CLOSED, + SOCKET_TOO_LARGE_FOR_SELECT, + SOCKET_OPERATION_OK } timeout_state; /* Wrap error strings with filename and line # */ @@ -155,294 +155,294 @@ typedef enum { static PyObject * PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno) { - PyObject *v; - char buf[2048]; - char *errstr; - int err; - enum py_ssl_error p = PY_SSL_ERROR_NONE; - - assert(ret <= 0); - - if (obj->ssl != NULL) { - err = SSL_get_error(obj->ssl, ret); - - switch (err) { - case SSL_ERROR_ZERO_RETURN: - errstr = "TLS/SSL connection has been closed"; - p = PY_SSL_ERROR_ZERO_RETURN; - break; - case SSL_ERROR_WANT_READ: - errstr = "The operation did not complete (read)"; - p = PY_SSL_ERROR_WANT_READ; - break; - case SSL_ERROR_WANT_WRITE: - p = PY_SSL_ERROR_WANT_WRITE; - errstr = "The operation did not complete (write)"; - break; - case SSL_ERROR_WANT_X509_LOOKUP: - p = PY_SSL_ERROR_WANT_X509_LOOKUP; - errstr = - "The operation did not complete (X509 lookup)"; - break; - case SSL_ERROR_WANT_CONNECT: - p = PY_SSL_ERROR_WANT_CONNECT; - errstr = "The operation did not complete (connect)"; - break; - case SSL_ERROR_SYSCALL: - { - unsigned long e = ERR_get_error(); - if (e == 0) { - if (ret == 0 || !obj->Socket) { - p = PY_SSL_ERROR_EOF; - errstr = - "EOF occurred in violation of protocol"; - } else if (ret == -1) { - /* underlying BIO reported an I/O error */ - return obj->Socket->errorhandler(); - } else { /* possible? */ - p = PY_SSL_ERROR_SYSCALL; - errstr = "Some I/O error occurred"; - } - } else { - p = PY_SSL_ERROR_SYSCALL; - /* XXX Protected by global interpreter lock */ - errstr = ERR_error_string(e, NULL); - } - break; - } - case SSL_ERROR_SSL: - { - unsigned long e = ERR_get_error(); - p = PY_SSL_ERROR_SSL; - if (e != 0) - /* XXX Protected by global interpreter lock */ - errstr = ERR_error_string(e, NULL); - else { /* possible? */ - errstr = - "A failure in the SSL library occurred"; - } - break; - } - default: - p = PY_SSL_ERROR_INVALID_ERROR_CODE; - errstr = "Invalid error code"; - } - } else { - errstr = ERR_error_string(ERR_peek_last_error(), NULL); - } - PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); - v = Py_BuildValue("(is)", p, buf); - if (v != NULL) { - PyErr_SetObject(PySSLErrorObject, v); - Py_DECREF(v); - } - return NULL; + PyObject *v; + char buf[2048]; + char *errstr; + int err; + enum py_ssl_error p = PY_SSL_ERROR_NONE; + + assert(ret <= 0); + + if (obj->ssl != NULL) { + err = SSL_get_error(obj->ssl, ret); + + switch (err) { + case SSL_ERROR_ZERO_RETURN: + errstr = "TLS/SSL connection has been closed"; + p = PY_SSL_ERROR_ZERO_RETURN; + break; + case SSL_ERROR_WANT_READ: + errstr = "The operation did not complete (read)"; + p = PY_SSL_ERROR_WANT_READ; + break; + case SSL_ERROR_WANT_WRITE: + p = PY_SSL_ERROR_WANT_WRITE; + errstr = "The operation did not complete (write)"; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + p = PY_SSL_ERROR_WANT_X509_LOOKUP; + errstr = + "The operation did not complete (X509 lookup)"; + break; + case SSL_ERROR_WANT_CONNECT: + p = PY_SSL_ERROR_WANT_CONNECT; + errstr = "The operation did not complete (connect)"; + break; + case SSL_ERROR_SYSCALL: + { + unsigned long e = ERR_get_error(); + if (e == 0) { + if (ret == 0 || !obj->Socket) { + p = PY_SSL_ERROR_EOF; + errstr = + "EOF occurred in violation of protocol"; + } else if (ret == -1) { + /* underlying BIO reported an I/O error */ + return obj->Socket->errorhandler(); + } else { /* possible? */ + p = PY_SSL_ERROR_SYSCALL; + errstr = "Some I/O error occurred"; + } + } else { + p = PY_SSL_ERROR_SYSCALL; + /* XXX Protected by global interpreter lock */ + errstr = ERR_error_string(e, NULL); + } + break; + } + case SSL_ERROR_SSL: + { + unsigned long e = ERR_get_error(); + p = PY_SSL_ERROR_SSL; + if (e != 0) + /* XXX Protected by global interpreter lock */ + errstr = ERR_error_string(e, NULL); + else { /* possible? */ + errstr = + "A failure in the SSL library occurred"; + } + break; + } + default: + p = PY_SSL_ERROR_INVALID_ERROR_CODE; + errstr = "Invalid error code"; + } + } else { + errstr = ERR_error_string(ERR_peek_last_error(), NULL); + } + PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); + v = Py_BuildValue("(is)", p, buf); + if (v != NULL) { + PyErr_SetObject(PySSLErrorObject, v); + Py_DECREF(v); + } + return NULL; } static PyObject * _setSSLError (char *errstr, int errcode, char *filename, int lineno) { - char buf[2048]; - PyObject *v; - - if (errstr == NULL) { - errcode = ERR_peek_last_error(); - errstr = ERR_error_string(errcode, NULL); - } - PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); - v = Py_BuildValue("(is)", errcode, buf); - if (v != NULL) { - PyErr_SetObject(PySSLErrorObject, v); - Py_DECREF(v); - } - return NULL; + char buf[2048]; + PyObject *v; + + if (errstr == NULL) { + errcode = ERR_peek_last_error(); + errstr = ERR_error_string(errcode, NULL); + } + PyOS_snprintf(buf, sizeof(buf), "_ssl.c:%d: %s", lineno, errstr); + v = Py_BuildValue("(is)", errcode, buf); + if (v != NULL) { + PyErr_SetObject(PySSLErrorObject, v); + Py_DECREF(v); + } + return NULL; } static PySSLObject * newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, - enum py_ssl_server_or_client socket_type, - enum py_ssl_cert_requirements certreq, - enum py_ssl_version proto_version, - char *cacerts_file, char *ciphers) + enum py_ssl_server_or_client socket_type, + enum py_ssl_cert_requirements certreq, + enum py_ssl_version proto_version, + char *cacerts_file, char *ciphers) { - PySSLObject *self; - char *errstr = NULL; - int ret; - int verification_mode; - - self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ - if (self == NULL) - return NULL; - memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN); - memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN); - self->peer_cert = NULL; - self->ssl = NULL; - self->ctx = NULL; - self->Socket = NULL; - - /* Make sure the SSL error state is initialized */ - (void) ERR_get_state(); - ERR_clear_error(); - - if ((key_file && !cert_file) || (!key_file && cert_file)) { - errstr = ERRSTR("Both the key & certificate files " - "must be specified"); - goto fail; - } - - if ((socket_type == PY_SSL_SERVER) && - ((key_file == NULL) || (cert_file == NULL))) { - errstr = ERRSTR("Both the key & certificate files " - "must be specified for server-side operation"); - goto fail; - } - - PySSL_BEGIN_ALLOW_THREADS - if (proto_version == PY_SSL_VERSION_TLS1) - self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ - else if (proto_version == PY_SSL_VERSION_SSL3) - self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ - else if (proto_version == PY_SSL_VERSION_SSL2) - self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ - else if (proto_version == PY_SSL_VERSION_SSL23) - self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ - PySSL_END_ALLOW_THREADS - - if (self->ctx == NULL) { - errstr = ERRSTR("Invalid SSL protocol variant specified."); - goto fail; - } - - if (ciphers != NULL) { - ret = SSL_CTX_set_cipher_list(self->ctx, ciphers); - if (ret == 0) { - errstr = ERRSTR("No cipher can be selected."); - goto fail; - } - } - - if (certreq != PY_SSL_CERT_NONE) { - if (cacerts_file == NULL) { - errstr = ERRSTR("No root certificates specified for " - "verification of other-side certificates."); - goto fail; - } else { - PySSL_BEGIN_ALLOW_THREADS - ret = SSL_CTX_load_verify_locations(self->ctx, - cacerts_file, - NULL); - PySSL_END_ALLOW_THREADS - if (ret != 1) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail; - } - } - } - if (key_file) { - PySSL_BEGIN_ALLOW_THREADS - ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file, - SSL_FILETYPE_PEM); - PySSL_END_ALLOW_THREADS - if (ret != 1) { - _setSSLError(NULL, ret, __FILE__, __LINE__); - goto fail; - } - - PySSL_BEGIN_ALLOW_THREADS - ret = SSL_CTX_use_certificate_chain_file(self->ctx, - cert_file); - PySSL_END_ALLOW_THREADS - if (ret != 1) { - /* - fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n", - ret, ERR_peek_error(), ERR_peek_last_error(), cert_file); - */ - if (ERR_peek_last_error() != 0) { - _setSSLError(NULL, ret, __FILE__, __LINE__); - goto fail; - } - } - } - - /* ssl compatibility */ - SSL_CTX_set_options(self->ctx, SSL_OP_ALL); - - verification_mode = SSL_VERIFY_NONE; - if (certreq == PY_SSL_CERT_OPTIONAL) - verification_mode = SSL_VERIFY_PEER; - else if (certreq == PY_SSL_CERT_REQUIRED) - verification_mode = (SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT); - SSL_CTX_set_verify(self->ctx, verification_mode, - NULL); /* set verify lvl */ - - PySSL_BEGIN_ALLOW_THREADS - self->ssl = SSL_new(self->ctx); /* New ssl struct */ - PySSL_END_ALLOW_THREADS - SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */ + PySSLObject *self; + char *errstr = NULL; + int ret; + int verification_mode; + + self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ + if (self == NULL) + return NULL; + memset(self->server, '\0', sizeof(char) * X509_NAME_MAXLEN); + memset(self->issuer, '\0', sizeof(char) * X509_NAME_MAXLEN); + self->peer_cert = NULL; + self->ssl = NULL; + self->ctx = NULL; + self->Socket = NULL; + + /* Make sure the SSL error state is initialized */ + (void) ERR_get_state(); + ERR_clear_error(); + + if ((key_file && !cert_file) || (!key_file && cert_file)) { + errstr = ERRSTR("Both the key & certificate files " + "must be specified"); + goto fail; + } + + if ((socket_type == PY_SSL_SERVER) && + ((key_file == NULL) || (cert_file == NULL))) { + errstr = ERRSTR("Both the key & certificate files " + "must be specified for server-side operation"); + goto fail; + } + + PySSL_BEGIN_ALLOW_THREADS + if (proto_version == PY_SSL_VERSION_TLS1) + self->ctx = SSL_CTX_new(TLSv1_method()); /* Set up context */ + else if (proto_version == PY_SSL_VERSION_SSL3) + self->ctx = SSL_CTX_new(SSLv3_method()); /* Set up context */ + else if (proto_version == PY_SSL_VERSION_SSL2) + self->ctx = SSL_CTX_new(SSLv2_method()); /* Set up context */ + else if (proto_version == PY_SSL_VERSION_SSL23) + self->ctx = SSL_CTX_new(SSLv23_method()); /* Set up context */ + PySSL_END_ALLOW_THREADS + + if (self->ctx == NULL) { + errstr = ERRSTR("Invalid SSL protocol variant specified."); + goto fail; + } + + if (ciphers != NULL) { + ret = SSL_CTX_set_cipher_list(self->ctx, ciphers); + if (ret == 0) { + errstr = ERRSTR("No cipher can be selected."); + goto fail; + } + } + + if (certreq != PY_SSL_CERT_NONE) { + if (cacerts_file == NULL) { + errstr = ERRSTR("No root certificates specified for " + "verification of other-side certificates."); + goto fail; + } else { + PySSL_BEGIN_ALLOW_THREADS + ret = SSL_CTX_load_verify_locations(self->ctx, + cacerts_file, + NULL); + PySSL_END_ALLOW_THREADS + if (ret != 1) { + _setSSLError(NULL, 0, __FILE__, __LINE__); + goto fail; + } + } + } + if (key_file) { + PySSL_BEGIN_ALLOW_THREADS + ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file, + SSL_FILETYPE_PEM); + PySSL_END_ALLOW_THREADS + if (ret != 1) { + _setSSLError(NULL, ret, __FILE__, __LINE__); + goto fail; + } + + PySSL_BEGIN_ALLOW_THREADS + ret = SSL_CTX_use_certificate_chain_file(self->ctx, + cert_file); + PySSL_END_ALLOW_THREADS + if (ret != 1) { + /* + fprintf(stderr, "ret is %d, errcode is %lu, %lu, with file \"%s\"\n", + ret, ERR_peek_error(), ERR_peek_last_error(), cert_file); + */ + if (ERR_peek_last_error() != 0) { + _setSSLError(NULL, ret, __FILE__, __LINE__); + goto fail; + } + } + } + + /* ssl compatibility */ + SSL_CTX_set_options(self->ctx, SSL_OP_ALL); + + verification_mode = SSL_VERIFY_NONE; + if (certreq == PY_SSL_CERT_OPTIONAL) + verification_mode = SSL_VERIFY_PEER; + else if (certreq == PY_SSL_CERT_REQUIRED) + verification_mode = (SSL_VERIFY_PEER | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT); + SSL_CTX_set_verify(self->ctx, verification_mode, + NULL); /* set verify lvl */ + + PySSL_BEGIN_ALLOW_THREADS + self->ssl = SSL_new(self->ctx); /* New ssl struct */ + PySSL_END_ALLOW_THREADS + SSL_set_fd(self->ssl, Sock->sock_fd); /* Set the socket for SSL */ #ifdef SSL_MODE_AUTO_RETRY - SSL_set_mode(self->ssl, SSL_MODE_AUTO_RETRY); + SSL_set_mode(self->ssl, SSL_MODE_AUTO_RETRY); #endif - /* If the socket is in non-blocking mode or timeout mode, set the BIO - * to non-blocking mode (blocking is the default) - */ - if (Sock->sock_timeout >= 0.0) { - /* Set both the read and write BIO's to non-blocking mode */ - BIO_set_nbio(SSL_get_rbio(self->ssl), 1); - BIO_set_nbio(SSL_get_wbio(self->ssl), 1); - } - - PySSL_BEGIN_ALLOW_THREADS - if (socket_type == PY_SSL_CLIENT) - SSL_set_connect_state(self->ssl); - else - SSL_set_accept_state(self->ssl); - PySSL_END_ALLOW_THREADS - - self->Socket = Sock; - Py_INCREF(self->Socket); - return self; + /* If the socket is in non-blocking mode or timeout mode, set the BIO + * to non-blocking mode (blocking is the default) + */ + if (Sock->sock_timeout >= 0.0) { + /* Set both the read and write BIO's to non-blocking mode */ + BIO_set_nbio(SSL_get_rbio(self->ssl), 1); + BIO_set_nbio(SSL_get_wbio(self->ssl), 1); + } + + PySSL_BEGIN_ALLOW_THREADS + if (socket_type == PY_SSL_CLIENT) + SSL_set_connect_state(self->ssl); + else + SSL_set_accept_state(self->ssl); + PySSL_END_ALLOW_THREADS + + self->Socket = Sock; + Py_INCREF(self->Socket); + return self; fail: - if (errstr) - PyErr_SetString(PySSLErrorObject, errstr); - Py_DECREF(self); - return NULL; + if (errstr) + PyErr_SetString(PySSLErrorObject, errstr); + Py_DECREF(self); + return NULL; } static PyObject * PySSL_sslwrap(PyObject *self, PyObject *args) { - PySocketSockObject *Sock; - int server_side = 0; - int verification_mode = PY_SSL_CERT_NONE; - int protocol = PY_SSL_VERSION_SSL23; - char *key_file = NULL; - char *cert_file = NULL; - char *cacerts_file = NULL; - char *ciphers = NULL; - - if (!PyArg_ParseTuple(args, "O!i|zziizz:sslwrap", - PySocketModule.Sock_Type, - &Sock, - &server_side, - &key_file, &cert_file, - &verification_mode, &protocol, - &cacerts_file, &ciphers)) - return NULL; - - /* - fprintf(stderr, - "server_side is %d, keyfile %p, certfile %p, verify_mode %d, " - "protocol %d, certs %p\n", - server_side, key_file, cert_file, verification_mode, - protocol, cacerts_file); - */ - - return (PyObject *) newPySSLObject(Sock, key_file, cert_file, - server_side, verification_mode, - protocol, cacerts_file, - ciphers); + PySocketSockObject *Sock; + int server_side = 0; + int verification_mode = PY_SSL_CERT_NONE; + int protocol = PY_SSL_VERSION_SSL23; + char *key_file = NULL; + char *cert_file = NULL; + char *cacerts_file = NULL; + char *ciphers = NULL; + + if (!PyArg_ParseTuple(args, "O!i|zziizz:sslwrap", + PySocketModule.Sock_Type, + &Sock, + &server_side, + &key_file, &cert_file, + &verification_mode, &protocol, + &cacerts_file, &ciphers)) + return NULL; + + /* + fprintf(stderr, + "server_side is %d, keyfile %p, certfile %p, verify_mode %d, " + "protocol %d, certs %p\n", + server_side, key_file, cert_file, verification_mode, + protocol, cacerts_file); + */ + + return (PyObject *) newPySSLObject(Sock, key_file, cert_file, + server_side, verification_mode, + protocol, cacerts_file, + ciphers); } PyDoc_STRVAR(ssl_doc, @@ -453,577 +453,577 @@ PyDoc_STRVAR(ssl_doc, static PyObject *PySSL_SSLdo_handshake(PySSLObject *self) { - int ret; - int err; - int sockstate, nonblocking; - - /* just in case the blocking state of the socket has been changed */ - nonblocking = (self->Socket->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - - /* Actually negotiate SSL connection */ - /* XXX If SSL_do_handshake() returns 0, it's also a failure. */ - do { - PySSL_BEGIN_ALLOW_THREADS - ret = SSL_do_handshake(self->ssl); - err = SSL_get_error(self->ssl, ret); - PySSL_END_ALLOW_THREADS - if(PyErr_CheckSignals()) { - return NULL; - } - if (err == SSL_ERROR_WANT_READ) { - sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); - } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); - } else { - sockstate = SOCKET_OPERATION_OK; - } - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("The handshake operation timed out")); - return NULL; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("Underlying socket has been closed.")); - return NULL; - } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("Underlying socket too large for select().")); - return NULL; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - if (ret < 1) - return PySSL_SetError(self, ret, __FILE__, __LINE__); - self->ssl->debug = 1; - - if (self->peer_cert) - X509_free (self->peer_cert); - PySSL_BEGIN_ALLOW_THREADS - if ((self->peer_cert = SSL_get_peer_certificate(self->ssl))) { - X509_NAME_oneline(X509_get_subject_name(self->peer_cert), - self->server, X509_NAME_MAXLEN); - X509_NAME_oneline(X509_get_issuer_name(self->peer_cert), - self->issuer, X509_NAME_MAXLEN); - } - PySSL_END_ALLOW_THREADS - - Py_INCREF(Py_None); - return Py_None; + int ret; + int err; + int sockstate, nonblocking; + + /* just in case the blocking state of the socket has been changed */ + nonblocking = (self->Socket->sock_timeout >= 0.0); + BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); + BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); + + /* Actually negotiate SSL connection */ + /* XXX If SSL_do_handshake() returns 0, it's also a failure. */ + do { + PySSL_BEGIN_ALLOW_THREADS + ret = SSL_do_handshake(self->ssl); + err = SSL_get_error(self->ssl, ret); + PySSL_END_ALLOW_THREADS + if(PyErr_CheckSignals()) { + return NULL; + } + if (err == SSL_ERROR_WANT_READ) { + sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); + } else if (err == SSL_ERROR_WANT_WRITE) { + sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); + } else { + sockstate = SOCKET_OPERATION_OK; + } + if (sockstate == SOCKET_HAS_TIMED_OUT) { + PyErr_SetString(PySSLErrorObject, + ERRSTR("The handshake operation timed out")); + return NULL; + } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { + PyErr_SetString(PySSLErrorObject, + ERRSTR("Underlying socket has been closed.")); + return NULL; + } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { + PyErr_SetString(PySSLErrorObject, + ERRSTR("Underlying socket too large for select().")); + return NULL; + } else if (sockstate == SOCKET_IS_NONBLOCKING) { + break; + } + } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); + if (ret < 1) + return PySSL_SetError(self, ret, __FILE__, __LINE__); + self->ssl->debug = 1; + + if (self->peer_cert) + X509_free (self->peer_cert); + PySSL_BEGIN_ALLOW_THREADS + if ((self->peer_cert = SSL_get_peer_certificate(self->ssl))) { + X509_NAME_oneline(X509_get_subject_name(self->peer_cert), + self->server, X509_NAME_MAXLEN); + X509_NAME_oneline(X509_get_issuer_name(self->peer_cert), + self->issuer, X509_NAME_MAXLEN); + } + PySSL_END_ALLOW_THREADS + + Py_INCREF(Py_None); + return Py_None; } static PyObject * PySSL_server(PySSLObject *self) { - return PyString_FromString(self->server); + return PyString_FromString(self->server); } static PyObject * PySSL_issuer(PySSLObject *self) { - return PyString_FromString(self->issuer); + return PyString_FromString(self->issuer); } static PyObject * _create_tuple_for_attribute (ASN1_OBJECT *name, ASN1_STRING *value) { - char namebuf[X509_NAME_MAXLEN]; - int buflen; - PyObject *name_obj; - PyObject *value_obj; - PyObject *attr; - unsigned char *valuebuf = NULL; - - buflen = OBJ_obj2txt(namebuf, sizeof(namebuf), name, 0); - if (buflen < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail; - } - name_obj = PyString_FromStringAndSize(namebuf, buflen); - if (name_obj == NULL) - goto fail; - - buflen = ASN1_STRING_to_UTF8(&valuebuf, value); - if (buflen < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - Py_DECREF(name_obj); - goto fail; - } - value_obj = PyUnicode_DecodeUTF8((char *) valuebuf, - buflen, "strict"); - OPENSSL_free(valuebuf); - if (value_obj == NULL) { - Py_DECREF(name_obj); - goto fail; - } - attr = PyTuple_New(2); - if (attr == NULL) { - Py_DECREF(name_obj); - Py_DECREF(value_obj); - goto fail; - } - PyTuple_SET_ITEM(attr, 0, name_obj); - PyTuple_SET_ITEM(attr, 1, value_obj); - return attr; + char namebuf[X509_NAME_MAXLEN]; + int buflen; + PyObject *name_obj; + PyObject *value_obj; + PyObject *attr; + unsigned char *valuebuf = NULL; + + buflen = OBJ_obj2txt(namebuf, sizeof(namebuf), name, 0); + if (buflen < 0) { + _setSSLError(NULL, 0, __FILE__, __LINE__); + goto fail; + } + name_obj = PyString_FromStringAndSize(namebuf, buflen); + if (name_obj == NULL) + goto fail; + + buflen = ASN1_STRING_to_UTF8(&valuebuf, value); + if (buflen < 0) { + _setSSLError(NULL, 0, __FILE__, __LINE__); + Py_DECREF(name_obj); + goto fail; + } + value_obj = PyUnicode_DecodeUTF8((char *) valuebuf, + buflen, "strict"); + OPENSSL_free(valuebuf); + if (value_obj == NULL) { + Py_DECREF(name_obj); + goto fail; + } + attr = PyTuple_New(2); + if (attr == NULL) { + Py_DECREF(name_obj); + Py_DECREF(value_obj); + goto fail; + } + PyTuple_SET_ITEM(attr, 0, name_obj); + PyTuple_SET_ITEM(attr, 1, value_obj); + return attr; fail: - return NULL; + return NULL; } static PyObject * _create_tuple_for_X509_NAME (X509_NAME *xname) { - PyObject *dn = NULL; /* tuple which represents the "distinguished name" */ - PyObject *rdn = NULL; /* tuple to hold a "relative distinguished name" */ - PyObject *rdnt; - PyObject *attr = NULL; /* tuple to hold an attribute */ - int entry_count = X509_NAME_entry_count(xname); - X509_NAME_ENTRY *entry; - ASN1_OBJECT *name; - ASN1_STRING *value; - int index_counter; - int rdn_level = -1; - int retcode; - - dn = PyList_New(0); - if (dn == NULL) - return NULL; - /* now create another tuple to hold the top-level RDN */ - rdn = PyList_New(0); - if (rdn == NULL) - goto fail0; - - for (index_counter = 0; - index_counter < entry_count; - index_counter++) - { - entry = X509_NAME_get_entry(xname, index_counter); - - /* check to see if we've gotten to a new RDN */ - if (rdn_level >= 0) { - if (rdn_level != entry->set) { - /* yes, new RDN */ - /* add old RDN to DN */ - rdnt = PyList_AsTuple(rdn); - Py_DECREF(rdn); - if (rdnt == NULL) - goto fail0; - retcode = PyList_Append(dn, rdnt); - Py_DECREF(rdnt); - if (retcode < 0) - goto fail0; - /* create new RDN */ - rdn = PyList_New(0); - if (rdn == NULL) - goto fail0; - } - } - rdn_level = entry->set; - - /* now add this attribute to the current RDN */ - name = X509_NAME_ENTRY_get_object(entry); - value = X509_NAME_ENTRY_get_data(entry); - attr = _create_tuple_for_attribute(name, value); - /* - fprintf(stderr, "RDN level %d, attribute %s: %s\n", - entry->set, - PyString_AS_STRING(PyTuple_GET_ITEM(attr, 0)), - PyString_AS_STRING(PyTuple_GET_ITEM(attr, 1))); - */ - if (attr == NULL) - goto fail1; - retcode = PyList_Append(rdn, attr); - Py_DECREF(attr); - if (retcode < 0) - goto fail1; - } - /* now, there's typically a dangling RDN */ - if ((rdn != NULL) && (PyList_Size(rdn) > 0)) { - rdnt = PyList_AsTuple(rdn); - Py_DECREF(rdn); - if (rdnt == NULL) - goto fail0; - retcode = PyList_Append(dn, rdnt); - Py_DECREF(rdnt); - if (retcode < 0) - goto fail0; - } - - /* convert list to tuple */ - rdnt = PyList_AsTuple(dn); - Py_DECREF(dn); - if (rdnt == NULL) - return NULL; - return rdnt; + PyObject *dn = NULL; /* tuple which represents the "distinguished name" */ + PyObject *rdn = NULL; /* tuple to hold a "relative distinguished name" */ + PyObject *rdnt; + PyObject *attr = NULL; /* tuple to hold an attribute */ + int entry_count = X509_NAME_entry_count(xname); + X509_NAME_ENTRY *entry; + ASN1_OBJECT *name; + ASN1_STRING *value; + int index_counter; + int rdn_level = -1; + int retcode; + + dn = PyList_New(0); + if (dn == NULL) + return NULL; + /* now create another tuple to hold the top-level RDN */ + rdn = PyList_New(0); + if (rdn == NULL) + goto fail0; + + for (index_counter = 0; + index_counter < entry_count; + index_counter++) + { + entry = X509_NAME_get_entry(xname, index_counter); + + /* check to see if we've gotten to a new RDN */ + if (rdn_level >= 0) { + if (rdn_level != entry->set) { + /* yes, new RDN */ + /* add old RDN to DN */ + rdnt = PyList_AsTuple(rdn); + Py_DECREF(rdn); + if (rdnt == NULL) + goto fail0; + retcode = PyList_Append(dn, rdnt); + Py_DECREF(rdnt); + if (retcode < 0) + goto fail0; + /* create new RDN */ + rdn = PyList_New(0); + if (rdn == NULL) + goto fail0; + } + } + rdn_level = entry->set; + + /* now add this attribute to the current RDN */ + name = X509_NAME_ENTRY_get_object(entry); + value = X509_NAME_ENTRY_get_data(entry); + attr = _create_tuple_for_attribute(name, value); + /* + fprintf(stderr, "RDN level %d, attribute %s: %s\n", + entry->set, + PyString_AS_STRING(PyTuple_GET_ITEM(attr, 0)), + PyString_AS_STRING(PyTuple_GET_ITEM(attr, 1))); + */ + if (attr == NULL) + goto fail1; + retcode = PyList_Append(rdn, attr); + Py_DECREF(attr); + if (retcode < 0) + goto fail1; + } + /* now, there's typically a dangling RDN */ + if ((rdn != NULL) && (PyList_Size(rdn) > 0)) { + rdnt = PyList_AsTuple(rdn); + Py_DECREF(rdn); + if (rdnt == NULL) + goto fail0; + retcode = PyList_Append(dn, rdnt); + Py_DECREF(rdnt); + if (retcode < 0) + goto fail0; + } + + /* convert list to tuple */ + rdnt = PyList_AsTuple(dn); + Py_DECREF(dn); + if (rdnt == NULL) + return NULL; + return rdnt; fail1: - Py_XDECREF(rdn); + Py_XDECREF(rdn); fail0: - Py_XDECREF(dn); - return NULL; + Py_XDECREF(dn); + return NULL; } static PyObject * _get_peer_alt_names (X509 *certificate) { - - /* this code follows the procedure outlined in - OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print() - function to extract the STACK_OF(GENERAL_NAME), - then iterates through the stack to add the - names. */ - - int i, j; - PyObject *peer_alt_names = Py_None; - PyObject *v, *t; - X509_EXTENSION *ext = NULL; - GENERAL_NAMES *names = NULL; - GENERAL_NAME *name; - X509V3_EXT_METHOD *method; - BIO *biobuf = NULL; - char buf[2048]; - char *vptr; - int len; - /* Issue #2973: ASN1_item_d2i() API changed in OpenSSL 0.9.6m */ + + /* this code follows the procedure outlined in + OpenSSL's crypto/x509v3/v3_prn.c:X509v3_EXT_print() + function to extract the STACK_OF(GENERAL_NAME), + then iterates through the stack to add the + names. */ + + int i, j; + PyObject *peer_alt_names = Py_None; + PyObject *v, *t; + X509_EXTENSION *ext = NULL; + GENERAL_NAMES *names = NULL; + GENERAL_NAME *name; + X509V3_EXT_METHOD *method; + BIO *biobuf = NULL; + char buf[2048]; + char *vptr; + int len; + /* Issue #2973: ASN1_item_d2i() API changed in OpenSSL 0.9.6m */ #if OPENSSL_VERSION_NUMBER >= 0x009060dfL - const unsigned char *p; + const unsigned char *p; #else - unsigned char *p; + unsigned char *p; #endif - if (certificate == NULL) - return peer_alt_names; - - /* get a memory buffer */ - biobuf = BIO_new(BIO_s_mem()); - - i = 0; - while ((i = X509_get_ext_by_NID( - certificate, NID_subject_alt_name, i)) >= 0) { - - if (peer_alt_names == Py_None) { - peer_alt_names = PyList_New(0); - if (peer_alt_names == NULL) - goto fail; - } - - /* now decode the altName */ - ext = X509_get_ext(certificate, i); - if(!(method = X509V3_EXT_get(ext))) { - PyErr_SetString(PySSLErrorObject, - ERRSTR("No method for internalizing subjectAltName!")); - goto fail; - } - - p = ext->value->data; - if (method->it) - names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, - &p, - ext->value->length, - ASN1_ITEM_ptr(method->it))); - else - names = (GENERAL_NAMES*) (method->d2i(NULL, - &p, - ext->value->length)); - - for(j = 0; j < sk_GENERAL_NAME_num(names); j++) { - - /* get a rendering of each name in the set of names */ - - name = sk_GENERAL_NAME_value(names, j); - if (name->type == GEN_DIRNAME) { - - /* we special-case DirName as a tuple of tuples of attributes */ - - t = PyTuple_New(2); - if (t == NULL) { - goto fail; - } - - v = PyString_FromString("DirName"); - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 0, v); - - v = _create_tuple_for_X509_NAME (name->d.dirn); - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 1, v); - - } else { - - /* for everything else, we use the OpenSSL print form */ - - (void) BIO_reset(biobuf); - GENERAL_NAME_print(biobuf, name); - len = BIO_gets(biobuf, buf, sizeof(buf)-1); - if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail; - } - vptr = strchr(buf, ':'); - if (vptr == NULL) - goto fail; - t = PyTuple_New(2); - if (t == NULL) - goto fail; - v = PyString_FromStringAndSize(buf, (vptr - buf)); - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 0, v); - v = PyString_FromStringAndSize((vptr + 1), (len - (vptr - buf + 1))); - if (v == NULL) { - Py_DECREF(t); - goto fail; - } - PyTuple_SET_ITEM(t, 1, v); - } - - /* and add that rendering to the list */ - - if (PyList_Append(peer_alt_names, t) < 0) { - Py_DECREF(t); - goto fail; - } - Py_DECREF(t); - } - } - BIO_free(biobuf); - if (peer_alt_names != Py_None) { - v = PyList_AsTuple(peer_alt_names); - Py_DECREF(peer_alt_names); - return v; - } else { - return peer_alt_names; - } - + if (certificate == NULL) + return peer_alt_names; + + /* get a memory buffer */ + biobuf = BIO_new(BIO_s_mem()); + + i = 0; + while ((i = X509_get_ext_by_NID( + certificate, NID_subject_alt_name, i)) >= 0) { + + if (peer_alt_names == Py_None) { + peer_alt_names = PyList_New(0); + if (peer_alt_names == NULL) + goto fail; + } + + /* now decode the altName */ + ext = X509_get_ext(certificate, i); + if(!(method = X509V3_EXT_get(ext))) { + PyErr_SetString(PySSLErrorObject, + ERRSTR("No method for internalizing subjectAltName!")); + goto fail; + } + + p = ext->value->data; + if (method->it) + names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, + &p, + ext->value->length, + ASN1_ITEM_ptr(method->it))); + else + names = (GENERAL_NAMES*) (method->d2i(NULL, + &p, + ext->value->length)); + + for(j = 0; j < sk_GENERAL_NAME_num(names); j++) { + + /* get a rendering of each name in the set of names */ + + name = sk_GENERAL_NAME_value(names, j); + if (name->type == GEN_DIRNAME) { + + /* we special-case DirName as a tuple of tuples of attributes */ + + t = PyTuple_New(2); + if (t == NULL) { + goto fail; + } + + v = PyString_FromString("DirName"); + if (v == NULL) { + Py_DECREF(t); + goto fail; + } + PyTuple_SET_ITEM(t, 0, v); + + v = _create_tuple_for_X509_NAME (name->d.dirn); + if (v == NULL) { + Py_DECREF(t); + goto fail; + } + PyTuple_SET_ITEM(t, 1, v); + + } else { + + /* for everything else, we use the OpenSSL print form */ + + (void) BIO_reset(biobuf); + GENERAL_NAME_print(biobuf, name); + len = BIO_gets(biobuf, buf, sizeof(buf)-1); + if (len < 0) { + _setSSLError(NULL, 0, __FILE__, __LINE__); + goto fail; + } + vptr = strchr(buf, ':'); + if (vptr == NULL) + goto fail; + t = PyTuple_New(2); + if (t == NULL) + goto fail; + v = PyString_FromStringAndSize(buf, (vptr - buf)); + if (v == NULL) { + Py_DECREF(t); + goto fail; + } + PyTuple_SET_ITEM(t, 0, v); + v = PyString_FromStringAndSize((vptr + 1), (len - (vptr - buf + 1))); + if (v == NULL) { + Py_DECREF(t); + goto fail; + } + PyTuple_SET_ITEM(t, 1, v); + } + + /* and add that rendering to the list */ + + if (PyList_Append(peer_alt_names, t) < 0) { + Py_DECREF(t); + goto fail; + } + Py_DECREF(t); + } + } + BIO_free(biobuf); + if (peer_alt_names != Py_None) { + v = PyList_AsTuple(peer_alt_names); + Py_DECREF(peer_alt_names); + return v; + } else { + return peer_alt_names; + } + fail: - if (biobuf != NULL) - BIO_free(biobuf); + if (biobuf != NULL) + BIO_free(biobuf); - if (peer_alt_names != Py_None) { - Py_XDECREF(peer_alt_names); - } + if (peer_alt_names != Py_None) { + Py_XDECREF(peer_alt_names); + } - return NULL; + return NULL; } static PyObject * _decode_certificate (X509 *certificate, int verbose) { - PyObject *retval = NULL; - BIO *biobuf = NULL; - PyObject *peer; - PyObject *peer_alt_names = NULL; - PyObject *issuer; - PyObject *version; - PyObject *sn_obj; - ASN1_INTEGER *serialNumber; - char buf[2048]; - int len; - ASN1_TIME *notBefore, *notAfter; - PyObject *pnotBefore, *pnotAfter; - - retval = PyDict_New(); - if (retval == NULL) - return NULL; - - peer = _create_tuple_for_X509_NAME( - X509_get_subject_name(certificate)); - if (peer == NULL) - goto fail0; - if (PyDict_SetItemString(retval, (const char *) "subject", peer) < 0) { - Py_DECREF(peer); - goto fail0; - } - Py_DECREF(peer); - - if (verbose) { - issuer = _create_tuple_for_X509_NAME( - X509_get_issuer_name(certificate)); - if (issuer == NULL) - goto fail0; - if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) { - Py_DECREF(issuer); - goto fail0; - } - Py_DECREF(issuer); - - version = PyInt_FromLong(X509_get_version(certificate) + 1); - if (PyDict_SetItemString(retval, "version", version) < 0) { - Py_DECREF(version); - goto fail0; - } - Py_DECREF(version); - } - - /* get a memory buffer */ - biobuf = BIO_new(BIO_s_mem()); - - if (verbose) { - - (void) BIO_reset(biobuf); - serialNumber = X509_get_serialNumber(certificate); - /* should not exceed 20 octets, 160 bits, so buf is big enough */ - i2a_ASN1_INTEGER(biobuf, serialNumber); - len = BIO_gets(biobuf, buf, sizeof(buf)-1); - if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail1; - } - sn_obj = PyString_FromStringAndSize(buf, len); - if (sn_obj == NULL) - goto fail1; - if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) { - Py_DECREF(sn_obj); - goto fail1; - } - Py_DECREF(sn_obj); - - (void) BIO_reset(biobuf); - notBefore = X509_get_notBefore(certificate); - ASN1_TIME_print(biobuf, notBefore); - len = BIO_gets(biobuf, buf, sizeof(buf)-1); - if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail1; - } - pnotBefore = PyString_FromStringAndSize(buf, len); - if (pnotBefore == NULL) - goto fail1; - if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) { - Py_DECREF(pnotBefore); - goto fail1; - } - Py_DECREF(pnotBefore); - } - - (void) BIO_reset(biobuf); - notAfter = X509_get_notAfter(certificate); - ASN1_TIME_print(biobuf, notAfter); - len = BIO_gets(biobuf, buf, sizeof(buf)-1); - if (len < 0) { - _setSSLError(NULL, 0, __FILE__, __LINE__); - goto fail1; - } - pnotAfter = PyString_FromStringAndSize(buf, len); - if (pnotAfter == NULL) - goto fail1; - if (PyDict_SetItemString(retval, "notAfter", pnotAfter) < 0) { - Py_DECREF(pnotAfter); - goto fail1; - } - Py_DECREF(pnotAfter); - - /* Now look for subjectAltName */ - - peer_alt_names = _get_peer_alt_names(certificate); - if (peer_alt_names == NULL) - goto fail1; - else if (peer_alt_names != Py_None) { - if (PyDict_SetItemString(retval, "subjectAltName", - peer_alt_names) < 0) { - Py_DECREF(peer_alt_names); - goto fail1; - } - Py_DECREF(peer_alt_names); - } - - BIO_free(biobuf); - return retval; + PyObject *retval = NULL; + BIO *biobuf = NULL; + PyObject *peer; + PyObject *peer_alt_names = NULL; + PyObject *issuer; + PyObject *version; + PyObject *sn_obj; + ASN1_INTEGER *serialNumber; + char buf[2048]; + int len; + ASN1_TIME *notBefore, *notAfter; + PyObject *pnotBefore, *pnotAfter; + + retval = PyDict_New(); + if (retval == NULL) + return NULL; + + peer = _create_tuple_for_X509_NAME( + X509_get_subject_name(certificate)); + if (peer == NULL) + goto fail0; + if (PyDict_SetItemString(retval, (const char *) "subject", peer) < 0) { + Py_DECREF(peer); + goto fail0; + } + Py_DECREF(peer); + + if (verbose) { + issuer = _create_tuple_for_X509_NAME( + X509_get_issuer_name(certificate)); + if (issuer == NULL) + goto fail0; + if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) { + Py_DECREF(issuer); + goto fail0; + } + Py_DECREF(issuer); + + version = PyInt_FromLong(X509_get_version(certificate) + 1); + if (PyDict_SetItemString(retval, "version", version) < 0) { + Py_DECREF(version); + goto fail0; + } + Py_DECREF(version); + } + + /* get a memory buffer */ + biobuf = BIO_new(BIO_s_mem()); + + if (verbose) { + + (void) BIO_reset(biobuf); + serialNumber = X509_get_serialNumber(certificate); + /* should not exceed 20 octets, 160 bits, so buf is big enough */ + i2a_ASN1_INTEGER(biobuf, serialNumber); + len = BIO_gets(biobuf, buf, sizeof(buf)-1); + if (len < 0) { + _setSSLError(NULL, 0, __FILE__, __LINE__); + goto fail1; + } + sn_obj = PyString_FromStringAndSize(buf, len); + if (sn_obj == NULL) + goto fail1; + if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) { + Py_DECREF(sn_obj); + goto fail1; + } + Py_DECREF(sn_obj); + + (void) BIO_reset(biobuf); + notBefore = X509_get_notBefore(certificate); + ASN1_TIME_print(biobuf, notBefore); + len = BIO_gets(biobuf, buf, sizeof(buf)-1); + if (len < 0) { + _setSSLError(NULL, 0, __FILE__, __LINE__); + goto fail1; + } + pnotBefore = PyString_FromStringAndSize(buf, len); + if (pnotBefore == NULL) + goto fail1; + if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) { + Py_DECREF(pnotBefore); + goto fail1; + } + Py_DECREF(pnotBefore); + } + + (void) BIO_reset(biobuf); + notAfter = X509_get_notAfter(certificate); + ASN1_TIME_print(biobuf, notAfter); + len = BIO_gets(biobuf, buf, sizeof(buf)-1); + if (len < 0) { + _setSSLError(NULL, 0, __FILE__, __LINE__); + goto fail1; + } + pnotAfter = PyString_FromStringAndSize(buf, len); + if (pnotAfter == NULL) + goto fail1; + if (PyDict_SetItemString(retval, "notAfter", pnotAfter) < 0) { + Py_DECREF(pnotAfter); + goto fail1; + } + Py_DECREF(pnotAfter); + + /* Now look for subjectAltName */ + + peer_alt_names = _get_peer_alt_names(certificate); + if (peer_alt_names == NULL) + goto fail1; + else if (peer_alt_names != Py_None) { + if (PyDict_SetItemString(retval, "subjectAltName", + peer_alt_names) < 0) { + Py_DECREF(peer_alt_names); + goto fail1; + } + Py_DECREF(peer_alt_names); + } + + BIO_free(biobuf); + return retval; fail1: - if (biobuf != NULL) - BIO_free(biobuf); + if (biobuf != NULL) + BIO_free(biobuf); fail0: - Py_XDECREF(retval); - return NULL; + Py_XDECREF(retval); + return NULL; } static PyObject * PySSL_test_decode_certificate (PyObject *mod, PyObject *args) { - PyObject *retval = NULL; - char *filename = NULL; - X509 *x=NULL; - BIO *cert; - int verbose = 1; + PyObject *retval = NULL; + char *filename = NULL; + X509 *x=NULL; + BIO *cert; + int verbose = 1; - if (!PyArg_ParseTuple(args, "s|i:test_decode_certificate", &filename, &verbose)) - return NULL; + if (!PyArg_ParseTuple(args, "s|i:test_decode_certificate", &filename, &verbose)) + return NULL; - if ((cert=BIO_new(BIO_s_file())) == NULL) { - PyErr_SetString(PySSLErrorObject, "Can't malloc memory to read file"); - goto fail0; - } + if ((cert=BIO_new(BIO_s_file())) == NULL) { + PyErr_SetString(PySSLErrorObject, "Can't malloc memory to read file"); + goto fail0; + } - if (BIO_read_filename(cert,filename) <= 0) { - PyErr_SetString(PySSLErrorObject, "Can't open file"); - goto fail0; - } + if (BIO_read_filename(cert,filename) <= 0) { + PyErr_SetString(PySSLErrorObject, "Can't open file"); + goto fail0; + } - x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL); - if (x == NULL) { - PyErr_SetString(PySSLErrorObject, "Error decoding PEM-encoded file"); - goto fail0; - } + x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL); + if (x == NULL) { + PyErr_SetString(PySSLErrorObject, "Error decoding PEM-encoded file"); + goto fail0; + } - retval = _decode_certificate(x, verbose); + retval = _decode_certificate(x, verbose); fail0: - - if (cert != NULL) BIO_free(cert); - return retval; + + if (cert != NULL) BIO_free(cert); + return retval; } static PyObject * PySSL_peercert(PySSLObject *self, PyObject *args) { - PyObject *retval = NULL; - int len; - int verification; - PyObject *binary_mode = Py_None; - - if (!PyArg_ParseTuple(args, "|O:peer_certificate", &binary_mode)) - return NULL; - - if (!self->peer_cert) - Py_RETURN_NONE; - - if (PyObject_IsTrue(binary_mode)) { - /* return cert in DER-encoded format */ - - unsigned char *bytes_buf = NULL; - - bytes_buf = NULL; - len = i2d_X509(self->peer_cert, &bytes_buf); - if (len < 0) { - PySSL_SetError(self, len, __FILE__, __LINE__); - return NULL; - } - retval = PyString_FromStringAndSize((const char *) bytes_buf, len); - OPENSSL_free(bytes_buf); - return retval; - - } else { - - verification = SSL_CTX_get_verify_mode(self->ctx); - if ((verification & SSL_VERIFY_PEER) == 0) - return PyDict_New(); - else - return _decode_certificate (self->peer_cert, 0); - } + PyObject *retval = NULL; + int len; + int verification; + PyObject *binary_mode = Py_None; + + if (!PyArg_ParseTuple(args, "|O:peer_certificate", &binary_mode)) + return NULL; + + if (!self->peer_cert) + Py_RETURN_NONE; + + if (PyObject_IsTrue(binary_mode)) { + /* return cert in DER-encoded format */ + + unsigned char *bytes_buf = NULL; + + bytes_buf = NULL; + len = i2d_X509(self->peer_cert, &bytes_buf); + if (len < 0) { + PySSL_SetError(self, len, __FILE__, __LINE__); + return NULL; + } + retval = PyString_FromStringAndSize((const char *) bytes_buf, len); + OPENSSL_free(bytes_buf); + return retval; + + } else { + + verification = SSL_CTX_get_verify_mode(self->ctx); + if ((verification & SSL_VERIFY_PEER) == 0) + return PyDict_New(); + else + return _decode_certificate (self->peer_cert, 0); + } } PyDoc_STRVAR(PySSL_peercert_doc, @@ -1040,60 +1040,60 @@ return the certificate even if it wasn't validated."); static PyObject *PySSL_cipher (PySSLObject *self) { - PyObject *retval, *v; - SSL_CIPHER *current; - char *cipher_name; - char *cipher_protocol; - - if (self->ssl == NULL) - return Py_None; - current = SSL_get_current_cipher(self->ssl); - if (current == NULL) - return Py_None; - - retval = PyTuple_New(3); - if (retval == NULL) - return NULL; - - cipher_name = (char *) SSL_CIPHER_get_name(current); - if (cipher_name == NULL) { - PyTuple_SET_ITEM(retval, 0, Py_None); - } else { - v = PyString_FromString(cipher_name); - if (v == NULL) - goto fail0; - PyTuple_SET_ITEM(retval, 0, v); - } - cipher_protocol = SSL_CIPHER_get_version(current); - if (cipher_protocol == NULL) { - PyTuple_SET_ITEM(retval, 1, Py_None); - } else { - v = PyString_FromString(cipher_protocol); - if (v == NULL) - goto fail0; - PyTuple_SET_ITEM(retval, 1, v); - } - v = PyInt_FromLong(SSL_CIPHER_get_bits(current, NULL)); - if (v == NULL) - goto fail0; - PyTuple_SET_ITEM(retval, 2, v); - return retval; - + PyObject *retval, *v; + SSL_CIPHER *current; + char *cipher_name; + char *cipher_protocol; + + if (self->ssl == NULL) + return Py_None; + current = SSL_get_current_cipher(self->ssl); + if (current == NULL) + return Py_None; + + retval = PyTuple_New(3); + if (retval == NULL) + return NULL; + + cipher_name = (char *) SSL_CIPHER_get_name(current); + if (cipher_name == NULL) { + PyTuple_SET_ITEM(retval, 0, Py_None); + } else { + v = PyString_FromString(cipher_name); + if (v == NULL) + goto fail0; + PyTuple_SET_ITEM(retval, 0, v); + } + cipher_protocol = SSL_CIPHER_get_version(current); + if (cipher_protocol == NULL) { + PyTuple_SET_ITEM(retval, 1, Py_None); + } else { + v = PyString_FromString(cipher_protocol); + if (v == NULL) + goto fail0; + PyTuple_SET_ITEM(retval, 1, v); + } + v = PyInt_FromLong(SSL_CIPHER_get_bits(current, NULL)); + if (v == NULL) + goto fail0; + PyTuple_SET_ITEM(retval, 2, v); + return retval; + fail0: - Py_DECREF(retval); - return NULL; + Py_DECREF(retval); + return NULL; } static void PySSL_dealloc(PySSLObject *self) { - if (self->peer_cert) /* Possible not to have one? */ - X509_free (self->peer_cert); - if (self->ssl) - SSL_free(self->ssl); - if (self->ctx) - SSL_CTX_free(self->ctx); - Py_XDECREF(self->Socket); - PyObject_Del(self); + if (self->peer_cert) /* Possible not to have one? */ + X509_free (self->peer_cert); + if (self->ssl) + SSL_free(self->ssl); + if (self->ctx) + SSL_CTX_free(self->ctx); + Py_XDECREF(self->Socket); + PyObject_Del(self); } /* If the socket has a timeout, do a select()/poll() on the socket. @@ -1104,137 +1104,137 @@ static void PySSL_dealloc(PySSLObject *self) static int check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing) { - fd_set fds; - struct timeval tv; - int rc; - - /* Nothing to do unless we're in timeout mode (not non-blocking) */ - if (s->sock_timeout < 0.0) - return SOCKET_IS_BLOCKING; - else if (s->sock_timeout == 0.0) - return SOCKET_IS_NONBLOCKING; - - /* Guard against closed socket */ - if (s->sock_fd < 0) - return SOCKET_HAS_BEEN_CLOSED; - - /* Prefer poll, if available, since you can poll() any fd - * which can't be done with select(). */ + fd_set fds; + struct timeval tv; + int rc; + + /* Nothing to do unless we're in timeout mode (not non-blocking) */ + if (s->sock_timeout < 0.0) + return SOCKET_IS_BLOCKING; + else if (s->sock_timeout == 0.0) + return SOCKET_IS_NONBLOCKING; + + /* Guard against closed socket */ + if (s->sock_fd < 0) + return SOCKET_HAS_BEEN_CLOSED; + + /* Prefer poll, if available, since you can poll() any fd + * which can't be done with select(). */ #ifdef HAVE_POLL - { - struct pollfd pollfd; - int timeout; + { + struct pollfd pollfd; + int timeout; - pollfd.fd = s->sock_fd; - pollfd.events = writing ? POLLOUT : POLLIN; + pollfd.fd = s->sock_fd; + pollfd.events = writing ? POLLOUT : POLLIN; - /* s->sock_timeout is in seconds, timeout in ms */ - timeout = (int)(s->sock_timeout * 1000 + 0.5); - PySSL_BEGIN_ALLOW_THREADS - rc = poll(&pollfd, 1, timeout); - PySSL_END_ALLOW_THREADS + /* s->sock_timeout is in seconds, timeout in ms */ + timeout = (int)(s->sock_timeout * 1000 + 0.5); + PySSL_BEGIN_ALLOW_THREADS + rc = poll(&pollfd, 1, timeout); + PySSL_END_ALLOW_THREADS - goto normal_return; - } + goto normal_return; + } #endif - /* Guard against socket too large for select*/ + /* Guard against socket too large for select*/ #ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE - if (s->sock_fd >= FD_SETSIZE) - return SOCKET_TOO_LARGE_FOR_SELECT; + if (s->sock_fd >= FD_SETSIZE) + return SOCKET_TOO_LARGE_FOR_SELECT; #endif - /* Construct the arguments to select */ - tv.tv_sec = (int)s->sock_timeout; - tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6); - FD_ZERO(&fds); - FD_SET(s->sock_fd, &fds); + /* Construct the arguments to select */ + tv.tv_sec = (int)s->sock_timeout; + tv.tv_usec = (int)((s->sock_timeout - tv.tv_sec) * 1e6); + FD_ZERO(&fds); + FD_SET(s->sock_fd, &fds); - /* See if the socket is ready */ - PySSL_BEGIN_ALLOW_THREADS - if (writing) - rc = select(s->sock_fd+1, NULL, &fds, NULL, &tv); - else - rc = select(s->sock_fd+1, &fds, NULL, NULL, &tv); - PySSL_END_ALLOW_THREADS + /* See if the socket is ready */ + PySSL_BEGIN_ALLOW_THREADS + if (writing) + rc = select(s->sock_fd+1, NULL, &fds, NULL, &tv); + else + rc = select(s->sock_fd+1, &fds, NULL, NULL, &tv); + PySSL_END_ALLOW_THREADS #ifdef HAVE_POLL normal_return: #endif - /* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise - (when we are able to write or when there's something to read) */ - return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK; + /* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise + (when we are able to write or when there's something to read) */ + return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK; } static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args) { - Py_buffer buf; - int len; - int sockstate; - int err; - int nonblocking; - - if (!PyArg_ParseTuple(args, "s*:write", &buf)) - return NULL; - - /* just in case the blocking state of the socket has been changed */ - nonblocking = (self->Socket->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - - sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The write operation timed out"); - goto error; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket has been closed."); - goto error; - } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket too large for select()."); - goto error; - } - do { - PySSL_BEGIN_ALLOW_THREADS - len = SSL_write(self->ssl, buf.buf, buf.len); - err = SSL_get_error(self->ssl, len); - PySSL_END_ALLOW_THREADS - if (PyErr_CheckSignals()) { - goto error; - } - if (err == SSL_ERROR_WANT_READ) { - sockstate = - check_socket_and_wait_for_timeout(self->Socket, 0); - } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = - check_socket_and_wait_for_timeout(self->Socket, 1); - } else { - sockstate = SOCKET_OPERATION_OK; - } - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The write operation timed out"); - goto error; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket has been closed."); - goto error; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - - PyBuffer_Release(&buf); - if (len > 0) - return PyInt_FromLong(len); - else - return PySSL_SetError(self, len, __FILE__, __LINE__); + Py_buffer buf; + int len; + int sockstate; + int err; + int nonblocking; + + if (!PyArg_ParseTuple(args, "s*:write", &buf)) + return NULL; + + /* just in case the blocking state of the socket has been changed */ + nonblocking = (self->Socket->sock_timeout >= 0.0); + BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); + BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); + + sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); + if (sockstate == SOCKET_HAS_TIMED_OUT) { + PyErr_SetString(PySSLErrorObject, + "The write operation timed out"); + goto error; + } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { + PyErr_SetString(PySSLErrorObject, + "Underlying socket has been closed."); + goto error; + } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { + PyErr_SetString(PySSLErrorObject, + "Underlying socket too large for select()."); + goto error; + } + do { + PySSL_BEGIN_ALLOW_THREADS + len = SSL_write(self->ssl, buf.buf, buf.len); + err = SSL_get_error(self->ssl, len); + PySSL_END_ALLOW_THREADS + if (PyErr_CheckSignals()) { + goto error; + } + if (err == SSL_ERROR_WANT_READ) { + sockstate = + check_socket_and_wait_for_timeout(self->Socket, 0); + } else if (err == SSL_ERROR_WANT_WRITE) { + sockstate = + check_socket_and_wait_for_timeout(self->Socket, 1); + } else { + sockstate = SOCKET_OPERATION_OK; + } + if (sockstate == SOCKET_HAS_TIMED_OUT) { + PyErr_SetString(PySSLErrorObject, + "The write operation timed out"); + goto error; + } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { + PyErr_SetString(PySSLErrorObject, + "Underlying socket has been closed."); + goto error; + } else if (sockstate == SOCKET_IS_NONBLOCKING) { + break; + } + } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); + + PyBuffer_Release(&buf); + if (len > 0) + return PyInt_FromLong(len); + else + return PySSL_SetError(self, len, __FILE__, __LINE__); error: - PyBuffer_Release(&buf); - return NULL; + PyBuffer_Release(&buf); + return NULL; } PyDoc_STRVAR(PySSL_SSLwrite_doc, @@ -1245,15 +1245,15 @@ of bytes written."); static PyObject *PySSL_SSLpending(PySSLObject *self) { - int count = 0; - - PySSL_BEGIN_ALLOW_THREADS - count = SSL_pending(self->ssl); - PySSL_END_ALLOW_THREADS - if (count < 0) - return PySSL_SetError(self, count, __FILE__, __LINE__); - else - return PyInt_FromLong(count); + int count = 0; + + PySSL_BEGIN_ALLOW_THREADS + count = SSL_pending(self->ssl); + PySSL_END_ALLOW_THREADS + if (count < 0) + return PySSL_SetError(self, count, __FILE__, __LINE__); + else + return PyInt_FromLong(count); } PyDoc_STRVAR(PySSL_SSLpending_doc, @@ -1264,96 +1264,96 @@ pending on the connection.\n"); static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) { - PyObject *buf; - int count = 0; - int len = 1024; - int sockstate; - int err; - int nonblocking; - - if (!PyArg_ParseTuple(args, "|i:read", &len)) - return NULL; - - if (!(buf = PyString_FromStringAndSize((char *) 0, len))) - return NULL; - - /* just in case the blocking state of the socket has been changed */ - nonblocking = (self->Socket->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - - /* first check if there are bytes ready to be read */ - PySSL_BEGIN_ALLOW_THREADS - count = SSL_pending(self->ssl); - PySSL_END_ALLOW_THREADS - - if (!count) { - sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The read operation timed out"); - Py_DECREF(buf); - return NULL; - } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket too large for select()."); - Py_DECREF(buf); - return NULL; - } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { - if (SSL_get_shutdown(self->ssl) != - SSL_RECEIVED_SHUTDOWN) - { - Py_DECREF(buf); - PyErr_SetString(PySSLErrorObject, - "Socket closed without SSL shutdown handshake"); - return NULL; - } else { - /* should contain a zero-length string */ - _PyString_Resize(&buf, 0); - return buf; - } - } - } - do { - PySSL_BEGIN_ALLOW_THREADS - count = SSL_read(self->ssl, PyString_AsString(buf), len); - err = SSL_get_error(self->ssl, count); - PySSL_END_ALLOW_THREADS - if(PyErr_CheckSignals()) { - Py_DECREF(buf); - return NULL; - } - if (err == SSL_ERROR_WANT_READ) { - sockstate = - check_socket_and_wait_for_timeout(self->Socket, 0); - } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = - check_socket_and_wait_for_timeout(self->Socket, 1); - } else if ((err == SSL_ERROR_ZERO_RETURN) && - (SSL_get_shutdown(self->ssl) == - SSL_RECEIVED_SHUTDOWN)) - { - _PyString_Resize(&buf, 0); - return buf; - } else { - sockstate = SOCKET_OPERATION_OK; - } - if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySSLErrorObject, - "The read operation timed out"); - Py_DECREF(buf); - return NULL; - } else if (sockstate == SOCKET_IS_NONBLOCKING) { - break; - } - } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); - if (count <= 0) { - Py_DECREF(buf); - return PySSL_SetError(self, count, __FILE__, __LINE__); - } - if (count != len) - _PyString_Resize(&buf, count); - return buf; + PyObject *buf; + int count = 0; + int len = 1024; + int sockstate; + int err; + int nonblocking; + + if (!PyArg_ParseTuple(args, "|i:read", &len)) + return NULL; + + if (!(buf = PyString_FromStringAndSize((char *) 0, len))) + return NULL; + + /* just in case the blocking state of the socket has been changed */ + nonblocking = (self->Socket->sock_timeout >= 0.0); + BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); + BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); + + /* first check if there are bytes ready to be read */ + PySSL_BEGIN_ALLOW_THREADS + count = SSL_pending(self->ssl); + PySSL_END_ALLOW_THREADS + + if (!count) { + sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); + if (sockstate == SOCKET_HAS_TIMED_OUT) { + PyErr_SetString(PySSLErrorObject, + "The read operation timed out"); + Py_DECREF(buf); + return NULL; + } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { + PyErr_SetString(PySSLErrorObject, + "Underlying socket too large for select()."); + Py_DECREF(buf); + return NULL; + } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { + if (SSL_get_shutdown(self->ssl) != + SSL_RECEIVED_SHUTDOWN) + { + Py_DECREF(buf); + PyErr_SetString(PySSLErrorObject, + "Socket closed without SSL shutdown handshake"); + return NULL; + } else { + /* should contain a zero-length string */ + _PyString_Resize(&buf, 0); + return buf; + } + } + } + do { + PySSL_BEGIN_ALLOW_THREADS + count = SSL_read(self->ssl, PyString_AsString(buf), len); + err = SSL_get_error(self->ssl, count); + PySSL_END_ALLOW_THREADS + if(PyErr_CheckSignals()) { + Py_DECREF(buf); + return NULL; + } + if (err == SSL_ERROR_WANT_READ) { + sockstate = + check_socket_and_wait_for_timeout(self->Socket, 0); + } else if (err == SSL_ERROR_WANT_WRITE) { + sockstate = + check_socket_and_wait_for_timeout(self->Socket, 1); + } else if ((err == SSL_ERROR_ZERO_RETURN) && + (SSL_get_shutdown(self->ssl) == + SSL_RECEIVED_SHUTDOWN)) + { + _PyString_Resize(&buf, 0); + return buf; + } else { + sockstate = SOCKET_OPERATION_OK; + } + if (sockstate == SOCKET_HAS_TIMED_OUT) { + PyErr_SetString(PySSLErrorObject, + "The read operation timed out"); + Py_DECREF(buf); + return NULL; + } else if (sockstate == SOCKET_IS_NONBLOCKING) { + break; + } + } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); + if (count <= 0) { + Py_DECREF(buf); + return PySSL_SetError(self, count, __FILE__, __LINE__); + } + if (count != len) + _PyString_Resize(&buf, count); + return buf; } PyDoc_STRVAR(PySSL_SSLread_doc, @@ -1363,82 +1363,82 @@ Read up to len bytes from the SSL socket."); static PyObject *PySSL_SSLshutdown(PySSLObject *self) { - int err, ssl_err, sockstate, nonblocking; - int zeros = 0; - - /* Guard against closed socket */ - if (self->Socket->sock_fd < 0) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket has been closed."); - return NULL; - } - - /* Just in case the blocking state of the socket has been changed */ - nonblocking = (self->Socket->sock_timeout >= 0.0); - BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); - BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); - - while (1) { - PySSL_BEGIN_ALLOW_THREADS - /* Disable read-ahead so that unwrap can work correctly. - * Otherwise OpenSSL might read in too much data, - * eating clear text data that happens to be - * transmitted after the SSL shutdown. - * Should be safe to call repeatedly everytime this - * function is used and the shutdown_seen_zero != 0 - * condition is met. - */ - if (self->shutdown_seen_zero) - SSL_set_read_ahead(self->ssl, 0); - err = SSL_shutdown(self->ssl); - PySSL_END_ALLOW_THREADS - /* If err == 1, a secure shutdown with SSL_shutdown() is complete */ - if (err > 0) - break; - if (err == 0) { - /* Don't loop endlessly; instead preserve legacy - behaviour of trying SSL_shutdown() only twice. - This looks necessary for OpenSSL < 0.9.8m */ - if (++zeros > 1) - break; - /* Shutdown was sent, now try receiving */ - self->shutdown_seen_zero = 1; - continue; - } - - /* Possibly retry shutdown until timeout or failure */ - ssl_err = SSL_get_error(self->ssl, err); - if (ssl_err == SSL_ERROR_WANT_READ) - sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); - else if (ssl_err == SSL_ERROR_WANT_WRITE) - sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); - else - break; - if (sockstate == SOCKET_HAS_TIMED_OUT) { - if (ssl_err == SSL_ERROR_WANT_READ) - PyErr_SetString(PySSLErrorObject, - "The read operation timed out"); - else - PyErr_SetString(PySSLErrorObject, - "The write operation timed out"); - return NULL; - } - else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { - PyErr_SetString(PySSLErrorObject, - "Underlying socket too large for select()."); - return NULL; - } - else if (sockstate != SOCKET_OPERATION_OK) - /* Retain the SSL error code */ - break; - } - - if (err < 0) - return PySSL_SetError(self, err, __FILE__, __LINE__); - else { - Py_INCREF(self->Socket); - return (PyObject *) (self->Socket); - } + int err, ssl_err, sockstate, nonblocking; + int zeros = 0; + + /* Guard against closed socket */ + if (self->Socket->sock_fd < 0) { + PyErr_SetString(PySSLErrorObject, + "Underlying socket has been closed."); + return NULL; + } + + /* Just in case the blocking state of the socket has been changed */ + nonblocking = (self->Socket->sock_timeout >= 0.0); + BIO_set_nbio(SSL_get_rbio(self->ssl), nonblocking); + BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); + + while (1) { + PySSL_BEGIN_ALLOW_THREADS + /* Disable read-ahead so that unwrap can work correctly. + * Otherwise OpenSSL might read in too much data, + * eating clear text data that happens to be + * transmitted after the SSL shutdown. + * Should be safe to call repeatedly everytime this + * function is used and the shutdown_seen_zero != 0 + * condition is met. + */ + if (self->shutdown_seen_zero) + SSL_set_read_ahead(self->ssl, 0); + err = SSL_shutdown(self->ssl); + PySSL_END_ALLOW_THREADS + /* If err == 1, a secure shutdown with SSL_shutdown() is complete */ + if (err > 0) + break; + if (err == 0) { + /* Don't loop endlessly; instead preserve legacy + behaviour of trying SSL_shutdown() only twice. + This looks necessary for OpenSSL < 0.9.8m */ + if (++zeros > 1) + break; + /* Shutdown was sent, now try receiving */ + self->shutdown_seen_zero = 1; + continue; + } + + /* Possibly retry shutdown until timeout or failure */ + ssl_err = SSL_get_error(self->ssl, err); + if (ssl_err == SSL_ERROR_WANT_READ) + sockstate = check_socket_and_wait_for_timeout(self->Socket, 0); + else if (ssl_err == SSL_ERROR_WANT_WRITE) + sockstate = check_socket_and_wait_for_timeout(self->Socket, 1); + else + break; + if (sockstate == SOCKET_HAS_TIMED_OUT) { + if (ssl_err == SSL_ERROR_WANT_READ) + PyErr_SetString(PySSLErrorObject, + "The read operation timed out"); + else + PyErr_SetString(PySSLErrorObject, + "The write operation timed out"); + return NULL; + } + else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) { + PyErr_SetString(PySSLErrorObject, + "Underlying socket too large for select()."); + return NULL; + } + else if (sockstate != SOCKET_OPERATION_OK) + /* Retain the SSL error code */ + break; + } + + if (err < 0) + return PySSL_SetError(self, err, __FILE__, __LINE__); + else { + Py_INCREF(self->Socket); + return (PyObject *) (self->Socket); + } } PyDoc_STRVAR(PySSL_SSLshutdown_doc, @@ -1448,44 +1448,44 @@ Does the SSL shutdown handshake with the remote end, and returns\n\ the underlying socket object."); static PyMethodDef PySSLMethods[] = { - {"do_handshake", (PyCFunction)PySSL_SSLdo_handshake, METH_NOARGS}, - {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, - PySSL_SSLwrite_doc}, - {"read", (PyCFunction)PySSL_SSLread, METH_VARARGS, - PySSL_SSLread_doc}, - {"pending", (PyCFunction)PySSL_SSLpending, METH_NOARGS, - PySSL_SSLpending_doc}, - {"server", (PyCFunction)PySSL_server, METH_NOARGS}, - {"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS}, - {"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS, - PySSL_peercert_doc}, - {"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS}, - {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS, - PySSL_SSLshutdown_doc}, - {NULL, NULL} + {"do_handshake", (PyCFunction)PySSL_SSLdo_handshake, METH_NOARGS}, + {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, + PySSL_SSLwrite_doc}, + {"read", (PyCFunction)PySSL_SSLread, METH_VARARGS, + PySSL_SSLread_doc}, + {"pending", (PyCFunction)PySSL_SSLpending, METH_NOARGS, + PySSL_SSLpending_doc}, + {"server", (PyCFunction)PySSL_server, METH_NOARGS}, + {"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS}, + {"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS, + PySSL_peercert_doc}, + {"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS}, + {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS, + PySSL_SSLshutdown_doc}, + {NULL, NULL} }; static PyObject *PySSL_getattr(PySSLObject *self, char *name) { - return Py_FindMethod(PySSLMethods, (PyObject *)self, name); + return Py_FindMethod(PySSLMethods, (PyObject *)self, name); } static PyTypeObject PySSL_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "ssl.SSLContext", /*tp_name*/ - sizeof(PySSLObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PySSL_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)PySSL_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ + PyVarObject_HEAD_INIT(NULL, 0) + "ssl.SSLContext", /*tp_name*/ + sizeof(PySSLObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)PySSL_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + (getattrfunc)PySSL_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ }; #ifdef HAVE_OPENSSL_RAND @@ -1499,7 +1499,7 @@ PySSL_RAND_add(PyObject *self, PyObject *args) double entropy; if (!PyArg_ParseTuple(args, "s#d:RAND_add", &buf, &len, &entropy)) - return NULL; + return NULL; RAND_add(buf, len, entropy); Py_INCREF(Py_None); return Py_None; @@ -1530,15 +1530,15 @@ PySSL_RAND_egd(PyObject *self, PyObject *arg) int bytes; if (!PyString_Check(arg)) - return PyErr_Format(PyExc_TypeError, - "RAND_egd() expected string, found %s", - Py_TYPE(arg)->tp_name); + return PyErr_Format(PyExc_TypeError, + "RAND_egd() expected string, found %s", + Py_TYPE(arg)->tp_name); bytes = RAND_egd(PyString_AS_STRING(arg)); if (bytes == -1) { - PyErr_SetString(PySSLErrorObject, - "EGD connection failed or EGD did not return " - "enough data to seed the PRNG"); - return NULL; + PyErr_SetString(PySSLErrorObject, + "EGD connection failed or EGD did not return " + "enough data to seed the PRNG"); + return NULL; } return PyInt_FromLong(bytes); } @@ -1555,19 +1555,19 @@ fails or if it does provide enough data to seed PRNG."); /* List of functions exported by this module. */ static PyMethodDef PySSL_methods[] = { - {"sslwrap", PySSL_sslwrap, - METH_VARARGS, ssl_doc}, - {"_test_decode_cert", PySSL_test_decode_certificate, - METH_VARARGS}, + {"sslwrap", PySSL_sslwrap, + METH_VARARGS, ssl_doc}, + {"_test_decode_cert", PySSL_test_decode_certificate, + METH_VARARGS}, #ifdef HAVE_OPENSSL_RAND - {"RAND_add", PySSL_RAND_add, METH_VARARGS, - PySSL_RAND_add_doc}, - {"RAND_egd", PySSL_RAND_egd, METH_O, - PySSL_RAND_egd_doc}, - {"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS, - PySSL_RAND_status_doc}, + {"RAND_add", PySSL_RAND_add, METH_VARARGS, + PySSL_RAND_add_doc}, + {"RAND_egd", PySSL_RAND_egd, METH_O, + PySSL_RAND_egd_doc}, + {"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS, + PySSL_RAND_status_doc}, #endif - {NULL, NULL} /* Sentinel */ + {NULL, NULL} /* Sentinel */ }; @@ -1579,64 +1579,64 @@ static PyMethodDef PySSL_methods[] = { static PyThread_type_lock *_ssl_locks = NULL; static unsigned long _ssl_thread_id_function (void) { - return PyThread_get_thread_ident(); + return PyThread_get_thread_ident(); } static void _ssl_thread_locking_function (int mode, int n, const char *file, int line) { - /* this function is needed to perform locking on shared data - structures. (Note that OpenSSL uses a number of global data - structures that will be implicitly shared whenever multiple threads - use OpenSSL.) Multi-threaded applications will crash at random if - it is not set. - - locking_function() must be able to handle up to CRYPTO_num_locks() - different mutex locks. It sets the n-th lock if mode & CRYPTO_LOCK, and - releases it otherwise. - - file and line are the file number of the function setting the - lock. They can be useful for debugging. - */ - - if ((_ssl_locks == NULL) || - (n < 0) || ((unsigned)n >= _ssl_locks_count)) - return; - - if (mode & CRYPTO_LOCK) { - PyThread_acquire_lock(_ssl_locks[n], 1); - } else { - PyThread_release_lock(_ssl_locks[n]); - } + /* this function is needed to perform locking on shared data + structures. (Note that OpenSSL uses a number of global data + structures that will be implicitly shared whenever multiple threads + use OpenSSL.) Multi-threaded applications will crash at random if + it is not set. + + locking_function() must be able to handle up to CRYPTO_num_locks() + different mutex locks. It sets the n-th lock if mode & CRYPTO_LOCK, and + releases it otherwise. + + file and line are the file number of the function setting the + lock. They can be useful for debugging. + */ + + if ((_ssl_locks == NULL) || + (n < 0) || ((unsigned)n >= _ssl_locks_count)) + return; + + if (mode & CRYPTO_LOCK) { + PyThread_acquire_lock(_ssl_locks[n], 1); + } else { + PyThread_release_lock(_ssl_locks[n]); + } } static int _setup_ssl_threads(void) { - unsigned int i; - - if (_ssl_locks == NULL) { - _ssl_locks_count = CRYPTO_num_locks(); - _ssl_locks = (PyThread_type_lock *) - malloc(sizeof(PyThread_type_lock) * _ssl_locks_count); - if (_ssl_locks == NULL) - return 0; - memset(_ssl_locks, 0, sizeof(PyThread_type_lock) * _ssl_locks_count); - for (i = 0; i < _ssl_locks_count; i++) { - _ssl_locks[i] = PyThread_allocate_lock(); - if (_ssl_locks[i] == NULL) { - unsigned int j; - for (j = 0; j < i; j++) { - PyThread_free_lock(_ssl_locks[j]); - } - free(_ssl_locks); - return 0; - } - } - CRYPTO_set_locking_callback(_ssl_thread_locking_function); - CRYPTO_set_id_callback(_ssl_thread_id_function); - } - return 1; + unsigned int i; + + if (_ssl_locks == NULL) { + _ssl_locks_count = CRYPTO_num_locks(); + _ssl_locks = (PyThread_type_lock *) + malloc(sizeof(PyThread_type_lock) * _ssl_locks_count); + if (_ssl_locks == NULL) + return 0; + memset(_ssl_locks, 0, sizeof(PyThread_type_lock) * _ssl_locks_count); + for (i = 0; i < _ssl_locks_count; i++) { + _ssl_locks[i] = PyThread_allocate_lock(); + if (_ssl_locks[i] == NULL) { + unsigned int j; + for (j = 0; j < i; j++) { + PyThread_free_lock(_ssl_locks[j]); + } + free(_ssl_locks); + return 0; + } + } + CRYPTO_set_locking_callback(_ssl_thread_locking_function); + CRYPTO_set_id_callback(_ssl_thread_id_function); + } + return 1; } -#endif /* def HAVE_THREAD */ +#endif /* def HAVE_THREAD */ PyDoc_STRVAR(module_doc, "Implementation module for SSL socket operations. See the socket module\n\ @@ -1645,103 +1645,103 @@ for documentation."); PyMODINIT_FUNC init_ssl(void) { - PyObject *m, *d, *r; - unsigned long libver; - unsigned int major, minor, fix, patch, status; + PyObject *m, *d, *r; + unsigned long libver; + unsigned int major, minor, fix, patch, status; - Py_TYPE(&PySSL_Type) = &PyType_Type; + Py_TYPE(&PySSL_Type) = &PyType_Type; - m = Py_InitModule3("_ssl", PySSL_methods, module_doc); - if (m == NULL) - return; - d = PyModule_GetDict(m); + m = Py_InitModule3("_ssl", PySSL_methods, module_doc); + if (m == NULL) + return; + d = PyModule_GetDict(m); - /* Load _socket module and its C API */ - if (PySocketModule_ImportModuleAndAPI()) - return; + /* Load _socket module and its C API */ + if (PySocketModule_ImportModuleAndAPI()) + return; - /* Init OpenSSL */ - SSL_load_error_strings(); - SSL_library_init(); + /* Init OpenSSL */ + SSL_load_error_strings(); + SSL_library_init(); #ifdef WITH_THREAD - /* note that this will start threading if not already started */ - if (!_setup_ssl_threads()) { - return; - } + /* note that this will start threading if not already started */ + if (!_setup_ssl_threads()) { + return; + } #endif - OpenSSL_add_all_algorithms(); - - /* Add symbols to module dict */ - PySSLErrorObject = PyErr_NewException("ssl.SSLError", - PySocketModule.error, - NULL); - if (PySSLErrorObject == NULL) - return; - if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0) - return; - if (PyDict_SetItemString(d, "SSLType", - (PyObject *)&PySSL_Type) != 0) - return; - PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", - PY_SSL_ERROR_ZERO_RETURN); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ", - PY_SSL_ERROR_WANT_READ); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE", - PY_SSL_ERROR_WANT_WRITE); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP", - PY_SSL_ERROR_WANT_X509_LOOKUP); - PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL", - PY_SSL_ERROR_SYSCALL); - PyModule_AddIntConstant(m, "SSL_ERROR_SSL", - PY_SSL_ERROR_SSL); - PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT", - PY_SSL_ERROR_WANT_CONNECT); - /* non ssl.h errorcodes */ - PyModule_AddIntConstant(m, "SSL_ERROR_EOF", - PY_SSL_ERROR_EOF); - PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE", - PY_SSL_ERROR_INVALID_ERROR_CODE); - /* cert requirements */ - PyModule_AddIntConstant(m, "CERT_NONE", - PY_SSL_CERT_NONE); - PyModule_AddIntConstant(m, "CERT_OPTIONAL", - PY_SSL_CERT_OPTIONAL); - PyModule_AddIntConstant(m, "CERT_REQUIRED", - PY_SSL_CERT_REQUIRED); - - /* protocol versions */ - PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", - PY_SSL_VERSION_SSL2); - PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", - PY_SSL_VERSION_SSL3); - PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", - PY_SSL_VERSION_SSL23); - PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", - PY_SSL_VERSION_TLS1); - - /* OpenSSL version */ - /* SSLeay() gives us the version of the library linked against, - which could be different from the headers version. - */ - libver = SSLeay(); - r = PyLong_FromUnsignedLong(libver); - if (r == NULL) - return; - if (PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r)) - return; - status = libver & 0xF; - libver >>= 4; - patch = libver & 0xFF; - libver >>= 8; - fix = libver & 0xFF; - libver >>= 8; - minor = libver & 0xFF; - libver >>= 8; - major = libver & 0xFF; - r = Py_BuildValue("IIIII", major, minor, fix, patch, status); - if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r)) - return; - r = PyString_FromString(SSLeay_version(SSLEAY_VERSION)); - if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r)) - return; + OpenSSL_add_all_algorithms(); + + /* Add symbols to module dict */ + PySSLErrorObject = PyErr_NewException("ssl.SSLError", + PySocketModule.error, + NULL); + if (PySSLErrorObject == NULL) + return; + if (PyDict_SetItemString(d, "SSLError", PySSLErrorObject) != 0) + return; + if (PyDict_SetItemString(d, "SSLType", + (PyObject *)&PySSL_Type) != 0) + return; + PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", + PY_SSL_ERROR_ZERO_RETURN); + PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ", + PY_SSL_ERROR_WANT_READ); + PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE", + PY_SSL_ERROR_WANT_WRITE); + PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP", + PY_SSL_ERROR_WANT_X509_LOOKUP); + PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL", + PY_SSL_ERROR_SYSCALL); + PyModule_AddIntConstant(m, "SSL_ERROR_SSL", + PY_SSL_ERROR_SSL); + PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT", + PY_SSL_ERROR_WANT_CONNECT); + /* non ssl.h errorcodes */ + PyModule_AddIntConstant(m, "SSL_ERROR_EOF", + PY_SSL_ERROR_EOF); + PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE", + PY_SSL_ERROR_INVALID_ERROR_CODE); + /* cert requirements */ + PyModule_AddIntConstant(m, "CERT_NONE", + PY_SSL_CERT_NONE); + PyModule_AddIntConstant(m, "CERT_OPTIONAL", + PY_SSL_CERT_OPTIONAL); + PyModule_AddIntConstant(m, "CERT_REQUIRED", + PY_SSL_CERT_REQUIRED); + + /* protocol versions */ + PyModule_AddIntConstant(m, "PROTOCOL_SSLv2", + PY_SSL_VERSION_SSL2); + PyModule_AddIntConstant(m, "PROTOCOL_SSLv3", + PY_SSL_VERSION_SSL3); + PyModule_AddIntConstant(m, "PROTOCOL_SSLv23", + PY_SSL_VERSION_SSL23); + PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", + PY_SSL_VERSION_TLS1); + + /* OpenSSL version */ + /* SSLeay() gives us the version of the library linked against, + which could be different from the headers version. + */ + libver = SSLeay(); + r = PyLong_FromUnsignedLong(libver); + if (r == NULL) + return; + if (PyModule_AddObject(m, "OPENSSL_VERSION_NUMBER", r)) + return; + status = libver & 0xF; + libver >>= 4; + patch = libver & 0xFF; + libver >>= 8; + fix = libver & 0xFF; + libver >>= 8; + minor = libver & 0xFF; + libver >>= 8; + major = libver & 0xFF; + r = Py_BuildValue("IIIII", major, minor, fix, patch, status); + if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION_INFO", r)) + return; + r = PyString_FromString(SSLeay_version(SSLEAY_VERSION)); + if (r == NULL || PyModule_AddObject(m, "OPENSSL_VERSION", r)) + return; } |