diff --git a/pyOpenSSL-threadsafe.patch b/pyOpenSSL-threadsafe.patch new file mode 100644 index 0000000..81ddda1 --- /dev/null +++ b/pyOpenSSL-threadsafe.patch @@ -0,0 +1,256 @@ +--- pyOpenSSL-0.6/src/ssl/context.c.threadsafe 2004-08-06 06:24:38.000000000 -0400 ++++ pyOpenSSL-0.6/src/ssl/context.c 2005-07-12 22:30:02.000000000 -0400 +@@ -53,39 +53,33 @@ + static int + global_passphrase_callback(char *buf, int maxlen, int verify, void *arg) + { +- int len; ++ int len = 0; + char *str; + PyObject *argv, *ret = NULL; + ssl_ContextObj *ctx = (ssl_ContextObj *)arg; + ++ if (!ctx->tstate) ++ fprintf (stderr, "ERROR: ctx->tstate == NULL!\n"); ++ MY_END_ALLOW_THREADS(ctx->tstate); ++ + /* The Python callback is called with a (maxlen,verify,userdata) tuple */ + argv = Py_BuildValue("(iiO)", maxlen, verify, ctx->passphrase_userdata); +- if (ctx->tstate != NULL) +- { +- /* We need to get back our thread state before calling the callback */ +- MY_END_ALLOW_THREADS(ctx->tstate); +- ret = PyEval_CallObject(ctx->passphrase_callback, argv); +- MY_BEGIN_ALLOW_THREADS(ctx->tstate); +- } +- else +- { +- ret = PyEval_CallObject(ctx->passphrase_callback, argv); +- } ++ ret = PyEval_CallObject(ctx->passphrase_callback, argv); + Py_DECREF(argv); + + if (ret == NULL) +- return 0; ++ goto out; + + if (!PyObject_IsTrue(ret)) + { + Py_DECREF(ret); +- return 0; ++ goto out; + } + + if (!PyString_Check(ret)) + { + Py_DECREF(ret); +- return 0; ++ goto out; + } + + len = PyString_Size(ret); +@@ -96,6 +90,8 @@ + strncpy(buf, str, len); + Py_XDECREF(ret); + ++out: ++ MY_BEGIN_ALLOW_THREADS(ctx->tstate); + return len; + } + +@@ -115,43 +111,39 @@ + SSL *ssl; + ssl_ConnectionObj *conn; + crypto_X509Obj *cert; +- int errnum, errdepth, c_ret; ++ int errnum, errdepth, c_ret = 0; + +- cert = crypto_X509_New(X509_STORE_CTX_get_current_cert(x509_ctx), 0); + errnum = X509_STORE_CTX_get_error(x509_ctx); + errdepth = X509_STORE_CTX_get_error_depth(x509_ctx); + ssl = (SSL *)X509_STORE_CTX_get_app_data(x509_ctx); + conn = (ssl_ConnectionObj *)SSL_get_app_data(ssl); + ++ if (!conn->tstate) ++ fprintf (stderr, "ERROR: ctx->tstate == NULL!\n"); ++ MY_END_ALLOW_THREADS(conn->tstate); ++ ++ cert = crypto_X509_New(X509_STORE_CTX_get_current_cert(x509_ctx), 0); ++ + argv = Py_BuildValue("(OOiii)", (PyObject *)conn, (PyObject *)cert, + errnum, errdepth, ok); + Py_DECREF(cert); +- if (conn->tstate != NULL) +- { +- /* We need to get back our thread state before calling the callback */ +- MY_END_ALLOW_THREADS(conn->tstate); +- ret = PyEval_CallObject(conn->context->verify_callback, argv); +- MY_BEGIN_ALLOW_THREADS(conn->tstate); +- } +- else +- { +- ret = PyEval_CallObject(conn->context->verify_callback, argv); +- } ++ ret = PyEval_CallObject(conn->context->verify_callback, argv); + Py_DECREF(argv); + +- if (ret == NULL) +- return 0; +- +- if (PyObject_IsTrue(ret)) ++ if (ret != NULL) + { +- X509_STORE_CTX_set_error(x509_ctx, X509_V_OK); +- c_ret = 1; +- } +- else +- c_ret = 0; ++ if (PyObject_IsTrue(ret)) ++ { ++ X509_STORE_CTX_set_error(x509_ctx, X509_V_OK); ++ c_ret = 1; ++ } ++ else ++ c_ret = 0; + +- Py_DECREF(ret); ++ Py_DECREF(ret); ++ } + ++ MY_BEGIN_ALLOW_THREADS(conn->tstate); + return c_ret; + } + +@@ -169,28 +161,19 @@ + ssl_ConnectionObj *conn = (ssl_ConnectionObj *)SSL_get_app_data(ssl); + PyObject *argv, *ret; + ++ if (!conn->tstate) ++ fprintf (stderr, "ERROR: ctx->tstate == NULL!\n"); ++ MY_END_ALLOW_THREADS(conn->tstate); ++ + argv = Py_BuildValue("(Oii)", (PyObject *)conn, where, _ret); +- if (conn->tstate != NULL) +- { +- /* We need to get back our thread state before calling the callback */ +- MY_END_ALLOW_THREADS(conn->tstate); +- ret = PyEval_CallObject(conn->context->info_callback, argv); +- if (ret == NULL) +- PyErr_Clear(); +- else +- Py_DECREF(ret); +- MY_BEGIN_ALLOW_THREADS(conn->tstate); +- } ++ ret = PyEval_CallObject(conn->context->info_callback, argv); ++ if (ret == NULL) ++ PyErr_Clear(); + else +- { +- ret = PyEval_CallObject(conn->context->info_callback, argv); +- if (ret == NULL) +- PyErr_Clear(); +- else +- Py_DECREF(ret); +- } ++ Py_DECREF(ret); + Py_DECREF(argv); + ++ MY_BEGIN_ALLOW_THREADS(conn->tstate); + return; + } + +@@ -393,6 +376,8 @@ + if (!PyArg_ParseTuple(args, "s|i:use_privatekey_file", &keyfile, &filetype)) + return NULL; + ++ if (self->tstate) ++ fprintf (stderr, "ERROR: ctx->tstate != NULL!\n"); + MY_BEGIN_ALLOW_THREADS(self->tstate); + ret = SSL_CTX_use_PrivateKey_file(self->ctx, keyfile, filetype); + MY_END_ALLOW_THREADS(self->tstate); +--- pyOpenSSL-0.6/src/crypto/crypto.c.threadsafe 2004-08-09 10:56:05.000000000 -0400 ++++ pyOpenSSL-0.6/src/crypto/crypto.c 2005-07-12 22:29:32.000000000 -0400 +@@ -668,6 +668,72 @@ + { NULL, NULL } + }; + ++ ++#ifdef WITH_THREAD ++ ++#define MUTEX_TYPE pthread_mutex_t ++#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL) ++#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x)) ++#define MUTEX_LOCK(x) pthread_mutex_lock(&(x)) ++#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x)) ++#define THREAD_ID pthread_self() ++ ++void handle_error(const char *file, int lineno, const char *msg) ++{ ++ fprintf(stderr, "** %s:%i %s\n", file, lineno, msg); ++ ERR_print_errors_fp(stderr); ++} ++ ++ ++/* This array will store all of the mutexes available to OpenSSL. */ ++static MUTEX_TYPE *mutex_buf = NULL; ++ ++ ++static void locking_function(int mode, int n, const char * file, int line) ++{ ++ if (mode & CRYPTO_LOCK) ++ MUTEX_LOCK(mutex_buf[n]); ++ else ++ MUTEX_UNLOCK(mutex_buf[n]); ++} ++ ++static unsigned long id_function(void) ++{ ++ return ((unsigned long)THREAD_ID); ++} ++ ++int init_openssl_threads(void) ++{ ++ int i; ++ ++ mutex_buf = (MUTEX_TYPE *)malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE)); ++ if (!mutex_buf) ++ return 0; ++ for (i = 0; i < CRYPTO_num_locks(); i++) ++ MUTEX_SETUP(mutex_buf[i]); ++ CRYPTO_set_id_callback(id_function); ++ CRYPTO_set_locking_callback(locking_function); ++ return 1; ++} ++ ++int deinit_openssl_threads(void) ++{ ++ int i; ++ ++ if (!mutex_buf) ++ return 0; ++ CRYPTO_set_id_callback(NULL); ++ CRYPTO_set_locking_callback(NULL); ++ for (i = 0; i < CRYPTO_num_locks(); i++) ++ MUTEX_CLEANUP(mutex_buf[i]); ++ free(mutex_buf); ++ mutex_buf = NULL; ++ return 1; ++} ++ ++#endif ++ ++ + /* + * Initialize crypto sub module + * +@@ -713,6 +779,10 @@ + PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA); + + dict = PyModule_GetDict(module); ++#ifdef WITH_THREAD ++ if (!init_openssl_threads()) ++ goto error; ++#endif + if (!init_crypto_x509(dict)) + goto error; + if (!init_crypto_x509name(dict))