--- 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))