@@ -325,6 +325,14 @@ typedef struct {
325
325
int check_hostname ;
326
326
} PySSLContext ;
327
327
328
+ typedef struct {
329
+ int ssl ; /* last seen error from SSL */
330
+ int c ; /* last seen error from libc */
331
+ #ifdef MS_WINDOWS
332
+ int ws ; /* last seen error from winsock */
333
+ #endif
334
+ } _PySSLError ;
335
+
328
336
typedef struct {
329
337
PyObject_HEAD
330
338
PyObject * Socket ; /* weakref to socket on which we're layered */
@@ -334,11 +342,7 @@ typedef struct {
334
342
enum py_ssl_server_or_client socket_type ;
335
343
PyObject * owner ; /* Python level "owner" passed to servername callback */
336
344
PyObject * server_hostname ;
337
- int ssl_errno ; /* last seen error from SSL */
338
- int c_errno ; /* last seen error from libc */
339
- #ifdef MS_WINDOWS
340
- int ws_errno ; /* last seen error from winsock */
341
- #endif
345
+ _PySSLError err ; /* last seen error from various sources */
342
346
} PySSLSocket ;
343
347
344
348
typedef struct {
@@ -358,19 +362,18 @@ static PyTypeObject PySSLSocket_Type;
358
362
static PyTypeObject PySSLMemoryBIO_Type ;
359
363
static PyTypeObject PySSLSession_Type ;
360
364
365
+ static inline _PySSLError _PySSL_errno (int failed , const SSL * ssl , int retcode )
366
+ {
367
+ _PySSLError err = { 0 };
368
+ if (failed ) {
361
369
#ifdef MS_WINDOWS
362
- #define _PySSL_UPDATE_ERRNO_IF (cond , sock , retcode ) if (cond) { \
363
- (sock)->ws_errno = WSAGetLastError(); \
364
- (sock)->c_errno = errno; \
365
- (sock)->ssl_errno = SSL_get_error((sock->ssl), (retcode)); \
366
- } else { sock->ws_errno = 0; sock->c_errno = 0; sock->ssl_errno = 0; }
367
- #else
368
- #define _PySSL_UPDATE_ERRNO_IF (cond , sock , retcode ) if (cond) { \
369
- (sock)->c_errno = errno; \
370
- (sock)->ssl_errno = SSL_get_error((sock->ssl), (retcode)); \
371
- } else { (sock)->c_errno = 0; (sock)->ssl_errno = 0; }
370
+ err .ws = WSAGetLastError ();
372
371
#endif
373
- #define _PySSL_UPDATE_ERRNO (sock , retcode ) _PySSL_UPDATE_ERRNO_IF(1, (sock), (retcode))
372
+ err .c = errno ;
373
+ err .ssl = SSL_get_error (ssl , retcode );
374
+ }
375
+ return err ;
376
+ }
374
377
375
378
/*[clinic input]
376
379
module _ssl
@@ -537,17 +540,17 @@ PySSL_SetError(PySSLSocket *obj, int ret, const char *filename, int lineno)
537
540
{
538
541
PyObject * type = PySSLErrorObject ;
539
542
char * errstr = NULL ;
540
- int err ;
543
+ _PySSLError err ;
541
544
enum py_ssl_error p = PY_SSL_ERROR_NONE ;
542
545
unsigned long e = 0 ;
543
546
544
547
assert (ret <= 0 );
545
548
e = ERR_peek_last_error ();
546
549
547
550
if (obj -> ssl != NULL ) {
548
- err = obj -> ssl_errno ;
551
+ err = obj -> err ;
549
552
550
- switch (err ) {
553
+ switch (err . ssl ) {
551
554
case SSL_ERROR_ZERO_RETURN :
F438
code>
552
555
errstr = "TLS/SSL connection has been closed (EOF)" ;
553
556
type = PySSLZeroReturnErrorObject ;
@@ -583,11 +586,12 @@ PySSL_SetError(PySSLSocket *obj, int ret, const char *filename, int lineno)
583
586
/* underlying BIO reported an I/O error */
584
587
ERR_clear_error ();
585
588
#ifdef MS_WINDOWS
586
- if (obj -> ws_errno )
587
- return PyErr_SetFromWindowsErr (obj -> ws_errno );
589
+ if (err .ws ) {
590
+ return PyErr_SetFromWindowsErr (err .ws );
591
+ }
588
592
#endif
589
- if (obj -> c_errno ) {
590
- errno = obj -> c_errno ;
593
+ if (err . c ) {
594
+ errno = err . c ;
591
595
return PyErr_SetFromErrno (PyExc_OSError );
592
596
}
593
597
Py_INCREF (s );
@@ -647,6 +651,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
647
651
PySSLSocket * self ;
648
652
SSL_CTX * ctx = sslctx -> ctx ;
649
653
long mode ;
654
+ _PySSLError err = { 0 };
650
655
651
656
self = PyObject_New (PySSLSocket , & PySSLSocket_Type );
652
657
if (self == NULL )
@@ -668,11 +673,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
668
673
}
669
674
self -> server_hostname = hostname ;
670
675
}
671
- self -> ssl_errno = 0 ;
672
- self -> c_errno = 0 ;
673
- #ifdef MS_WINDOWS
674
- self -> ws_errno = 0 ;
675
- #endif
676
+ self -> err = err ;
676
677
677
678
/* Make sure the SSL error state is initialized */
678
679
(void ) ERR_get_state ();
@@ -773,7 +774,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
773
774
/*[clinic end generated code: output=6c0898a8936548f6 input=d2d737de3df018c8]*/
774
775
{
775
776
int ret ;
776
- int err ;
777
+ _PySSLError err ;
777
778
int sockstate , nonblocking ;
778
779
PySocketSockObject * sock = GET_SOCKET (self );
779
780
_PyTime_t timeout , deadline = 0 ;
@@ -803,19 +804,19 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
803
804
do {
804
805
PySSL_BEGIN_ALLOW_THREADS
805
806
ret = SSL_do_handshake (self -> ssl );
806
- _PySSL_UPDATE_ERRNO_IF (ret < 1 , self , ret );
807
+ err = _PySSL_errno (ret < 1 , self -> ssl , ret );
807
808
PySSL_END_ALLOW_THREADS
808
- err = self -> ssl_errno ;
809
+ self -> err = err ;
809
810
810
811
if (PyErr_CheckSignals ())
811
812
goto error ;
812
813
813
814
if (has_timeout )
814
815
timeout = deadline - _PyTime_GetMonotonicClock ();
815
816
816
- if (err == SSL_ERROR_WANT_READ ) {
817
+ if (err . ssl == SSL_ERROR_WANT_READ ) {
817
818
sockstate = PySSL_select (sock , 0 , timeout );
818
- } else if (err == SSL_ERROR_WANT_WRITE ) {
819
+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
819
820
sockstate = PySSL_select (sock , 1 , timeout );
820
821
} else {
821
822
sockstate = SOCKET_OPERATION_OK ;
@@ -836,7 +837,8 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
836
837
} else if (sockstate == SOCKET_IS_NONBLOCKING ) {
837
838
break ;
838
839
}
839
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE );
840
+ } while (err .ssl == SSL_ERROR_WANT_READ ||
841
+ err .ssl == SSL_ERROR_WANT_WRITE );
840
842
Py_XDECREF (sock );
841
843
if (ret < 1 )
842
844
return PySSL_SetError (self , ret , __FILE__ , __LINE__ );
@@ -2050,7 +2052,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2050
2052
{
2051
2053
int len ;
2052
2054
int sockstate ;
2053
- int err ;
2055
+ _PySSLError err ;
2054
2056
int nonblocking ;
2055
2057
PySocketSockObject * sock = GET_SOCKET (self );
2056
2058
_PyTime_t timeout , deadline = 0 ;
@@ -2101,19 +2103,19 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2101
2103
do {
2102
2104
PySSL_BEGIN_ALLOW_THREADS
2103
2105
len = SSL_write (self -> ssl , b -> buf , (int )b -> len );
2104
- _PySSL_UPDATE_ERRNO_IF (len <= 0 , self , len );
2106
+ err = _PySSL_errno (len <= 0 , self -> ssl , len );
2105
2107
PySSL_END_ALLOW_THREADS
2106
- err = self -> ssl_errno ;
2108
+ self -> err = err ;
2107
2109
2108
2110
if (PyErr_CheckSignals ())
2109
2111
goto error ;
2110
2112
2111
2113
if (has_timeout )
2112
2114
timeout = deadline - _PyTime_GetMonotonicClock ();
2113
2115
2114
- if (err == SSL_ERROR_WANT_READ ) {
2116
+ if (err . ssl == SSL_ERROR_WANT_READ ) {
2115
2117
sockstate = PySSL_select (sock , 0 , timeout );
2116
- } else if (err == SSL_ERROR_WANT_WRITE ) {
2118
+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
2117
2119
sockstate = PySSL_select (sock , 1 , timeout );
2118
2120
} else {
2119
2121
sockstate = SOCKET_OPERATION_OK ;
@@ -2130,7 +2132,8 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b)
2130
2132
} else if (sockstate == SOCKET_IS_NONBLOCKING ) {
2131
2133
break ;
2132
2134
}
2133
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE );
2135
+ } while (err .ssl == SSL_ERROR_WANT_READ ||
2136
+ err .ssl == SSL_ERROR_WANT_WRITE );
2134
2137
2135
2138
Py_XDECREF (sock );
2136
2139
if (len > 0 )
@@ -2154,11 +2157,14 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self)
2154
2157
/*[clinic end generated code: output=983d9fecdc308a83 input=2b77487d6dfd597f]*/
2155
2158
{
2156
2159
int count = 0 ;
2160
+ _PySSLError err ;
2157
2161
2158
2162
PySSL_BEGIN_ALLOW_THREADS
2159
2163
count = SSL_pending (self -> ssl );
2160
- _PySSL_UPDATE_ERRNO_IF (count < 0 , self , count );
2164
+ err = _PySSL_errno (count < 0 , self -> ssl , count );
2161
2165
PySSL_END_ALLOW_THREADS
2166
+ self -> err = err ;
2167
+
2162
2168
if (count < 0 )
2163
2169
return PySSL_SetError (self , count , __FILE__ , __LINE__ );
2164
2170
else
@@ -2185,7 +2191,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
2185
2191
char * mem ;
2186
2192
int count ;
2187
2193
int sockstate ;
2188
- int err ;
2194
+ _PySSLError err ;
2189
2195
int nonblocking ;
2190
2196
PySocketSockObject * sock = GET_SOCKET (self );
2191
2197
_PyTime_t timeout , deadline = 0 ;
@@ -2246,21 +2252,21 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
2246
2252
do {
2247
2253
PySSL_BEGIN_ALLOW_THREADS
2248
2254
count = SSL_read (self -> ssl , mem , len );
2249
- _PySSL_UPDATE_ERRNO_IF (count <= 0 , self , count );
2255
+ err = _PySSL_errno (count <= 0 , self -> ssl , count );
2250
2256
PySSL_END_ALLOW_THREADS
2257
+ self -> err = err ;
2251
2258
2252
2259
if (PyErr_CheckSignals ())
2253
2260
goto error ;
2254
2261
2255
2262
if (has_timeout )
2256
2263
timeout = deadline - _PyTime_GetMonotonicClock ();
2257
2264
2258
- err = self -> ssl_errno ;
2259
- if (err == SSL_ERROR_WANT_READ ) {
2265
+ if (err .ssl == SSL_ERROR_WANT_READ ) {
2260
2266
sockstate = PySSL_select (sock , 0 , timeout );
2261
- } else if (err == SSL_ERROR_WANT_WRITE ) {
2267
+ } else if (err . ssl == SSL_ERROR_WANT_WRITE ) {
2262
2268
sockstate = PySSL_select (sock , 1 , timeout );
2263
- } else if (err == SSL_ERROR_ZERO_RETURN &&
2269
+ } else if (err . ssl == SSL_ERROR_ZERO_RETURN &&
2264
2270
SSL_get_shutdown (self -> ssl ) == SSL_RECEIVED_SHUTDOWN )
2265
2271
{
2266
2272
count = 0 ;
@@ -2276,7 +2282,8 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1,
2276
2282
} else if (sockstate == SOCKET_IS_NONBLOCKING ) {
2277
2283
break ;
2278
2284
}
2279
- } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE );
2285
+ } while (err .ssl == SSL_ERROR_WANT_READ ||
2286
+ err .ssl == SSL_ERROR_WANT_WRITE );
2280
2287
2281
2288
if (count <= 0 ) {
2282
2289
PySSL_SetError (self , count , __FILE__ , __LINE__ );
@@ -2312,7 +2319,8 @@ static PyObject *
2312
2319
_ssl__SSLSocket_shutdown_impl (PySSLSocket * self )
2313
2320
/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=ede2cc1a2ddf0ee4]*/
2314
2321
{
2315
- int err , sockstate , nonblocking ;
2322
+ _PySSLError err ;
2323
+ int sockstate , nonblocking , ret ;
2316
2324
int zeros = 0 ;
2317
2325
PySocketSockObject * sock = GET_SOCKET (self );
2318
2326
_PyTime_t timeout , deadline = 0 ;
@@ -2350,14 +2358,15 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2350
2358
*/
2351
2359
if (self -> shutdown_seen_zero )
2352
2360
SSL_set_read_ahead (self - > ssl , 0 );
2353
- err = SSL_shutdown (self -> ssl );
2354
- _PySSL_UPDATE_ERRNO_IF ( err < 0 , self , err );
2361
+ ret = SSL_shutdown (self -> ssl );
2362
+ err = _PySSL_errno ( ret < 0 , self -> ssl , ret );
2355
2363
PySSL_END_ALLOW_THREADS
2364
+ self -> err = err ;
2356
2365
2357
2366
/* If err == 1, a secure shutdown with SSL_shutdown() is complete */
2358
- if (err > 0 )
2367
+ if (ret > 0 )
2359
2368
break ;
2360
- if (err == 0 ) {
2369
+ if (ret == 0 ) {
2361
2370
/* Don't loop endlessly; instead preserve legacy
2362
2371
behaviour of trying SSL_shutdown() only twice.
2363
2372
This looks necessary for OpenSSL < 0.9.8m */
@@ -2372,16 +2381,15 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2372
2381
timeout = deadline - _PyTime_GetMonotonicClock ();
2373
2382
2374
2383
/* Possibly retry shutdown until timeout or failure */
2375
- _PySSL_UPDATE_ERRNO (self , err );
2376
- if (self -> ssl_errno == SSL_ERROR_WANT_READ )
2384
+ if (err .ssl == SSL_ERROR_WANT_READ )
2377
2385
sockstate = PySSL_select (sock , 0 , timeout );
2378
- else if (self -> ssl_errno == SSL_ERROR_WANT_WRITE )
2386
+ else if (err . ssl == SSL_ERROR_WANT_WRITE )
2379
2387
sockstate = PySSL_select (sock , 1 , timeout );
2380
2388
else
2381
2389
break ;
2382
2390
2383
2391
if (sockstate == SOCKET_HAS_TIMED_OUT ) {
2384
- if (self -> ssl_errno == SSL_ERROR_WANT_READ )
2392
+ if (err . ssl == SSL_ERROR_WANT_READ )
2385
2393
PyErr_SetString (PySocketModule .timeout_error ,
2386
2394
"The read operation timed out" );
2387
2395
else
@@ -2399,9 +2407,9 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self)
2399
2407
break ;
2400
2408
}
2401
2409
2402
- if (err < 0 ) {
2410
+ if (err . ssl < 0 ) {
2403
2411
Py_XDECREF (sock );
2404
- return PySSL_SetError (self , err , __FILE__ , __LINE__ );
2412
+ return PySSL_SetError (self , err . ssl , __FILE__ , __LINE__ );
2405
2413
}
2406
2414
if (sock )
2407
2415
/* It's already INCREF'ed */
0 commit comments