@@ -423,6 +423,14 @@ typedef struct {
423423 int protocol ;
424424} PySSLContext ;
425425
426+ typedef struct {
427+ int ssl ; /* last seen error from SSL */
428+ int c ; /* last seen error from libc */
429+ #ifdef MS_WINDOWS
430+ int ws ; /* last seen error from winsock */
431+ #endif
432+ } _PySSLError ;
433+
426434typedef struct {
427435 PyObject_HEAD
428436 PyObject * Socket ; /* weakref to socket on which we're layered */
@@ -432,11 +440,7 @@ typedef struct {
432440 enum py_ssl_server_or_client socket_type ;
433441 PyObject * owner ; /* Python level "owner" passed to servername callback */
434442 PyObject * server_hostname ;
435- int ssl_errno ; /* last seen error from SSL */
436- int c_errno ; /* last seen error from libc */
437- #ifdef MS_WINDOWS
438- int ws_errno ; /* last seen error from winsock */
439- #endif
443+ _PySSLError err ; /* last seen error from various sources */
440444} PySSLSocket ;
441445
442446typedef struct {
@@ -456,20 +460,19 @@ static PyTypeObject PySSLSocket_Type;
456460static PyTypeObject PySSLMemoryBIO_Type ;
457461static PyTypeObject PySSLSession_Type ;
458462
463+ static inline _PySSLError _PySSL_errno (int failed , const SSL * ssl , int retcode )
464+ {
465+ _PySSLError err = { 0 };
466+ if (failed ) {
459467#ifdef MS_WINDOWS
460- #define _PySSL_UPDATE_ERRNO_IF (cond , sock , retcode ) if (cond) { \
461- (sock)->ws_errno = WSAGetLastError(); \
462- _PySSL_FIX_ERRNO; \
463- (sock)->c_errno = errno; \
464- (sock)->ssl_errno = SSL_get_error((sock->ssl), (retcode)); \
465- } else { sock->ws_errno = 0; sock->c_errno = 0; sock->ssl_errno = 0; }
466- #else
467- #define _PySSL_UPDATE_ERRNO_IF (cond , sock , retcode ) if (cond) { \
468- (sock)->c_errno = errno; \
469- (sock)->ssl_errno = SSL_get_error((sock->ssl), (retcode)); \
470- } else { (sock)->c_errno = 0; (sock)->ssl_errno = 0; }
468+ err .ws = WSAGetLastError ();
469+ _PySSL_FIX_ERRNO ;
471470#endif
472- #define _PySSL_UPDATE_ERRNO (sock , retcode ) _PySSL_UPDATE_ERRNO_IF(1, (sock), (retcode))
471+ err .c = errno ;
472+ err .ssl = SSL_get_error (ssl , retcode );
473+ }
474+ return err ;
475+ }
473476
474477/*[clinic input]
475478module _ssl
@@ -703,17 +706,17 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
703706{
704707 PyObject * type = PySSLErrorObject ;
705708 char * errstr = NULL ;
706- int err ;
709+ _PySSLError err ;
707710 enum py_ssl_error p = PY_SSL_ERROR_NONE ;
708711 unsigned long e = 0 ;
709712
710713 assert (ret <= 0 );
711714 e = ERR_peek_last_error ();
712715
713716 if (sslsock -> ssl != NULL ) {
714- err = sslsock -> ssl_errno ;
717+ err = sslsock -> err ;
715718
716- switch (err ) {
719+ switch (err . ssl ) {
717720 case SSL_ERROR_ZERO_RETURN :
718721 errstr = "TLS/SSL connection has been closed (EOF)" ;
719722 type = PySSLZeroReturnErrorObject ;
@@ -749,11 +752,12 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
749752 /* underlying BIO reported an I/O error */
750753 ERR_clear_error ();
751754#ifdef MS_WINDOWS
752- if (sslsock -> ws_errno )
753- return PyErr_SetFromWindowsErr (sslsock -> ws_errno );
755+ if (err .ws ) {
756+ return PyErr_SetFromWindowsErr (err .ws );
757+ }
754758#endif
755- if (sslsock -> c_errno ) {
756- errno = sslsock -> c_errno ;
759+ if (err . c ) {
760+ errno = err . c ;
757761 return PyErr_SetFromErrno (PyExc_OSError );
758762 }
759763 Py_INCREF (s );
@@ -883,6 +887,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
883887{
884888 PySSLSocket * self ;
885889 SSL_CTX * ctx = sslctx -> ctx ;
890+ _PySSLError err = { 0 };
886891
887892 self = PyObject_New (PySSLSocket , & PySSLSocket_Type );
888893 if (self == NULL )
@@ -895,11 +900,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
895900 self -> shutdown_seen_zero = 0 ;
896901 self -> owner = NULL ;
897902 self -> server_hostname = NULL ;
898- self -> ssl_errno = 0 ;
899- self -> c_errno = 0 ;
900- #ifdef MS_WINDOWS
901- self -> ws_errno = 0 ;
902- #endif
903+ self -> err = err ;
903904
904905 /* Make sure the SSL error state is initialized */
905906 (void ) ERR_get_state ();
@@ -977,7 +978,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
977978/*[clinic end generated code: output=6c0898a8936548f6 input=d2d737de3df018c8]*/
978979{
979980 int ret ;
980- int err ;
981+ _PySSLError err ;
981982 int sockstate , nonblocking ;
982983 PySocketSockObject * sock = GET_SOCKET (self );
983984 _PyTime_t timeout , deadline = 0 ;
@@ -1007,19 +1008,19 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
10071008 do {
10081009 PySSL_BEGIN_ALLOW_THREADS
10091010 ret = SSL_do_handshake (self -> ssl );
1010- _PySSL_UPDATE_ERRNO_IF (ret < 1 , self , ret );
1011+ err = _PySSL_errno (ret < 1 , self -> ssl , ret );
10111012 PySSL_END_ALLOW_THREADS
1012- err = self -> ssl_errno ;
1013+ self -> err = err ;
10131014
10141015 if (PyErr_CheckSignals ())
10151016 goto error ;
10161017
10171018 if (has_timeout )
10181019 timeout = deadline - _PyTime_GetMonotonicClock ();
10191020
1020- if (err == SSL_ERROR_WANT_READ ) {
1021+ if (err . ssl == SSL_ERROR_WANT_READ ) {
10211022 sockstate = PySSL_select (sock , 0 , timeout );
1022- } else if (err == SSL_ERROR_WANT_WRITE ) {
1023+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
10231024 sockstate = PySSL_select (sock , 1 , timeout );
10241025 } else {
10251026 sockstate = SOCKET_OPERATION_OK ;
@@ -1040,7 +1041,8 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
10401041 } else if (sockstate == SOCKET_IS_NONBLOCKING ) {
10411042 break ;
10421043 }
1043- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE );
1044+ } while (err .ssl == SSL_ERROR_WANT_READ ||
1045+ err .ssl == SSL_ERROR_WANT_WRITE );
10441046 Py_XDECREF (sock );
10451047 if (ret < 1 )
10461048 return PySSL_SetError (self , ret , __FILE__ , __LINE__ );
@@ -2229,7 +2231,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
22292231{
22302232 int len ;
22312233 int sockstate ;
2232- int err ;
2234+ _PySSLError err ;
22332235 int nonblocking ;
22342236 PySocketSockObject * sock = GET_SOCKET (self );
22352237 _PyTime_t timeout , deadline = 0 ;
@@ -2280,19 +2282,19 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
22802282 do {
22812283 PySSL_BEGIN_ALLOW_THREADS
22822284 len = SSL_write (self -> ssl , b -> buf , (int )b -> len );
2283- _PySSL_UPDATE_ERRNO_IF (len <= 0 , self , len );
2285+ err = _PySSL_errno (len <= 0 , self -> ssl , len );
22842286 PySSL_END_ALLOW_THREADS
2285- err = self -> ssl_errno ;
2287+ self -> err = err ;
22862288
22872289 if (PyErr_CheckSignals ())
22882290 goto error ;
22892291
22902292 if (has_timeout )
22912293 timeout = deadline - _PyTime_GetMonotonicClock ();
22922294
2293- if (err == SSL_ERROR_WANT_READ ) {
2295+ if (err . ssl == SSL_ERROR_WANT_READ ) {
22942296 sockstate = PySSL_select (sock , 0 , timeout );
2295- } else if (err == SSL_ERROR_WANT_WRITE ) {
2297+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
22962298 sockstate = PySSL_select (sock , 1 , timeout );
22972299 } else {
22982300 sockstate = SOCKET_OPERATION_OK ;
@@ -2309,7 +2311,8 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
23092311 } else if (sockstate == SOCKET_IS_NONBLOCKING ) {
23102312 break ;
23112313 }
2312- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE );
2314+ } while (err .ssl == SSL_ERROR_WANT_READ ||
2315+ err .ssl == SSL_ERROR_WANT_WRITE );
23132316
23142317 Py_XDECREF (sock );
23152318 if (len > 0 )
@@ -2333,11 +2336,14 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
23332336/*[clinic end generated code: output=983d9fecdc308a83 input=2b77487d6dfd597f]*/
23342337{
23352338 int count = 0 ;
2339+ _PySSLError err ;
23362340
23372341 PySSL_BEGIN_ALLOW_THREADS
23382342 count = SSL_pending (self -> ssl );
2339- _PySSL_UPDATE_ERRNO_IF (count < 0 , self , count );
2343+ err = _PySSL_errno (count < 0 , self -> ssl , count );
23402344 PySSL_END_ALLOW_THREADS
2345+ self -> err = err ;
2346+
23412347 if (count < 0 )
23422348 return PySSL_SetError (self , count , __FILE__ , __LINE__ );
23432349 else
@@ -2364,7 +2370,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
23642370 char * mem ;
23652371 int count ;
23662372 int sockstate ;
2367- int err ;
2373+ _PySSLError err ;
23682374 int nonblocking ;
23692375 PySocketSockObject * sock = GET_SOCKET (self );
23702376 _PyTime_t timeout , deadline = 0 ;
@@ -2425,21 +2431,21 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
24252431 do {
24262432 PySSL_BEGIN_ALLOW_THREADS
24272433 count = SSL_read (self -> ssl , mem , len );
2428- _PySSL_UPDATE_ERRNO_IF (count <= 0 , self , count );
2434+ err = _PySSL_errno (count <= 0 , self -> ssl , count );
24292435 PySSL_END_ALLOW_THREADS
2436+ self -> err = err ;
24302437
24312438 if (PyErr_CheckSignals ())
24322439 goto error ;
24332440
24342441 if (has_timeout )
24352442 timeout = deadline - _PyTime_GetMonotonicClock ();
24362443
2437- err = self -> ssl_errno ;
2438- if (err == SSL_ERROR_WANT_READ ) {
2444+ if (err .ssl == SSL_ERROR_WANT_READ ) {
24392445 sockstate = PySSL_select (sock , 0 , timeout );
2440- } else if (err == SSL_ERROR_WANT_WRITE ) {
2446+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
24412447 sockstate = PySSL_select (sock , 1 , timeout );
2442- } else if (err == SSL_ERROR_ZERO_RETURN &&
2448+ } else if (err . ssl == SSL_ERROR_ZERO_RETURN &&
24432449 SSL_get_shutdown (self -> ssl ) == SSL_RECEIVED_SHUTDOWN )
24442450 {
24452451 count = 0 ;
@@ -2455,7 +2461,8 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
24552461 } else if (sockstate == SOCKET_IS_NONBLOCKING ) {
24562462 break ;
24572463 }
2458- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE );
2464+ } while (err .ssl == SSL_ERROR_WANT_READ ||
2465+ err .ssl == SSL_ERROR_WANT_WRITE );
24592466
24602467 if (count <= 0 ) {
24612468 PySSL_SetError (self , count , __FILE__ , __LINE__ );
@@ -2489,7 +2496,8 @@ static PyObject *
24892496_ssl__SSLSocket_shutdown_impl (PySSLSocket * self )
24902497/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=11d39e69b0a2bf4a]*/
24912498{
2492- int err , sockstate , nonblocking ;
2499+ _PySSLError err ;
2500+ int sockstate , nonblocking , ret ;
24932501 int zeros = 0 ;
24942502 PySocketSockObject * sock = GET_SOCKET (self );
24952503 _PyTime_t timeout , deadline = 0 ;
@@ -2527,14 +2535,15 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
25272535 */
25282536 if (self -> shutdown_seen_zero )
25292537 SSL_set_read_ahead (self - > ssl , 0 );
2530- err = SSL_shutdown (self -> ssl );
2531- _PySSL_UPDATE_ERRNO_IF ( err < 0 , self , err );
2538+ ret = SSL_shutdown (self -> ssl );
2539+ err = _PySSL_errno ( ret < 0 , self -> ssl , ret );
25322540 PySSL_END_ALLOW_THREADS
2541+ self -> err = err ;
25332542
25342543 /* If err == 1, a secure shutdown with SSL_shutdown() is complete */
2535- if (err > 0 )
2544+ if (ret > 0 )
25362545 break ;
2537- if (err == 0 ) {
2546+ if (ret == 0 ) {
25382547 /* Don't loop endlessly; instead preserve legacy
25392548 behaviour of trying SSL_shutdown() only twice.
25402549 This looks necessary for OpenSSL < 0.9.8m */
@@ -2549,16 +2558,15 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
25492558 timeout = deadline - _PyTime_GetMonotonicClock ();
25502559
25512560 /* Possibly retry shutdown until timeout or failure */
2552- _PySSL_UPDATE_ERRNO (self , err );
2553- if (self -> ssl_errno == SSL_ERROR_WANT_READ )
2561+ if (err .ssl == SSL_ERROR_WANT_READ )
25542562 sockstate = PySSL_select (sock , 0 , timeout );
2555- else if (self -> ssl_errno == SSL_ERROR_WANT_WRITE )
2563+ else if (err . ssl == SSL_ERROR_WANT_WRITE )
25562564 sockstate = PySSL_select (sock , 1 , timeout );
25572565 else
25582566 break ;
25592567
25602568 if (sockstate == SOCKET_HAS_TIMED_OUT ) {
2561- if (self -> ssl_errno == SSL_ERROR_WANT_READ )
2569+ if (err . ssl == SSL_ERROR_WANT_READ )
25622570 PyErr_SetString (PySocketModule .timeout_error ,
25632571 "The read operation timed out" );
25642572 else
@@ -2576,9 +2584,9 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
25762584 break ;
25772585 }
25782586
2579- if (err < 0 ) {
2587+ if (err . ssl < 0 ) {
25802588 Py_XDECREF (sock );
2581- return PySSL_SetError (self , err , __FILE__ , __LINE__ );
2589+ return PySSL_SetError (self , err . ssl , __FILE__ , __LINE__ );
25822590 }
25832591 if (sock )
25842592 /* It's already INCREF'ed */
0 commit comments