From 6af3e2dc315797e799a6ad0baedd393ff65ef1db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sat, 20 Apr 2002 07:47:40 +0000 Subject: Forward port of patch # 500311: Work around for buggy https servers. Fixes #494762. --- Lib/httplib.py | 3 +- Misc/ACKS | 1 + Modules/_ssl.c | 96 +++++++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 75 insertions(+), 25 deletions(-) diff --git a/Lib/httplib.py b/Lib/httplib.py index 2faf318..9d01859 100644 --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -633,7 +633,8 @@ class FakeSocket: if (err[0] == socket.SSL_ERROR_WANT_READ or err[0] == socket.SSL_ERROR_WANT_WRITE): 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 raise except socket.error, err: diff --git a/Misc/ACKS b/Misc/ACKS index 2cafde8..12605fc 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -38,6 +38,7 @@ Reimer Behrends Thomas Bellman Juan M. Bello Rivas Andy Bensky +Michel Van den Bergh Eric Beser Stephen Bevan Ron Bickers diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 17ca3b0..f5ab2b6 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -8,6 +8,20 @@ */ #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 "socketmodule.h" @@ -64,53 +78,79 @@ PySSL_SetError(PySSLObject *obj, int ret) PyObject *v, *n, *s; char *errstr; int err; + enum py_ssl_error p; assert(ret <= 0); 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: 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: - 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(); + 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) + return NULL; + v = PyTuple_New(2); + if (v == NULL) { + Py_DECREF(n); + return NULL; + } + s = PyString_FromString(errstr); if (s == NULL) { Py_DECREF(v); @@ -447,15 +487,23 @@ init_ssl(void) (PyObject *)&PySSL_Type) != 0) return; PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", - SSL_ERROR_ZERO_RETURN); + PY_SSL_ERROR_ZERO_RETURN); PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ", - SSL_ERROR_WANT_READ); + PY_SSL_ERROR_WANT_READ); PyModule_AddIntConstant(m, "SSL_ERROR_WANT_WRITE", - SSL_ERROR_WANT_WRITE); + PY_SSL_ERROR_WANT_WRITE); 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", - SSL_ERROR_SYSCALL); + PY_SSL_ERROR_SYSCALL); 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); + } -- cgit v0.12