@@ -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
ERR_clear_error ();
@@ -976,7 +977,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
976
977
/*[clinic end generated code: output=6c0898a8936548f6 input=d2d737de3df018c8]*/
977
978
{
978
979
int ret ;
979
- int err ;
980
+ _PySSLError err ;
980
981
int sockstate , nonblocking ;
981
982
PySocketSockObject * sock = GET_SOCKET (self );
982
983
_PyTime_t timeout , deadline = 0 ;
@@ -1006,19 +1007,19 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
1006
1007
do {
1007
1008
PySSL_BEGIN_ALLOW_THREADS
1008
1009
ret = SSL_do_handshake (self -> ssl );
1009
- _PySSL_UPDATE_ERRNO_IF (ret < 1 , self , ret );
1010
+ err = _PySSL_errno (ret < 1 , self -> ssl , ret );
1010
1011
PySSL_END_ALLOW_THREADS
1011
- err = self -> ssl_errno ;
1012
+ self -> err = err ;
1012
1013
1013
1014
if (PyErr_CheckSignals ())
1014
1015
goto error ;
1015
1016
1016
1017
if (has_timeout )
1017
1018
timeout = deadline - _PyTime_GetMonotonicClock ();
1018
1019
1019
- if (err == SSL_ERROR_WANT_READ ) {
1020
+ if (err . ssl == SSL_ERROR_WANT_READ ) {
1020
1021
sockstate = PySSL_select (sock , 0 , timeout );
1021
- } else if (err == SSL_ERROR_WANT_WRITE ) {
1022
+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
1022
1023
sockstate = PySSL_select (sock , 1 , timeout );
1023
1024
} else {
1024
1025
sockstate = SOCKET_OPERATION_OK ;
@@ -1039,7 +1040,8 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
1039
1040
} else if (sockstate == SOCKET_IS_NONBLOCKING ) {
1040
1041
break ;
1041
1042
}
1042
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE );
1043
+ } while (err .ssl == SSL_ERROR_WANT_READ ||
1044
+ err .ssl == SSL_ERROR_WANT_WRITE );
1043
1045
Py_XDECREF (sock );
1044
1046
if (ret < 1 )
1045
1047
return PySSL_SetError (self , ret , __FILE__ , __LINE__ );
@@ -2228,7 +2230,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2228
2230
{
2229
2231
int len ;
2230
2232
int sockstate ;
2231
- int err ;
2233
+ _PySSLError err ;
2232
2234
int nonblocking ;
2233
2235
PySocketSockObject * sock = GET_SOCKET (self );
2234
2236
_PyTime_t timeout , deadline = 0 ;
@@ -2279,19 +2281,19 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2279
2281
do {
2280
2282
PySSL_BEGIN_ALLOW_THREADS
2281
2283
len = SSL_write (self -> ssl , b -> buf , (int )b -> len );
2282
- _PySSL_UPDATE_ERRNO_IF (len <= 0 , self , len );
2284
+ err = _PySSL_errno (len <= 0 , self -> ssl , len );
2283
2285
PySSL_END_ALLOW_THREADS
2284
- err = self -> ssl_errno ;
2286
+ self -> err = err ;
2285
2287
2286
2288
if (PyErr_CheckSignals ())
2287
2289
goto error ;
2288
2290
2289
2291
if (has_timeout )
2290
2292
timeout = deadline - _PyTime_GetMonotonicClock ();
2291
2293
2292
- if (err == SSL_ERROR_WANT_READ ) {
2294
+ if (err . ssl == SSL_ERROR_WANT_READ ) {
2293
2295
sockstate = PySSL_select (sock , 0 , timeout );
2294
- } else if (err == SSL_ERROR_WANT_WRITE ) {
2296
+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
2295
2297
sockstate = PySSL_select (sock , 1 , timeout );
2296
2298
} else {
2297
2299
sockstate = SOCKET_OPERATION_OK ;
@@ -2308,7 +2310,8 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2308
2310
} else if (sockstate == SOCKET_IS_NONBLOCKING ) {
2309
2311
break ;
2310
2312
}
2311
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE );
2313
+ } while (err .ssl == SSL_ERROR_WANT_READ ||
2314
+ err .ssl == SSL_ERROR_WANT_WRITE );
2312
2315
2313
2316
Py_XDECREF (sock );
2314
2317
if (len > 0 )
@@ -2332,11 +2335,14 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
2332
2335
/*[clinic end generated code: output=983d9fecdc308a83 input=2b77487d6dfd597f]*/
2333
2336
{
2334
2337
int count = 0 ;
2338
+ _PySSLError err ;
2335
2339
2336
2340
PySSL_BEGIN_ALLOW_THREADS
2337
2341
count = SSL_pending (self -> ssl );
2338
- _PySSL_UPDATE_ERRNO_IF (count < 0 , self , count );
2342
+ err = _PySSL_errno (count < 0 , self -> ssl , count );
2339
2343
PySSL_END_ALLOW_THREADS
2344
+ self -> err = err ;
2345
+
2340
2346
if (count < 0 )
2341
2347
return PySSL_SetError (self , count , __FILE__ , __LINE__ );
2342
2348
else
@@ -2363,7 +2369,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
2363
2369
char * mem ;
2364
2370
int count ;
2365
2371
int sockstate ;
2366
- int err ;
2372
+ _PySSLError err ;
2367
2373
int nonblocking ;
2368
2374
PySocketSockObject * sock = GET_SOCKET (self );
2369
2375
_PyTime_t timeout , deadline = 0 ;
@@ -2424,21 +2430,21 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
2424
2430
do {
2425
2431
PySSL_BEGIN_ALLOW_THREADS
2426
2432
count = SSL_read (self -> ssl , mem , len );
2427
- _PySSL_UPDATE_ERRNO_IF (count <= 0 , self , count );
2433
+ err = _PySSL_errno (count <= 0 , self -> ssl , count );
2428
2434
PySSL_END_ALLOW_THREADS
2435
+ self -> err = err ;
2429
2436
2430
2437
if (PyErr_CheckSignals ())
2431
2438
goto error ;
2432
2439
2433
2440
if (has_timeout )
2434
2441
timeout = deadline - _PyTime_GetMonotonicClock ();
2435
2442
2436
- err = self -> ssl_errno ;
2437
- if (err == SSL_ERROR_WANT_READ ) {
2443
+ if (err .ssl == SSL_ERROR_WANT_READ ) {
2438
2444
sockstate = PySSL_select (sock , 0 , timeout );
2439
- } else if (err == SSL_ERROR_WANT_WRITE ) {
2445
+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
2440
2446
sockstate = PySSL_select (sock , 1 , timeout );
2441
- } else if (err == SSL_ERROR_ZERO_RETURN &&
2447
+ } else if (err . ssl == SSL_ERROR_ZERO_RETURN &&
2442
2448
SSL_get_shutdown (self -> ssl ) == SSL_RECEIVED_SHUTDOWN )
2443
2449
{
2444
2450
count = 0 ;
@@ -2454,7 +2460,8 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
2454
2460
} else if (sockstate == SOCKET_IS_NONBLOCKING ) {
2455
2461
break ;
2456
2462
}
2457
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE );
2463
+ } while (err .ssl == SSL_ERROR_WANT_READ ||
2464
+ err .ssl == SSL_ERROR_WANT_WRITE );
2458
2465
2459
2466
if (count <= 0 ) {
2460
2467
PySSL_SetError (self , count , __FILE__ , __LINE__ );
@@ -2488,7 +2495,8 @@ static PyObject *
2488
2495
_ssl__SSLSocket_shutdown_impl (PySSLSocket * self )
2489
2496
/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=11d39e69b0a2bf4a]*/
2490
2497
{
2491
- int err , sockstate , nonblocking ;
2498
+ _PySSLError err ;
2499
+ int sockstate , nonblocking , ret ;
2492
2500
int zeros = 0 ;
2493
2501
PySocketSockObject * sock = GET_SOCKET (self );
2494
2502
_PyTime_t timeout , deadline = 0 ;
@@ -2526,14 +2534,15 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2526
2534
*/
2527
2535
if (self -> shutdown_seen_zero )
2528
2536
SSL_set_read_ahead (self - > ssl , 0 );
2529
- err = SSL_shutdown (self -> ssl );
2530
- _PySSL_UPDATE_ERRNO_IF ( err < 0 , self , err );
2537
+ ret = SSL_shutdown (self -> ssl );
2538
+ err = _PySSL_errno ( ret < 0 , self -> ssl , ret );
2531
2539
PySSL_END_ALLOW_THREADS
2540
+ self -> err = err ;
2532
2541
2533
2542
/* If err == 1, a secure shutdown with SSL_shutdown() is complete */
2534
- if (err > 0 )
2543
+ if (ret > 0 )
2535
2544
break ;
2536
- if (err == 0 ) {
2545
+ if (ret == 0 ) {
2537
2546
/* Don't loop endlessly; instead preserve legacy
2538
2547
behaviour of trying SSL_shutdown() only twice.
2539
2548
This looks necessary for OpenSSL < 0.9.8m */
@@ -2548,16 +2557,15 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2548
2557
timeout = deadline - _PyTime_GetMonotonicClock ();
2549
2558
2550
2559
/* Possibly retry shutdown until timeout or failure */
2551
- _PySSL_UPDATE_ERRNO (self , err );
2552
- if (self -> ssl_errno == SSL_ERROR_WANT_READ )
2560
+ if (err .ssl == SSL_ERROR_WANT_READ )
2553
2561
sockstate = PySSL_select (sock , 0 , timeout );
2554
- else if (self -> ssl_errno == SSL_ERROR_WANT_WRITE )
2562
+ else if (err . ssl == SSL_ERROR_WANT_WRITE )
2555
2563
sockstate = PySSL_select (sock , 1 , timeout );
2556
2564
else
2557
2565
break ;
2558
2566
2559
2567
if (sockstate == SOCKET_HAS_TIMED_OUT ) {
2560
- if (self -> ssl_errno == SSL_ERROR_WANT_READ )
2568
+ if (err . ssl == SSL_ERROR_WANT_READ )
2561
2569
PyErr_SetString (PySocketModule .timeout_error ,
2562
2570
"The read operation timed out" );
2563
2571
else
@@ -2575,9 +2583,9 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2575
2583
break ;
2576
2584
}
2577
2585
2578
- if (err < 0 ) {
2586
+ if (err . ssl < 0 ) {
2579
2587
Py_XDECREF (sock );
2580
- return PySSL_SetError (self , err , __FILE__ , __LINE__ );
2588
+ return PySSL_SetError (self , err . ssl , __FILE__ , __LINE__ );
2581
2589
}
2582
2590
if (sock )
2583
2591
/* It's already INCREF'ed */
0 commit comments