Commit a4c2a5c9 authored by Antoine Pitrou's avatar Antoine Pitrou

Untabify Modules/_ssl.c

parent 91165c0b
......@@ -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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment