Skip to content

Commit ed00fc4

Browse files
committed
[3.6] bpo-29334: Fix ssl.getpeercert for auto-handshake (GH-1769)
Drop handshake_done and peer_cert members from PySSLSocket struct. The peer certificate can be acquired from *SSL directly. SSL_get_peer_certificate() does not trigger any network activity. Instead of manually tracking the handshake state, simply use SSL_is_init_finished(). In combination these changes fix auto-handshake for non-blocking MemoryBIO connections. Signed-off-by: Christian Heimes <[email protected]>. (cherry picked from commit 66dc33b)
1 parent 8704d54 commit ed00fc4

File tree

1 file changed

+12
-21
lines changed

1 file changed

+12
-21
lines changed

Modules/_ssl.c

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,7 @@ typedef struct {
298298
PyObject *Socket; /* weakref to socket on which we're layered */
299299
SSL *ssl;
300300
PySSLContext *ctx; /* weakref to SSL context */
301-
X509 *peer_cert;
302301
char shutdown_seen_zero;
303-
char handshake_done;
304302
enum py_ssl_server_or_client socket_type;
305303
PyObject *owner; /* Python level "owner" passed to servername callback */
306304
PyObject *server_hostname;
@@ -595,13 +593,11 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
595593
if (self == NULL)
596594
return NULL;
597595

598-
self->peer_cert = NULL;
599596
self->ssl = NULL;
600597
self->Socket = NULL;
601598
self->ctx = sslctx;
602599
Py_INCREF(sslctx);
603600
self->shutdown_seen_zero = 0;
604-
self->handshake_done = 0;
605601
self->owner = NULL;
606602
self->server_hostname = NULL;
607603
if (server_hostname != NULL) {
@@ -747,15 +743,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self)
747743
if (ret < 1)
748744
return PySSL_SetError(self, ret, __FILE__, __LINE__);
749745

750-
if (self->peer_cert)
751-
X509_free (self->peer_cert);
752-
PySSL_BEGIN_ALLOW_THREADS
753-
self->peer_cert = SSL_get_peer_certificate(self->ssl);
754-
PySSL_END_ALLOW_THREADS
755-
self->handshake_done = 1;
756-
757-
Py_INCREF(Py_None);
758-
return Py_None;
746+
Py_RETURN_NONE;
759747

760748
error:
761749
Py_XDECREF(sock);
@@ -1506,25 +1494,30 @@ _ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode)
15061494
/*[clinic end generated code: output=f0dc3e4d1d818a1d input=8281bd1d193db843]*/
15071495
{
15081496
int verification;
1497+
X509 *peer_cert;
1498+
PyObject *result;
15091499

1510-
if (!self->handshake_done) {
1500+
if (!SSL_is_init_finished(self->ssl)) {
15111501
PyErr_SetString(PyExc_ValueError,
15121502
"handshake not done yet");
15131503
return NULL;
15141504
}
1515-
if (!self->peer_cert)
1505+
peer_cert = SSL_get_peer_certificate(self->ssl);
1506+
if (peer_cert == NULL)
15161507
Py_RETURN_NONE;
15171508

15181509
if (binary_mode) {
15191510
/* return cert in DER-encoded format */
1520-
return _certificate_to_der(self->peer_cert);
1511+
result = _certificate_to_der(peer_cert);
15211512
} else {
15221513
verification = SSL_CTX_get_verify_mode(SSL_get_SSL_CTX(self->ssl));
15231514
if ((verification & SSL_VERIFY_PEER) == 0)
1524-
return PyDict_New();
1515+
result = PyDict_New();
15251516
else
1526-
return _decode_certificate(self->peer_cert);
1517+
result = _decode_certificate(peer_cert);
15271518
}
1519+
X509_free(peer_cert);
1520+
return result;
15281521
}
15291522

15301523
static PyObject *
@@ -1845,8 +1838,6 @@ Passed as \"self\" in servername callback.");
18451838

18461839
static void PySSL_dealloc(PySSLSocket *self)
18471840
{
1848-
if (self->peer_cert) /* Possible not to have one? */
1849-
X509_free (self->peer_cert);
18501841
if (self->ssl)
18511842
SSL_free(self->ssl);
18521843
Py_XDECREF(self->Socket);
@@ -2442,7 +2433,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
24422433
"Cannot set session for server-side SSLSocket.");
24432434
return -1;
24442435
}
2445-
if (self->handshake_done) {
2436+
if (SSL_is_init_finished(self->ssl)) {
24462437
PyErr_SetString(PyExc_ValueError,
24472438
"Cannot set session after handshake.");
24482439
return -1;

0 commit comments

Comments
 (0)