Forward port of patch # 500311: Work around for buggy https servers.

Fixes #494762.
This commit is contained in:
Martin v. Löwis 2002-04-20 07:47:40 +00:00
parent 954aed8c8d
commit 6af3e2dc31
3 changed files with 92 additions and 42 deletions

View file

@ -633,7 +633,8 @@ class FakeSocket:
if (err[0] == socket.SSL_ERROR_WANT_READ if (err[0] == socket.SSL_ERROR_WANT_READ
or err[0] == socket.SSL_ERROR_WANT_WRITE): or err[0] == socket.SSL_ERROR_WANT_WRITE):
continue continue
if err[0] == socket.SSL_ERROR_ZERO_RETURN: if (err[0] == socket.SSL_ERROR_ZERO_RETURN
or err[0] == socket.SSL_ERROR_EOF):
break break
raise raise
except socket.error, err: except socket.error, err:

View file

@ -38,6 +38,7 @@ Reimer Behrends
Thomas Bellman Thomas Bellman
Juan M. Bello Rivas Juan M. Bello Rivas
Andy Bensky Andy Bensky
Michel Van den Bergh
Eric Beser Eric Beser
Stephen Bevan Stephen Bevan
Ron Bickers Ron Bickers

View file

@ -8,6 +8,20 @@
*/ */
#include "Python.h" #include "Python.h"
enum py_ssl_error {
/* these mirror ssl.h */
PY_SSL_ERROR_NONE,
PY_SSL_ERROR_SSL,
PY_SSL_ERROR_WANT_READ,
PY_SSL_ERROR_WANT_WRITE,
PY_SSL_ERROR_WANT_X509_LOOKUP,
PY_SSL_ERROR_SYSCALL, /* look at error stack/return value/errno */
PY_SSL_ERROR_ZERO_RETURN,
PY_SSL_ERROR_WANT_CONNECT,
/* start of non ssl.h errorcodes */
PY_SSL_ERROR_EOF, /* special case of SSL_ERROR_SYSCALL */
PY_SSL_ERROR_INVALID_ERROR_CODE
};
/* Include symbols from _socket module */ /* Include symbols from _socket module */
#include "socketmodule.h" #include "socketmodule.h"
@ -64,11 +78,71 @@ PySSL_SetError(PySSLObject *obj, int ret)
PyObject *v, *n, *s; PyObject *v, *n, *s;
char *errstr; char *errstr;
int err; int err;
enum py_ssl_error p;
assert(ret <= 0); assert(ret <= 0);
err = SSL_get_error(obj->ssl, ret); err = SSL_get_error(obj->ssl, ret);
n = PyInt_FromLong(err);
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){
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? */
p=PY_SSL_ERROR_SYSCALL;
errstr = "Some I/O error occurred";
}
} else {
p=PY_SSL_ERROR_SYSCALL;
/* XXX Protected by global interpreter lock */
errstr = ERR_error_string(e, NULL);
}
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";
}
break;
}
default:
p=PY_SSL_ERROR_INVALID_ERROR_CODE;
errstr = "Invalid error code";
}
n = PyInt_FromLong((long) p);
if (n == NULL) if (n == NULL)
return NULL; return NULL;
v = PyTuple_New(2); v = PyTuple_New(2);
@ -77,40 +151,6 @@ PySSL_SetError(PySSLObject *obj, int ret)
return NULL; return NULL;
} }
switch (SSL_get_error(obj->ssl, ret)) {
case SSL_ERROR_ZERO_RETURN:
errstr = "TLS/SSL connection has been closed";
break;
case SSL_ERROR_WANT_READ:
errstr = "The operation did not complete (read)";
break;
case SSL_ERROR_WANT_WRITE:
errstr = "The operation did not complete (write)";
break;
case SSL_ERROR_WANT_X509_LOOKUP:
errstr = "The operation did not complete (X509 lookup)";
break;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
{
unsigned long e = ERR_get_error();
if (e == 0) {
/* an EOF was observed that violates the protocol */
errstr = "EOF occurred in violation of protocol";
} else if (e == -1) {
/* the underlying BIO reported an I/O error */
Py_DECREF(v);
Py_DECREF(n);
return obj->Socket->errorhandler();
} else {
/* XXX Protected by global interpreter lock */
errstr = ERR_error_string(e, NULL);
}
break;
}
default:
errstr = "Invalid error code";
}
s = PyString_FromString(errstr); s = PyString_FromString(errstr);
if (s == NULL) { if (s == NULL) {
Py_DECREF(v); Py_DECREF(v);
@ -447,15 +487,23 @@ init_ssl(void)
(PyObject *)&PySSL_Type) != 0) (PyObject *)&PySSL_Type) != 0)
return; return;
PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN",
SSL_ERROR_ZERO_RETURN); PY_SSL_ERROR_ZERO_RETURN);
PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ", PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ",
SSL_ERROR_WANT_READ); PY_SSL_ERROR_WANT_READ);
PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE", PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE",
SSL_ERROR_WANT_WRITE); PY_SSL_ERROR_WANT_WRITE);
PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP", PyModule_AddIntConstant(m, "SSL_ERROR_WANT_X509_LOOKUP",
SSL_ERROR_WANT_X509_LOOKUP); PY_SSL_ERROR_WANT_X509_LOOKUP);
PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL", PyModule_AddIntConstant(m, "SSL_ERROR_SYSCALL",
SSL_ERROR_SYSCALL); PY_SSL_ERROR_SYSCALL);
PyModule_AddIntConstant(m, "SSL_ERROR_SSL", PyModule_AddIntConstant(m, "SSL_ERROR_SSL",
SSL_ERROR_SSL); PY_SSL_ERROR_SSL);
PyModule_AddIntConstant(m, "SSL_ERROR_WANT_CONNECT",
PY_SSL_ERROR_WANT_CONNECT);
/* non ssl.h errorcodes */
PyModule_AddIntConstant(m, "SSL_ERROR_EOF",
PY_SSL_ERROR_EOF);
PyModule_AddIntConstant(m, "SSL_ERROR_INVALID_ERROR_CODE",
PY_SSL_ERROR_INVALID_ERROR_CODE);
} }