diff --git a/Lib/test/test_asyncio/test_ssl.py b/Lib/test/test_asyncio/test_ssl.py index 5e3c1573c9c587..78778f6ea02465 100644 --- a/Lib/test/test_asyncio/test_ssl.py +++ b/Lib/test/test_asyncio/test_ssl.py @@ -1080,12 +1080,14 @@ def prog(sock): try: sock.connect(addr) sock.starttls(client_sslctx_1) + sock._sslobj._debug_bio() # because wrap_socket() doesn't work correctly on # SSLSocket, we have to do the 2nd level SSL manually incoming = ssl.MemoryBIO() outgoing = ssl.MemoryBIO() sslobj = client_sslctx_2.wrap_bio(incoming, outgoing) + sslobj._sslobj._debug_bio() def do(func, *args): while True: diff --git a/Modules/_ssl.c b/Modules/_ssl.c index bf8bd9dea89b6b..4a8ae6bb5f1375 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -21,6 +21,8 @@ #endif #define OPENSSL_NO_DEPRECATED 1 +#define PY_DEBUG_BIO 1 + #define PY_SSIZE_T_CLEAN #include "Python.h" @@ -668,6 +670,21 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) p = PY_SSL_ERROR_INVALID_ERROR_CODE; errstr = "Invalid error code"; } +#if PY_DEBUG_BIO + if (p == PY_SSL_ERROR_EOF) { + BIO *rb, *wb; + rb = SSL_get_rbio(sslsock->ssl); + wb = SSL_get_wbio(sslsock->ssl); + if (rb != wb) { + fprintf(stderr, "BIO[%p] ssl.SSLEOFError: %s (read)\n", rb, errstr); + fprintf(stderr, "BIO[%p] ssl.SSLEOFError: %s (write)\n", wb, errstr); + } else { + int fd = -1; + (void)BIO_get_fd(rb, &fd); + fprintf(stderr, "BIO[%p] ssl.SSLEOFError: %s (fd=%i)\n", rb, errstr, fd); + } + } +#endif } fill_and_set_sslerror(state, sslsock, type, p, errstr, lineno, e); ERR_clear_error(); @@ -2752,6 +2769,30 @@ _ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self) #endif } +#if PY_DEBUG_BIO +/*[clinic input] +_ssl._SSLSocket._debug_bio +[clinic start generated code]*/ + +static PyObject * +_ssl__SSLSocket__debug_bio_impl(PySSLSocket *self) +/*[clinic end generated code: output=16043f90e4d11e66 input=4b0cc8d6ed9998cb]*/ +{ + BIO *rb, *wb; + rb = SSL_get_rbio(self->ssl); + wb = SSL_get_wbio(self->ssl); + if (rb != NULL) { + BIO_set_callback(rb, &BIO_debug_callback); + // socket BIO uses same BIO for both directions. + // mem bio uses a different BIO for each direction. + if (wb != rb) { + BIO_set_callback(wb, &BIO_debug_callback); + } + } + Py_RETURN_NONE; +} +#endif + static SSL_SESSION* _ssl_session_dup(SSL_SESSION *session) { SSL_SESSION *newsession = NULL; @@ -2918,6 +2959,7 @@ static PyMethodDef PySSLMethods[] = { _SSL__SSLSOCKET_VERIFY_CLIENT_POST_HANDSHAKE_METHODDEF _SSL__SSLSOCKET_GET_UNVERIFIED_CHAIN_METHODDEF _SSL__SSLSOCKET_GET_VERIFIED_CHAIN_METHODDEF + _SSL__SSLSOCKET__DEBUG_BIO_METHODDEF {NULL, NULL} }; diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 24604dd43687c5..236e58248a6b43 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -399,6 +399,27 @@ _ssl__SSLSocket_verify_client_post_handshake(PySSLSocket *self, PyObject *Py_UNU return _ssl__SSLSocket_verify_client_post_handshake_impl(self); } +#if (PY_DEBUG_BIO) + +PyDoc_STRVAR(_ssl__SSLSocket__debug_bio__doc__, +"_debug_bio($self, /)\n" +"--\n" +"\n"); + +#define _SSL__SSLSOCKET__DEBUG_BIO_METHODDEF \ + {"_debug_bio", (PyCFunction)_ssl__SSLSocket__debug_bio, METH_NOARGS, _ssl__SSLSocket__debug_bio__doc__}, + +static PyObject * +_ssl__SSLSocket__debug_bio_impl(PySSLSocket *self); + +static PyObject * +_ssl__SSLSocket__debug_bio(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +{ + return _ssl__SSLSocket__debug_bio_impl(self); +} + +#endif /* (PY_DEBUG_BIO) */ + static PyObject * _ssl__SSLContext_impl(PyTypeObject *type, int proto_version); @@ -1323,6 +1344,10 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #endif /* defined(_MSC_VER) */ +#ifndef _SSL__SSLSOCKET__DEBUG_BIO_METHODDEF + #define _SSL__SSLSOCKET__DEBUG_BIO_METHODDEF +#endif /* !defined(_SSL__SSLSOCKET__DEBUG_BIO_METHODDEF) */ + #ifndef _SSL_ENUM_CERTIFICATES_METHODDEF #define _SSL_ENUM_CERTIFICATES_METHODDEF #endif /* !defined(_SSL_ENUM_CERTIFICATES_METHODDEF) */ @@ -1330,4 +1355,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=9d806f8ff4a06ed3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0305e6f6115dc11d input=a9049054013a1b77]*/