Kaydet (Commit) 6af3e2dc authored tarafından Martin v. Löwis's avatar Martin v. Löwis

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

Fixes #494762.
üst 954aed8c
...@@ -633,7 +633,8 @@ class FakeSocket: ...@@ -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:
......
...@@ -38,6 +38,7 @@ Reimer Behrends ...@@ -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
......
...@@ -8,6 +8,20 @@ ...@@ -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,53 +78,79 @@ PySSL_SetError(PySSLObject *obj, int ret) ...@@ -64,53 +78,79 @@ 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);
if (n == NULL)
return NULL;
v = PyTuple_New(2);
if (v == NULL) {
Py_DECREF(n);
return NULL;
}
switch (SSL_get_error(obj->ssl, ret)) { switch (err) {
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
errstr = "TLS/SSL connection has been closed"; errstr = "TLS/SSL connection has been closed";
p=PY_SSL_ERROR_ZERO_RETURN;
break; break;
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
errstr = "The operation did not complete (read)"; errstr = "The operation did not complete (read)";
p=PY_SSL_ERROR_WANT_READ;
break; break;
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
p=PY_SSL_ERROR_WANT_WRITE;
errstr = "The operation did not complete (write)"; errstr = "The operation did not complete (write)";
break; break;
case SSL_ERROR_WANT_X509_LOOKUP: 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; break;
case SSL_ERROR_WANT_CONNECT:
p=PY_SSL_ERROR_WANT_CONNECT;
errstr = "The operation did not complete (connect)";
break;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
{ {
unsigned long e = ERR_get_error(); unsigned long e = ERR_get_error();
if (e == 0) { if(e==0){
/* an EOF was observed that violates the protocol */ if(ret==0){
errstr = "EOF occurred in violation of protocol"; p=PY_SSL_ERROR_EOF;
} else if (e == -1) { errstr = "EOF occurred in violation of protocol";
/* the underlying BIO reported an I/O error */ }else if(ret==-1){
Py_DECREF(v); /* the underlying BIO reported an I/O error */
Py_DECREF(n); return obj->Socket->errorhandler();
return obj->Socket->errorhandler(); }else{ /* possible? */
p=PY_SSL_ERROR_SYSCALL;
errstr = "Some I/O error occurred";
}
} else { } 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 */ /* XXX Protected by global interpreter lock */
errstr = ERR_error_string(e, NULL); errstr = ERR_error_string(e, NULL);
} else { /* possible? */
errstr="A failure in the SSL library occurred";
} }
break; break;
} }
default: default:
p=PY_SSL_ERROR_INVALID_ERROR_CODE;
errstr = "Invalid error code"; errstr = "Invalid error code";
} }
n = PyInt_FromLong((long) p);
if (n == NULL)
return NULL;
v = PyTuple_New(2);
if (v == NULL) {
Py_DECREF(n);
return NULL;
}
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) ...@@ -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);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment