summaryrefslogtreecommitdiffstats
path: root/Modules/_ssl.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2007-08-27 18:42:23 (GMT)
committerGuido van Rossum <guido@python.org>2007-08-27 18:42:23 (GMT)
commit780b80dc086809f0fa6ccc2508f5ede585151625 (patch)
treec222c2a59bc883b202230612c6bebc5161068355 /Modules/_ssl.c
parentba8c5653cc9d2777f8becacad122801a388d6cff (diff)
downloadcpython-780b80dc086809f0fa6ccc2508f5ede585151625.zip
cpython-780b80dc086809f0fa6ccc2508f5ede585151625.tar.gz
cpython-780b80dc086809f0fa6ccc2508f5ede585151625.tar.bz2
> Some of the code sets the error string in this directly before
> returning NULL, and other pieces of the code call PySSL_SetError, > which creates the error string. I think some of the places which set > the string directly probably shouldn't; instead, they should call > PySSL_SetError to cons up the error name directly from the err code. > However, PySSL_SetError only works after the construction of an ssl > object, which means it can't be used there... I'll take a longer look > at it and see if there's a reasonable fix. Here's a patch which addresses this. It also fixes the indentation in PySSL_SetError, bringing it into line with PEP 7, fixes a compile warning about one of the OpenSSL macros, and makes the namespace a bit more consistent. I've tested it on FC 7 and OS X 10.4. % ./python ./Lib/test/regrtest.py -R :1: -u all test_ssl test_ssl beginning 6 repetitions 123456 ...... 1 test OK. [29244 refs] % [GvR: slightly edited to enforce 79-char line length, even if it required violating the style guide.]
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r--Modules/_ssl.c198
1 files changed, 110 insertions, 88 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 4d6c38c..a1c2380 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -122,71 +122,77 @@ PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno)
char buf[2048];
char *errstr;
int err;
- enum py_ssl_error p;
+ enum py_ssl_error p = PY_SSL_ERROR_NONE;
assert(ret <= 0);
- 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) {
- /* the underlying BIO reported an I/O error */
- return obj->Socket->errorhandler();
- } else { /* possible? */
+ if ((obj != NULL) && (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;
- errstr = "Some I/O error occurred";
+ /* XXX Protected by global interpreter lock */
+ errstr = ERR_error_string(e, NULL);
}
- } else {
- p = PY_SSL_ERROR_SYSCALL;
- /* XXX Protected by global interpreter lock */
- errstr = ERR_error_string(e, NULL);
+ break;
}
- 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";
+ 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;
}
- break;
- }
- default:
- p = PY_SSL_ERROR_INVALID_ERROR_CODE;
- errstr = "Invalid error code";
+ 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) {
@@ -221,13 +227,15 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file,
self->Socket = NULL;
if ((key_file && !cert_file) || (!key_file && cert_file)) {
- errstr = ERRSTR("Both the key & certificate files must be specified");
+ 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");
+ errstr = ERRSTR("Both the key & certificate files "
+ "must be specified for server-side operation");
goto fail;
}
@@ -249,15 +257,17 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file,
if (certreq != PY_SSL_CERT_NONE) {
if (cacerts_file == NULL) {
- errstr = ERRSTR("No root certificates specified for verification of other-side certificates.");
+ errstr = ERRSTR("No root certificates specified for "
+ "verification of other-side certificates.");
goto fail;
} else {
Py_BEGIN_ALLOW_THREADS
ret = SSL_CTX_load_verify_locations(self->ctx,
- cacerts_file, NULL);
+ cacerts_file,
+ NULL);
Py_END_ALLOW_THREADS
- if (ret < 1) {
- errstr = ERRSTR("SSL_CTX_load_verify_locations");
+ if (ret != 1) {
+ PySSL_SetError(NULL, 0, __FILE__, __LINE__);
goto fail;
}
}
@@ -267,8 +277,8 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file,
ret = SSL_CTX_use_PrivateKey_file(self->ctx, key_file,
SSL_FILETYPE_PEM);
Py_END_ALLOW_THREADS
- if (ret < 1) {
- errstr = ERRSTR("SSL_CTX_use_PrivateKey_file error");
+ if (ret != 1) {
+ PySSL_SetError(NULL, 0, __FILE__, __LINE__);
goto fail;
}
@@ -276,11 +286,12 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file,
ret = SSL_CTX_use_certificate_chain_file(self->ctx,
cert_file);
Py_END_ALLOW_THREADS
- if (ret < 1) {
- errstr = ERRSTR("SSL_CTX_use_certificate_chain_file error") ;
+ if (ret != 1) {
+ PySSL_SetError(NULL, 0, __FILE__, __LINE__);
goto fail;
}
- SSL_CTX_set_options(self->ctx, SSL_OP_ALL); /* ssl compatibility */
+ /* ssl compatibility */
+ SSL_CTX_set_options(self->ctx, SSL_OP_ALL);
}
verification_mode = SSL_VERIFY_NONE;
@@ -375,7 +386,7 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file,
}
static PyObject *
-PySocket_ssl(PyObject *self, PyObject *args)
+PySSL_sslwrap(PyObject *self, PyObject *args)
{
PySocketSockObject *Sock;
int server_side = 0;
@@ -431,6 +442,9 @@ _create_dict_for_X509_NAME (X509_NAME *xname)
PyObject *pd = PyDict_New();
int index_counter;
+ if (pd == NULL)
+ return NULL;
+
for (index_counter = 0;
index_counter < X509_NAME_entry_count(xname);
index_counter++)
@@ -520,7 +534,7 @@ PySSL_peercert(PySSLObject *self)
X509_get_issuer_name(self->peer_cert));
if (issuer == NULL)
goto fail0;
- if (PyDict_SetItemString(retval, (const char *) "issuer", issuer) < 0) {
+ if (PyDict_SetItemString(retval, (const char *)"issuer", issuer) < 0) {
Py_DECREF(issuer);
goto fail0;
}
@@ -548,7 +562,7 @@ PySSL_peercert(PySSLObject *self)
}
Py_DECREF(pnotBefore);
- BIO_reset(biobuf);
+ (void) BIO_reset(biobuf);
notAfter = X509_get_notAfter(self->peer_cert);
ASN1_TIME_print(biobuf, notAfter);
len = BIO_gets(biobuf, buf, sizeof(buf)-1);
@@ -664,13 +678,16 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
sockstate = check_socket_and_wait_for_timeout(self->Socket, 1);
if (sockstate == SOCKET_HAS_TIMED_OUT) {
- PyErr_SetString(PySSLErrorObject, "The write operation timed out");
+ PyErr_SetString(PySSLErrorObject,
+ "The write operation timed out");
return NULL;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
- PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed.");
+ PyErr_SetString(PySSLErrorObject,
+ "Underlying socket has been closed.");
return NULL;
} else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
- PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
+ PyErr_SetString(PySSLErrorObject,
+ "Underlying socket too large for select().");
return NULL;
}
do {
@@ -683,17 +700,21 @@ static PyObject *PySSL_SSLwrite(PySSLObject *self, PyObject *args)
return NULL;
}
if (err == SSL_ERROR_WANT_READ) {
- sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
+ 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);
+ 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");
+ PyErr_SetString(PySSLErrorObject,
+ "The write operation timed out");
return NULL;
} else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
- PyErr_SetString(PySSLErrorObject, "Underlying socket has been closed.");
+ PyErr_SetString(PySSLErrorObject,
+ "Underlying socket has been closed.");
return NULL;
} else if (sockstate == SOCKET_IS_NONBLOCKING) {
break;
@@ -746,9 +767,9 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
if (SSL_get_shutdown(self->ssl) !=
SSL_RECEIVED_SHUTDOWN)
{
- Py_DECREF(buf);
- PyErr_SetString(PySSLErrorObject,
- "Socket closed without SSL shutdown handshake");
+ Py_DECREF(buf);
+ PyErr_SetString(PySSLErrorObject,
+ "Socket closed without SSL shutdown handshake");
return NULL;
} else {
/* should contain a zero-length string */
@@ -768,14 +789,14 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
return NULL;
}
if (err == SSL_ERROR_WANT_READ) {
- sockstate =
+ 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))
+ SSL_RECEIVED_SHUTDOWN))
{
_PyString_Resize(&buf, 0);
return buf;
@@ -846,7 +867,8 @@ static PyMethodDef PySSLMethods[] = {
{"server", (PyCFunction)PySSL_server, METH_NOARGS},
{"issuer", (PyCFunction)PySSL_issuer, METH_NOARGS},
{"peer_certificate", (PyCFunction)PySSL_peercert, METH_NOARGS},
- {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS, PySSL_SSLshutdown_doc},
+ {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS,
+ PySSL_SSLshutdown_doc},
{NULL, NULL}
};
@@ -857,7 +879,7 @@ static PyObject *PySSL_getattr(PySSLObject *self, char *name)
static PyTypeObject PySSL_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
- "socket.SSL", /*tp_name*/
+ "ssl.SSLContext", /*tp_name*/
sizeof(PySSLObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
@@ -932,7 +954,7 @@ PyDoc_STRVAR(PySSL_RAND_egd_doc,
"RAND_egd(path) -> bytes\n\
\n\
Queries the entropy gather daemon (EGD) on socket path. Returns number\n\
-of bytes read. Raises socket.sslerror if connection to EGD fails or\n\
+of bytes read. Raises ssl.sslerror if connection to EGD fails or\n\
if it does provide enough data to seed PRNG.");
#endif
@@ -940,7 +962,7 @@ if it does provide enough data to seed PRNG.");
/* List of functions exported by this module. */
static PyMethodDef PySSL_methods[] = {
- {"sslwrap", PySocket_ssl,
+ {"sslwrap", PySSL_sslwrap,
METH_VARARGS, ssl_doc},
#ifdef HAVE_OPENSSL_RAND
{"RAND_add", PySSL_RAND_add, METH_VARARGS,
@@ -979,7 +1001,7 @@ init_ssl(void)
SSLeay_add_ssl_algorithms();
/* Add symbols to module dict */
- PySSLErrorObject = PyErr_NewException("socket.sslerror",
+ PySSLErrorObject = PyErr_NewException("ssl.sslerror",
PySocketModule.error,
NULL);
if (PySSLErrorObject == NULL)