Skip to content

Commit 63b3f2b

Browse files
authored
[3.6] bpo-29334: Fix ssl.getpeercert for auto-handshake (GH-1769) (#1778)
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 f201e88 commit 63b3f2b

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);
@@ -1521,25 +1509,30 @@ _ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode)
15211509
/*[clinic end generated code: output=f0dc3e4d1d818a1d input=8281bd1d193db843]*/
15221510
{
15231511
int verification;
1512+
X509 *peer_cert;
1513+
PyObject *result;
15241514

1525-
if (!self->handshake_done) {
1515+
if (!SSL_is_init_finished(self->ssl)) {
15261516
PyErr_SetString(PyExc_ValueError,
15271517
"handshake not done yet");
15281518
return NULL;
15291519
}
1530-
if (!self->peer_cert)
1520+
peer_cert = SSL_get_peer_certificate(self->ssl);
1521+
if (peer_cert == NULL)
15311522
Py_RETURN_NONE;
15321523

15331524
if (binary_mode) {
15341525
/* return cert in DER-encoded format */
1535-
return _certificate_to_der(self->peer_cert);
1526+
result = _certificate_to_der(peer_cert);
15361527
} else {
15371528
verification = SSL_CTX_get_verify_mode(SSL_get_SSL_CTX(self->ssl));
15381529
if ((verification & SSL_VERIFY_PEER) == 0)
1539-
return PyDict_New();
1530+
result = PyDict_New();
15401531
else
1541-
return _decode_certificate(self->peer_cert);
1532+
result = _decode_certificate(peer_cert);
15421533
}
1534+
X509_free(peer_cert);
1535+
return result;
15431536
}
15441537

15451538
static PyObject *
@@ -1860,8 +1853,6 @@ Passed as \"self\" in servername callback.");
18601853

18611854
static void PySSL_dealloc(PySSLSocket *self)
18621855
{
1863-
if (self->peer_cert) /* Possible not to have one? */
1864-
X509_free (self->peer_cert);
18651856
if (self->ssl)
18661857
SSL_free(self->ssl);
18671858
Py_XDECREF(self->Socket);
@@ -2457,7 +2448,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value,
24572448
"Cannot set session for server-side SSLSocket.");
24582449
return -1;
24592450
}
2460-
if (self->handshake_done) {
2451+
if (SSL_is_init_finished(self->ssl)) {
24612452
PyErr_SetString(PyExc_ValueError,
24622453
"Cannot set session after handshake.");
24632454
return -1;

0 commit comments

Comments
 (0)