From 42375fb03a49611ba051783fe27db39c023cd7f3 Mon Sep 17 00:00:00 2001
From: Dima Tisnek <dimaqq@gmail.com>
Date: Wed, 4 Mar 2020 16:12:56 +0900
Subject: [PATCH 1/3] wip: raise SSLEOFError rather than OSError if peer closes
 connection during TLS negotiation

---
 Modules/_ssl.c | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index ef047126361ed5..ac8c62d342af82 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -744,8 +744,11 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
 
     assert(ret <= 0);
     e = ERR_peek_last_error();
+    fprintf(stderr, "FIXME peek last error %ld\n", e);
+    fprintf(stderr, "FIXME ret %d\n", ret);
 
     if (sslsock->ssl != NULL) {
+            fprintf(stderr, "FIXME ->ssl is null, reading ->err\n");
         err = sslsock->err;
 
         switch (err.ssl) {
@@ -789,13 +792,21 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
                     }
 #endif
                     if (err.c) {
+                            fprintf(stderr, "FIXME got err.c\n");
                         errno = err.c;
                         return PyErr_SetFromErrno(PyExc_OSError);
                     }
-                    Py_INCREF(s);
-                    s->errorhandler();
-                    Py_DECREF(s);
-                    return NULL;
+                    else {
+                            fprintf(stderr, "FIXME do not have err.c\n");
+                            p = PY_SSL_ERROR_EOF;
+                            type = PySSLEOFErrorObject;
+                            errstr = "EOF occurred in violation of protocol";
+                            
+                    }
+                    // Py_INCREF(s);
+                    // s->errorhandler();
+                    // Py_DECREF(s);
+                    //return NULL;
                 } else { /* possible? */
                     p = PY_SSL_ERROR_SYSCALL;
                     type = PySSLSyscallErrorObject;
@@ -1037,6 +1048,7 @@ static PyObject *
 _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
 /*[clinic end generated code: output=6c0898a8936548f6 input=d2d737de3df018c8]*/
 {
+        fprintf(stderr, "FIXME here\n");
     int ret;
     _PySSLError err;
     int sockstate, nonblocking;
@@ -1045,9 +1057,11 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
     int has_timeout;
 
     if (sock) {
+        fprintf(stderr, "FIXME here 33\n");
         if (((PyObject*)sock) == Py_None) {
             _setSSLError("Underlying socket connection gone",
                          PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
+        fprintf(stderr, "FIXME here 42\n");
             return NULL;
         }
         Py_INCREF(sock);
@@ -1068,7 +1082,9 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
     do {
         PySSL_BEGIN_ALLOW_THREADS
         ret = SSL_do_handshake(self->ssl);
+        fprintf(stderr, "FIXME loop iter, ret now %d\n", ret);
         err = _PySSL_errno(ret < 1, self->ssl, ret);
+        fprintf(stderr, "FIXME loop iter, err.c %d err.ssl %d\n", err.c, err.ssl);
         PySSL_END_ALLOW_THREADS
         self->err = err;
 
@@ -1079,10 +1095,13 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
             timeout = deadline - _PyTime_GetMonotonicClock();
 
         if (err.ssl == SSL_ERROR_WANT_READ) {
+        fprintf(stderr, "FIXME want read\n");
             sockstate = PySSL_select(sock, 0, timeout);
         } else if (err.ssl == SSL_ERROR_WANT_WRITE) {
+        fprintf(stderr, "FIXME want write\n");
             sockstate = PySSL_select(sock, 1, timeout);
         } else {
+        fprintf(stderr, "FIXME assume ok\n");
             sockstate = SOCKET_OPERATION_OK;
         }
 
@@ -1091,6 +1110,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
                             ERRSTR("The handshake operation timed out"));
             goto error;
         } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
+                fprintf(stderr, "FIXME -- does not happen\n");
             PyErr_SetString(PySSLErrorObject,
                             ERRSTR("Underlying socket has been closed."));
             goto error;
@@ -1103,6 +1123,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
         }
     } while (err.ssl == SSL_ERROR_WANT_READ ||
              err.ssl == SSL_ERROR_WANT_WRITE);
+    fprintf(stderr, "FIXME loop done %d\n", ret);
     Py_XDECREF(sock);
     if (ret < 1)
         return PySSL_SetError(self, ret, __FILE__, __LINE__);

From 7f33d55f602a1f4384ce76b71e209b219a9e1765 Mon Sep 17 00:00:00 2001
From: Dima Tisnek <dimaqq@gmail.com>
Date: Wed, 4 Mar 2020 16:23:35 +0900
Subject: [PATCH 2/3] cleanup

---
 Modules/_ssl.c | 26 +++-----------------------
 1 file changed, 3 insertions(+), 23 deletions(-)

diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index ac8c62d342af82..a1d4b19b303016 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -744,11 +744,8 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
 
     assert(ret <= 0);
     e = ERR_peek_last_error();
-    fprintf(stderr, "FIXME peek last error %ld\n", e);
-    fprintf(stderr, "FIXME ret %d\n", ret);
 
     if (sslsock->ssl != NULL) {
-            fprintf(stderr, "FIXME ->ssl is null, reading ->err\n");
         err = sslsock->err;
 
         switch (err.ssl) {
@@ -792,21 +789,14 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
                     }
 #endif
                     if (err.c) {
-                            fprintf(stderr, "FIXME got err.c\n");
                         errno = err.c;
                         return PyErr_SetFromErrno(PyExc_OSError);
                     }
                     else {
-                            fprintf(stderr, "FIXME do not have err.c\n");
-                            p = PY_SSL_ERROR_EOF;
-                            type = PySSLEOFErrorObject;
-                            errstr = "EOF occurred in violation of protocol";
-                            
+                        p = PY_SSL_ERROR_EOF;
+                        type = PySSLEOFErrorObject;
+                        errstr = "EOF occurred in violation of protocol";
                     }
-                    // Py_INCREF(s);
-                    // s->errorhandler();
-                    // Py_DECREF(s);
-                    //return NULL;
                 } else { /* possible? */
                     p = PY_SSL_ERROR_SYSCALL;
                     type = PySSLSyscallErrorObject;
@@ -1048,7 +1038,6 @@ static PyObject *
 _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
 /*[clinic end generated code: output=6c0898a8936548f6 input=d2d737de3df018c8]*/
 {
-        fprintf(stderr, "FIXME here\n");
     int ret;
     _PySSLError err;
     int sockstate, nonblocking;
@@ -1057,11 +1046,9 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
     int has_timeout;
 
     if (sock) {
-        fprintf(stderr, "FIXME here 33\n");
         if (((PyObject*)sock) == Py_None) {
             _setSSLError("Underlying socket connection gone",
                          PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__);
-        fprintf(stderr, "FIXME here 42\n");
             return NULL;
         }
         Py_INCREF(sock);
@@ -1082,9 +1069,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
     do {
         PySSL_BEGIN_ALLOW_THREADS
         ret = SSL_do_handshake(self->ssl);
-        fprintf(stderr, "FIXME loop iter, ret now %d\n", ret);
         err = _PySSL_errno(ret < 1, self->ssl, ret);
-        fprintf(stderr, "FIXME loop iter, err.c %d err.ssl %d\n", err.c, err.ssl);
         PySSL_END_ALLOW_THREADS
         self->err = err;
 
@@ -1095,13 +1080,10 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
             timeout = deadline - _PyTime_GetMonotonicClock();
 
         if (err.ssl == SSL_ERROR_WANT_READ) {
-        fprintf(stderr, "FIXME want read\n");
             sockstate = PySSL_select(sock, 0, timeout);
         } else if (err.ssl == SSL_ERROR_WANT_WRITE) {
-        fprintf(stderr, "FIXME want write\n");
             sockstate = PySSL_select(sock, 1, timeout);
         } else {
-        fprintf(stderr, "FIXME assume ok\n");
             sockstate = SOCKET_OPERATION_OK;
         }
 
@@ -1110,7 +1092,6 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
                             ERRSTR("The handshake operation timed out"));
             goto error;
         } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) {
-                fprintf(stderr, "FIXME -- does not happen\n");
             PyErr_SetString(PySSLErrorObject,
                             ERRSTR("Underlying socket has been closed."));
             goto error;
@@ -1123,7 +1104,6 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
         }
     } while (err.ssl == SSL_ERROR_WANT_READ ||
              err.ssl == SSL_ERROR_WANT_WRITE);
-    fprintf(stderr, "FIXME loop done %d\n", ret);
     Py_XDECREF(sock);
     if (ret < 1)
         return PySSL_SetError(self, ret, __FILE__, __LINE__);

From 3ce5ebc79ea8e2a0f074003ea9b4fb54b863fa02 Mon Sep 17 00:00:00 2001
From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com>
Date: Wed, 11 Mar 2020 07:44:07 +0000
Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?=
 =?UTF-8?q?rb=5Fit.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../NEWS.d/next/Library/2020-03-11-07-44-06.bpo-31122.zIQ80l.rst | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 Misc/NEWS.d/next/Library/2020-03-11-07-44-06.bpo-31122.zIQ80l.rst

diff --git a/Misc/NEWS.d/next/Library/2020-03-11-07-44-06.bpo-31122.zIQ80l.rst b/Misc/NEWS.d/next/Library/2020-03-11-07-44-06.bpo-31122.zIQ80l.rst
new file mode 100644
index 00000000000000..2e70f7aee65c83
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-03-11-07-44-06.bpo-31122.zIQ80l.rst
@@ -0,0 +1 @@
+ssl.wrap_socket() now raises ssl.SSLEOFError rather than OSError when peer closes connection during TLS negotiation
\ No newline at end of file
