summaryrefslogtreecommitdiffstats
path: root/Modules/_ssl.c
diff options
context:
space:
mode:
authorBill Janssen <janssen@parc.com>2007-11-15 22:23:56 (GMT)
committerBill Janssen <janssen@parc.com>2007-11-15 22:23:56 (GMT)
commit6e027dba9339887feeb947fa409e18a6f44e210b (patch)
treec01007b372bbcc467bd00bb97e065a2ff1ed218c /Modules/_ssl.c
parentf83088aefedd3c6ee41171ec7c0b5b354df11e63 (diff)
downloadcpython-6e027dba9339887feeb947fa409e18a6f44e210b.zip
cpython-6e027dba9339887feeb947fa409e18a6f44e210b.tar.gz
cpython-6e027dba9339887feeb947fa409e18a6f44e210b.tar.bz2
get SSL support to work again
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r--Modules/_ssl.c328
1 files changed, 198 insertions, 130 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index b680c41..64f4578 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -2,14 +2,15 @@
SSL support based on patches by Brian E Gallew and Laszlo Kovacs.
Re-worked a bit by Bill Janssen to add server-side support and
- certificate decoding.
+ certificate decoding. Chris Stawarz contributed some non-blocking
+ patches.
This module is imported by ssl.py. It should *not* be used
directly.
XXX should partial writes be enabled, SSL_MODE_ENABLE_PARTIAL_WRITE?
- XXX what about SSL_MODE_AUTO_RETRY
+ XXX what about SSL_MODE_AUTO_RETRY?
*/
#include "Python.h"
@@ -17,7 +18,7 @@
#ifdef WITH_THREAD
#include "pythread.h"
#define PySSL_BEGIN_ALLOW_THREADS { \
- PyThreadState *_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()};
@@ -114,8 +115,6 @@ typedef struct {
SSL_CTX* ctx;
SSL* ssl;
X509* peer_cert;
- char server[X509_NAME_MAXLEN];
- char issuer[X509_NAME_MAXLEN];
} PySSLObject;
@@ -265,15 +264,11 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file,
PySSLObject *self;
char *errstr = NULL;
int ret;
- int err;
- int sockstate;
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;
@@ -388,57 +383,6 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file,
SSL_set_accept_state(self->ssl);
PySSL_END_ALLOW_THREADS
- /* Actually negotiate SSL connection */
- /* XXX If SSL_connect() returns 0, it's also a failure. */
- sockstate = 0;
- do {
- PySSL_BEGIN_ALLOW_THREADS
- if (socket_type == PY_SSL_CLIENT)
- ret = SSL_connect(self->ssl);
- else
- ret = SSL_accept(self->ssl);
- err = SSL_get_error(self->ssl, ret);
- PySSL_END_ALLOW_THREADS
- if(PyErr_CheckSignals()) {
- goto fail;
- }
- if (err == SSL_ERROR_WANT_READ) {
- sockstate = check_socket_and_wait_for_timeout(Sock, 0);
- } else if (err == SSL_ERROR_WANT_WRITE) {
- sockstate = check_socket_and_wait_for_timeout(Sock, 1);
- } else {
- sockstate = SOCKET_OPERATION_OK;
- }
- if (sockstate == SOCKET_HAS_TIMED_OUT) {
- PyErr_SetString(PySSLErrorObject,
- ERRSTR("The connect operation timed out"));
- goto fail;
- } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
- PyErr_SetString(PySSLErrorObject,
- ERRSTR("Underlying socket has been closed."));
- goto fail;
- } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
- PyErr_SetString(PySSLErrorObject,
- ERRSTR("Underlying socket too large for select()."));
- goto fail;
- } else if (sockstate == SOCKET_IS_NONBLOCKING) {
- break;
- }
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
- if (ret < 1) {
- PySSL_SetError(self, ret, __FILE__, __LINE__);
- goto fail;
- }
- self->ssl->debug = 1;
-
- 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
self->Socket = Sock;
Py_INCREF(self->Socket);
return self;
@@ -488,16 +432,58 @@ PyDoc_STRVAR(ssl_doc,
/* SSL object methods */
-static PyObject *
-PySSL_server(PySSLObject *self)
+static PyObject *PySSL_SSLdo_handshake(PySSLObject *self)
{
- return PyUnicode_FromString(self->server);
-}
+ int ret;
+ int err;
+ int sockstate;
-static PyObject *
-PySSL_issuer(PySSLObject *self)
-{
- return PyUnicode_FromString(self->issuer);
+ /* Actually negotiate SSL connection */
+ /* XXX If SSL_do_handshake() returns 0, it's also a failure. */
+ sockstate = 0;
+ 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
+ self->peer_cert = SSL_get_peer_certificate(self->ssl);
+ PySSL_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return Py_None;
}
static PyObject *
@@ -515,7 +501,7 @@ _create_tuple_for_attribute (ASN1_OBJECT *name, ASN1_STRING *value) {
_setSSLError(NULL, 0, __FILE__, __LINE__);
goto fail;
}
- name_obj = PyString_FromStringAndSize(namebuf, buflen);
+ name_obj = PyUnicode_FromStringAndSize(namebuf, buflen);
if (name_obj == NULL)
goto fail;
@@ -681,21 +667,24 @@ _get_peer_alt_names (X509 *certificate) {
/* 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!"));
+ 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)));
+ 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));
+ names = (GENERAL_NAMES*)
+ (method->d2i(NULL,
+ &p,
+ ext->value->length));
for(j = 0; j < sk_GENERAL_NAME_num(names); j++) {
@@ -704,14 +693,15 @@ _get_peer_alt_names (X509 *certificate) {
name = sk_GENERAL_NAME_value(names, j);
if (name->type == GEN_DIRNAME) {
- /* we special-case DirName as a tuple of tuples of attributes */
+ /* we special-case DirName as a tuple of
+ tuples of attributes */
t = PyTuple_New(2);
if (t == NULL) {
goto fail;
}
- v = PyString_FromString("DirName");
+ v = PyUnicode_FromString("DirName");
if (v == NULL) {
Py_DECREF(t);
goto fail;
@@ -742,13 +732,14 @@ _get_peer_alt_names (X509 *certificate) {
t = PyTuple_New(2);
if (t == NULL)
goto fail;
- v = PyString_FromStringAndSize(buf, (vptr - buf));
+ v = PyUnicode_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)));
+ v = PyUnicode_FromStringAndSize((vptr + 1),
+ (len - (vptr - buf + 1)));
if (v == NULL) {
Py_DECREF(t);
goto fail;
@@ -849,7 +840,7 @@ _decode_certificate (X509 *certificate, int verbose) {
_setSSLError(NULL, 0, __FILE__, __LINE__);
goto fail1;
}
- sn_obj = PyString_FromStringAndSize(buf, len);
+ sn_obj = PyUnicode_FromStringAndSize(buf, len);
if (sn_obj == NULL)
goto fail1;
if (PyDict_SetItemString(retval, "serialNumber", sn_obj) < 0) {
@@ -866,7 +857,7 @@ _decode_certificate (X509 *certificate, int verbose) {
_setSSLError(NULL, 0, __FILE__, __LINE__);
goto fail1;
}
- pnotBefore = PyString_FromStringAndSize(buf, len);
+ pnotBefore = PyUnicode_FromStringAndSize(buf, len);
if (pnotBefore == NULL)
goto fail1;
if (PyDict_SetItemString(retval, "notBefore", pnotBefore) < 0) {
@@ -884,7 +875,7 @@ _decode_certificate (X509 *certificate, int verbose) {
_setSSLError(NULL, 0, __FILE__, __LINE__);
goto fail1;
}
- pnotAfter = PyString_FromStringAndSize(buf, len);
+ pnotAfter = PyUnicode_FromStringAndSize(buf, len);
if (pnotAfter == NULL)
goto fail1;
if (PyDict_SetItemString(retval, "notAfter", pnotAfter) < 0) {
@@ -928,22 +919,26 @@ PySSL_test_decode_certificate (PyObject *mod, PyObject *args) {
BIO *cert;
int verbose = 1;
- if (!PyArg_ParseTuple(args, "s|i:test_decode_certificate", &filename, &verbose))
+ 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");
+ 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");
+ 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");
+ PyErr_SetString(PySSLErrorObject,
+ "Error decoding PEM-encoded file");
goto fail0;
}
@@ -981,7 +976,9 @@ PySSL_peercert(PySSLObject *self, PyObject *args)
PySSL_SetError(self, len, __FILE__, __LINE__);
return NULL;
}
- retval = PyString_FromStringAndSize((const char *) bytes_buf, len);
+ /* this is actually an immutable bytes sequence */
+ retval = PyBytes_FromStringAndSize
+ ((const char *) bytes_buf, len);
OPENSSL_free(bytes_buf);
return retval;
@@ -1028,7 +1025,7 @@ static PyObject *PySSL_cipher (PySSLObject *self) {
if (cipher_name == NULL) {
PyTuple_SET_ITEM(retval, 0, Py_None);
} else {
- v = PyString_FromString(cipher_name);
+ v = PyUnicode_FromString(cipher_name);
if (v == NULL)
goto fail0;
PyTuple_SET_ITEM(retval, 0, v);
@@ -1037,7 +1034,7 @@ static PyObject *PySSL_cipher (PySSLObject *self) {
if (cipher_protocol == NULL) {
PyTuple_SET_ITEM(retval, 1, Py_None);
} else {
- v = PyString_FromString(cipher_protocol);
+ v = PyUnicode_FromString(cipher_protocol);
if (v == NULL)
goto fail0;
PyTuple_SET_ITEM(retval, 1, v);
@@ -1127,7 +1124,9 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing)
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;
@@ -1140,10 +1139,16 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
int count;
int sockstate;
int err;
+ int nonblocking;
- if (!PyArg_ParseTuple(args, "s#:write", &data, &count))
+ if (!PyArg_ParseTuple(args, "y#:write", &data, &count))
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,
@@ -1200,19 +1205,58 @@ PyDoc_STRVAR(PySSL_SSLwrite_doc,
Writes the string s into the SSL object. Returns the number\n\
of bytes written.");
-static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
+static PyObject *PySSL_SSLpending(PySSLObject *self)
{
- PyObject *buf;
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,
+"pending() -> count\n\
+\n\
+Returns the number of already decrypted bytes available for read,\n\
+pending on the connection.\n");
+
+static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
+{
+ PyObject *buf = NULL;
+ int buf_passed = 0;
+ int count = -1;
int len = 1024;
int sockstate;
int err;
+ int nonblocking;
- if (!PyArg_ParseTuple(args, "|i:read", &len))
+ if (!PyArg_ParseTuple(args, "|Oi:read", &buf, &count))
return NULL;
- if (!(buf = PyBytes_FromStringAndSize((char *) 0, len)))
- return NULL;
+ if ((buf == NULL) || (buf == Py_None)) {
+ if (!(buf = PyBytes_FromStringAndSize((char *) 0, len)))
+ return NULL;
+ } else if (PyInt_Check(buf)) {
+ len = PyInt_AS_LONG(buf);
+ if (!(buf = PyBytes_FromStringAndSize((char *) 0, len)))
+ return NULL;
+ } else {
+ if (!PyBytes_Check(buf))
+ return NULL;
+ len = PyBytes_Size(buf);
+ if ((count > 0) && (count <= len))
+ len = count;
+ buf_passed = 1;
+ }
+
+ /* 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
@@ -1224,27 +1268,38 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
"The read operation timed out");
- Py_DECREF(buf);
+ if (!buf_passed) {
+ Py_DECREF(buf);
+ }
return NULL;
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
PyErr_SetString(PySSLErrorObject,
"Underlying socket too large for select().");
+ if (!buf_passed) {
+ Py_DECREF(buf);
+ }
Py_DECREF(buf);
return NULL;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
/* should contain a zero-length string */
- _PyString_Resize(&buf, 0);
- return buf;
+ if (!buf_passed) {
+ PyBytes_Resize(buf, 0);
+ return buf;
+ } else {
+ return PyInt_FromLong(0);
+ }
}
}
do {
err = 0;
PySSL_BEGIN_ALLOW_THREADS
- count = SSL_read(self->ssl, PyBytes_AS_STRING(buf), len);
+ count = SSL_read(self->ssl, PyBytes_AsString(buf), len);
err = SSL_get_error(self->ssl, count);
PySSL_END_ALLOW_THREADS
if(PyErr_CheckSignals()) {
- Py_DECREF(buf);
+ if (!buf_passed) {
+ Py_DECREF(buf);
+ }
return NULL;
}
if (err == SSL_ERROR_WANT_READ) {
@@ -1257,44 +1312,55 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
(SSL_get_shutdown(self->ssl) ==
SSL_RECEIVED_SHUTDOWN))
{
- _PyString_Resize(&buf, 0);
- return buf;
+ if (!buf_passed) {
+ PyBytes_Resize(buf, 0);
+ return buf;
+ } else {
+ return PyInt_FromLong(0);
+ }
} else {
sockstate = SOCKET_OPERATION_OK;
}
if (sockstate == SOCKET_HAS_TIMED_OUT) {
PyErr_SetString(PySSLErrorObject,
"The read operation timed out");
- Py_DECREF(buf);
+ if (!buf_passed) {
+ 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);
+ if (!buf_passed) {
+ Py_DECREF(buf);
+ }
return PySSL_SetError(self, count, __FILE__, __LINE__);
}
- if (count != len)
- if (PyBytes_Resize(buf, count) < 0) {
- Py_DECREF(buf);
- return NULL;
- }
- return buf;
+ if (!buf_passed) {
+ if (count != len) {
+ PyBytes_Resize(buf, count);
+ }
+ return buf;
+ } else {
+ return PyInt_FromLong(count);
+ }
}
PyDoc_STRVAR(PySSL_SSLread_doc,
-"read([len]) -> bytes\n\
+"read([len]) -> string\n\
\n\
Read up to len bytes from the SSL socket.");
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},
- {"server", (PyCFunction)PySSL_server, METH_NOARGS},
- {"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS},
+ {"pending", (PyCFunction)PySSL_SSLpending, METH_NOARGS,
+ PySSL_SSLpending_doc},
{"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS,
PySSL_peercert_doc},
{"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS},
@@ -1350,26 +1416,26 @@ bound on the entropy contained in string. See RFC 1750.");
static PyObject *
PySSL_RAND_status(PyObject *self)
{
- return PyBool_FromLong(RAND_status());
+ return PyInt_FromLong(RAND_status());
}
PyDoc_STRVAR(PySSL_RAND_status_doc,
"RAND_status() -> 0 or 1\n\
\n\
-Returns True if the OpenSSL PRNG has been seeded with enough data and\n\
-False if not. It is necessary to seed the PRNG with RAND_add()\n\
-on some platforms before using the ssl() function.");
+Returns 1 if the OpenSSL PRNG has been seeded with enough data and 0 if not.\n\
+It is necessary to seed the PRNG with RAND_add() on some platforms before\n\
+using the ssl() function.");
static PyObject *
PySSL_RAND_egd(PyObject *self, PyObject *arg)
{
int bytes;
- if (!PyString_Check(arg))
+ if (!PyUnicode_Check(arg))
return PyErr_Format(PyExc_TypeError,
"RAND_egd() expected string, found %s",
Py_Type(arg)->tp_name);
- bytes = RAND_egd(PyString_AS_STRING(arg));
+ bytes = RAND_egd(PyUnicode_AsString(arg));
if (bytes == -1) {
PyErr_SetString(PySSLErrorObject,
"EGD connection failed or EGD did not return "
@@ -1418,16 +1484,17 @@ static unsigned long _ssl_thread_id_function (void) {
return PyThread_get_thread_ident();
}
-static void _ssl_thread_locking_function (int mode, int n, const char *file, int line) {
+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.
+ 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.
+ 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.
@@ -1454,7 +1521,8 @@ static int _setup_ssl_threads(void) {
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);
+ 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) {