@@ -423,6 +423,14 @@ typedef struct {
423
423
int protocol ;
424
424
} PySSLContext ;
425
425
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
+
426
434
typedef struct {
427
435
PyObject_HEAD
428
436
PyObject * Socket ; /* weakref to socket on which we're layered */
@@ -432,11 +440,7 @@ typedef struct {
432
440
enum py_ssl_server_or_client socket_type ;
433
441
PyObject * owner ; /* Python level "owner" passed to servername callback */
434
442
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 */
440
444
} PySSLSocket ;
441
445
442
446
typedef struct {
@@ -456,20 +460,19 @@ static PyTypeObject PySSLSocket_Type;
456
460
static PyTypeObject PySSLMemoryBIO_Type ;
457
461
static PyTypeObject PySSLSession_Type ;
458
462
463
+ static inline _PySSLError _PySSL_errno (int failed , const SSL * ssl , int retcode )
464
+ {
465
+ _PySSLError err = { 0 };
466
+ if (failed ) {
459
467
#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 ;
471
470
#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
+ }
473
476
474
477
/*[clinic input]
475
478
module _ssl
@@ -703,17 +706,17 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
703
706
{
704
707
PyObject * type = PySSLErrorObject ;
705
708
char * errstr = NULL ;
706
- int err ;
709
+ _PySSLError err ;
707
710
enum py_ssl_error p = PY_SSL_ERROR_NONE ;
708
711
unsigned long e = 0 ;
709
712
710
713
assert (ret <= 0 );
711
714
e = ERR_peek_last_error ();
712
715
713
716
if (sslsock -> ssl != NULL ) {
714
- err = sslsock -> ssl_errno ;
717
+ err = sslsock -> err ;
715
718
716
- switch (err ) {
719
+ switch (err . ssl ) {
717
720
case SSL_ERROR_ZERO_RETURN :
718
721
errstr = "TLS/SSL connection has been closed (EOF)" ;
719
722
type = PySSLZeroReturnErrorObject ;
@@ -749,11 +752,12 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno)
749
752
/* underlying BIO reported an I/O error */
750
753
ERR_clear_error ();
751
754
#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
+ }
754
758
#endif
755
- if (sslsock -> c_errno ) {
756
- errno = sslsock -> c_errno ;
759
+ if (err . c ) {
760
+ errno = err . c ;
757
761
return PyErr_SetFromErrno (PyExc_OSError );
758
762
}
759
763
Py_INCREF (s );
@@ -883,6 +887,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
883
887
{
884
888
PySSLSocket * self ;
885
889
SSL_CTX * ctx = sslctx -> ctx ;
890
+ _PySSLError err = { 0 };
886
891
887
892
self = PyObject_New (PySSLSocket , & PySSLSocket_Type );
888
893
if (self == NULL )
@@ -895,11 +900,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
895
900
self -> shutdown_seen_zero = 0 ;
896
901
self -> owner = NULL ;
897
902
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 ;
903
904
904
905
/* Make sure the SSL error state is initialized */
905
906
(void ) ERR_get_state ();
@@ -977,7 +978,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
977
978
/*[clinic end generated code: output=6c0898a8936548f6 input=d2d737de3df018c8]*/
978
979
{
979
980
int ret ;
980
- int err ;
981
+ _PySSLError err ;
981
982
int sockstate , nonblocking ;
982
983
PySocketSockObject * sock = GET_SOCKET (self );
983
984
_PyTime_t timeout , deadline = 0 ;
@@ -1007,19 +1008,19 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
1007
1008
do {
1008
1009
PySSL_BEGIN_ALLOW_THREADS
1009
1010
ret = SSL_do_handshake (self -> ssl );
1010
- _PySSL_UPDATE_ERRNO_IF (ret < 1 , self , ret );
1011
+ err = _PySSL_errno (ret < 1 , self -> ssl , ret );
1011
1012
PySSL_END_ALLOW_THREADS
1012
- err = self -> ssl_errno ;
1013
+ self -> err = err ;
1013
1014
1014
1015
if (PyErr_CheckSignals ())
1015
1016
goto error ;
1016
1017
1017
1018
if (has_timeout )
1018
1019
timeout = deadline - _PyTime_GetMonotonicClock ();
1019
1020
1020
- if (err == SSL_ERROR_WANT_READ ) {
1021
+ if (err . ssl == SSL_ERROR_WANT_READ ) {
1021
1022
sockstate = PySSL_select (sock , 0 , timeout );
1022
- } else if (err == SSL_ERROR_WANT_WRITE ) {
1023
+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
1023
1024
sockstate = PySSL_select (sock , 1 , timeout );
1024
1025
} else {
1025
1026
sockstate = SOCKET_OPERATION_OK ;
@@ -1040,7 +1041,8 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
1040
1041
} else if (sockstate == SOCKET_IS_NONBLOCKING ) {
1041
1042
break ;
1042
1043
}
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 );
1044
1046
Py_XDECREF (sock );
1045
1047
if (ret < 1 )
1046
1048
return PySSL_SetError (self , ret , __FILE__ , __LINE__ );
@@ -2229,7 +2231,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2229
2231
{
2230
2232
int len ;
2231
2233
int sockstate ;
2232
- int err ;
2234
+ _PySSLError err ;
2233
2235
int nonblocking ;
2234
2236
PySocketSockObject * sock = GET_SOCKET (self );
2235
2237
_PyTime_t timeout , deadline = 0 ;
@@ -2280,19 +2282,19 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2280
2282
do {
2281
2283
PySSL_BEGIN_ALLOW_THREADS
2282
2284
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 );
2284
2286
PySSL_END_ALLOW_THREADS
2285
- err = self -> ssl_errno ;
2287
+ self -> err = err ;
2286
2288
2287
2289
if (PyErr_CheckSignals ())
2288
2290
goto error ;
2289
2291
2290
2292
if (has_timeout )
2291
2293
timeout = deadline - _PyTime_GetMonotonicClock ();
2292
2294
2293
- if (err == SSL_ERROR_WANT_READ ) {
2295
+ if (err . ssl == SSL_ERROR_WANT_READ ) {
2294
2296
sockstate = PySSL_select (sock , 0 , timeout );
2295
- } else if (err == SSL_ERROR_WANT_WRITE ) {
2297
+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
2296
2298
sockstate = PySSL_select (sock , 1 , timeout );
2297
2299
} else {
2298
2300
sockstate = SOCKET_OPERATION_OK ;
@@ -2309,7 +2311,8 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2309
2311
} else if (sockstate == SOCKET_IS_NONBLOCKING ) {
2310
2312
break ;
2311
2313
}
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 );
2313
2316
2314
2317
Py_XDECREF (sock );
2315
2318
if (len > 0 )
@@ -2333,11 +2336,14 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
2333
2336
/*[clinic end generated code: output=983d9fecdc308a83 input=2b77487d6dfd597f]*/
2334
2337
{
2335
2338
int count = 0 ;
2339
+ _PySSLError err ;
2336
2340
2337
2341
PySSL_BEGIN_ALLOW_THREADS
2338
2342
count = SSL_pending (self -> ssl );
2339
- _PySSL_UPDATE_ERRNO_IF (count < 0 , self , count );
2343
+ err = _PySSL_errno (count < 0 , self -> ssl , count );
2340
2344
PySSL_END_ALLOW_THREADS
2345
+ self -> err = err ;
2346
+
2341
2347
if (count < 0 )
2342
2348
return PySSL_SetError (self , count , __FILE__ , __LINE__ );
2343
2349
else
@@ -2364,7 +2370,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
2364
2370
char * mem ;
2365
2371
int count ;
2366
2372
int sockstate ;
2367
- int err ;
2373
+ _PySSLError err ;
2368
2374
int nonblocking ;
2369
2375
PySocketSockObject * sock = GET_SOCKET (self );
2370
2376
_PyTime_t timeout , deadline = 0 ;
@@ -2425,21 +2431,21 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
2425
2431
do {
2426
2432
PySSL_BEGIN_ALLOW_THREADS
2427
2433
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 );
2429
2435
PySSL_END_ALLOW_THREADS
2436
+ self -> err = err ;
2430
2437
2431
2438
if (PyErr_CheckSignals ())
2432
2439
goto error ;
2433
2440
2434
2441
if (has_timeout )
2435
2442
timeout = deadline - _PyTime_GetMonotonicClock ();
2436
2443
2437
- err = self -> ssl_errno ;
2438
- if (err == SSL_ERROR_WANT_READ ) {
2444
+ if (err .ssl == SSL_ERROR_WANT_READ ) {
2439
2445
sockstate = PySSL_select (sock , 0 , timeout );
2440
- } else if (err == SSL_ERROR_WANT_WRITE ) {
2446
+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
2441
2447
sockstate = PySSL_select (sock , 1 , timeout );
2442
- } else if (err == SSL_ERROR_ZERO_RETURN &&
2448
+ } else if (err . ssl == SSL_ERROR_ZERO_RETURN &&
2443
2449
SSL_get_shutdown (self -> ssl ) == SSL_RECEIVED_SHUTDOWN )
2444
2450
{
2445
2451
count = 0 ;
@@ -2455,7 +2461,8 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
2455
2461
} else if (sockstate == SOCKET_IS_NONBLOCKING ) {
2456
2462
break ;
2457
2463
}
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 );
2459
2466
2460
2467
if (count <= 0 ) {
2461
2468
PySSL_SetError (self , count , __FILE__ , __LINE__ );
@@ -2489,7 +2496,8 @@ static PyObject *
2489
2496
_ssl__SSLSocket_shutdown_impl (PySSLSocket * self )
2490
2497
/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=11d39e69b0a2bf4a]*/
2491
2498
{
2492
- int err , sockstate , nonblocking ;
2499
+ _PySSLError err ;
2500
+ int sockstate , nonblocking , ret ;
2493
2501
int zeros = 0 ;
2494
2502
PySocketSockObject * sock = GET_SOCKET (self );
2495
2503
_PyTime_t timeout , deadline = 0 ;
@@ -2527,14 +2535,15 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2527
2535
*/
2528
2536
if (self -> shutdown_seen_zero )
2529
2537
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 );
2532
2540
PySSL_END_ALLOW_THREADS
2541
+ self -> err = err ;
2533
2542
2534
2543
/* If err == 1, a secure shutdown with SSL_shutdown() is complete */
2535
- if (err > 0 )
2544
+ if (ret > 0 )
2536
2545
break ;
2537
- if (err == 0 ) {
2546
+ if (ret == 0 ) {
2538
2547
/* Don't loop endlessly; instead preserve legacy
2539
2548
behaviour of trying SSL_shutdown() only twice.
2540
2549
This looks necessary for OpenSSL < 0.9.8m */
@@ -2549,16 +2558,15 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2549
2558
timeout = deadline - _PyTime_GetMonotonicClock ();
2550
2559
2551
2560
/* 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 )
2554
2562
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 )
2556
2564
sockstate = PySSL_select (sock , 1 , timeout );
2557
2565
else
2558
2566
break ;
2559
2567
2560
2568
if (sockstate == SOCKET_HAS_TIMED_OUT ) {
2561
- if (self -> ssl_errno == SSL_ERROR_WANT_READ )
2569
+ if (err . ssl == SSL_ERROR_WANT_READ )
2562
2570
PyErr_SetString (PySocketModule .timeout_error ,
2563
2571
"The read operation timed out" );
2564
2572
else
@@ -2576,9 +2584,9 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2576
2584
break ;
2577
2585
}
2578
2586
2579
- if (err < 0 ) {
2587
+ if (err . ssl < 0 ) {
2580
2588
Py_XDECREF (sock );
2581
- return PySSL_SetError (self , err , __FILE__ , __LINE__ );
2589
+ return PySSL_SetError (self , err . ssl , __FILE__ , __LINE__ );
2582
2590
}
2583
2591
if (sock )
2584
2592
/* It's already INCREF'ed */
0 commit comments