mirror of https://github.com/python/cpython
> 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.]
This commit is contained in:
parent
ba8c5653cc
commit
780b80dc08
|
@ -122,10 +122,11 @@ 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);
|
||||
|
||||
if ((obj != NULL) && (obj->ssl != NULL)) {
|
||||
err = SSL_get_error(obj->ssl, ret);
|
||||
|
||||
switch (err) {
|
||||
|
@ -143,7 +144,8 @@ PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno)
|
|||
break;
|
||||
case SSL_ERROR_WANT_X509_LOOKUP:
|
||||
p = PY_SSL_ERROR_WANT_X509_LOOKUP;
|
||||
errstr = "The operation did not complete (X509 lookup)";
|
||||
errstr =
|
||||
"The operation did not complete (X509 lookup)";
|
||||
break;
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
p = PY_SSL_ERROR_WANT_CONNECT;
|
||||
|
@ -155,9 +157,10 @@ PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno)
|
|||
if (e == 0) {
|
||||
if (ret == 0 || !obj->Socket) {
|
||||
p = PY_SSL_ERROR_EOF;
|
||||
errstr = "EOF occurred in violation of protocol";
|
||||
errstr =
|
||||
"EOF occurred in violation of protocol";
|
||||
} else if (ret == -1) {
|
||||
/* the underlying BIO reported an I/O error */
|
||||
/* underlying BIO reported an I/O error */
|
||||
return obj->Socket->errorhandler();
|
||||
} else { /* possible? */
|
||||
p = PY_SSL_ERROR_SYSCALL;
|
||||
|
@ -178,7 +181,8 @@ PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno)
|
|||
/* XXX Protected by global interpreter lock */
|
||||
errstr = ERR_error_string(e, NULL);
|
||||
else { /* possible? */
|
||||
errstr = "A failure in the SSL library occurred";
|
||||
errstr =
|
||||
"A failure in the SSL library occurred";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -186,7 +190,9 @@ PySSL_SetError(PySSLObject *obj, int ret, char *filename, int lineno)
|
|||
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;
|
||||
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue