diff options
author | Christian Heimes <christian@python.org> | 2017-09-05 20:43:05 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-05 20:43:05 (GMT) |
commit | 63b3f2b19cc96801c3b8619e4cf8aa9028e7a33c (patch) | |
tree | 2e27789a66a12671ebdbf2b3c0cd99909ca67a33 /Modules | |
parent | f201e886fc7aaeb50f5e945578c6aec2a59a5323 (diff) | |
download | cpython-63b3f2b19cc96801c3b8619e4cf8aa9028e7a33c.zip cpython-63b3f2b19cc96801c3b8619e4cf8aa9028e7a33c.tar.gz cpython-63b3f2b19cc96801c3b8619e4cf8aa9028e7a33c.tar.bz2 |
[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 <christian@python.org>.
(cherry picked from commit 66dc33b6822be93f85d84d24d3f9159ff568fbbb)
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ssl.c | 33 |
1 files changed, 12 insertions, 21 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 9429c80..b5eab0f 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -298,9 +298,7 @@ typedef struct { PyObject *Socket; /* weakref to socket on which we're layered */ SSL *ssl; PySSLContext *ctx; /* weakref to SSL context */ - X509 *peer_cert; char shutdown_seen_zero; - char handshake_done; enum py_ssl_server_or_client socket_type; PyObject *owner; /* Python level "owner" passed to servername callback */ PyObject *server_hostname; @@ -595,13 +593,11 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, if (self == NULL) return NULL; - self->peer_cert = NULL; self->ssl = NULL; self->Socket = NULL; self->ctx = sslctx; Py_INCREF(sslctx); self->shutdown_seen_zero = 0; - self->handshake_done = 0; self->owner = NULL; self->server_hostname = NULL; if (server_hostname != NULL) { @@ -747,15 +743,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self) if (ret < 1) return PySSL_SetError(self, ret, __FILE__, __LINE__); - if (self->peer_cert) - X509_free (self->peer_cert); - PySSL_BEGIN_ALLOW_THREADS - self->peer_cert = SSL_get_peer_certificate(self->ssl); - PySSL_END_ALLOW_THREADS - self->handshake_done = 1; - - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; error: Py_XDECREF(sock); @@ -1521,25 +1509,30 @@ _ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode) /*[clinic end generated code: output=f0dc3e4d1d818a1d input=8281bd1d193db843]*/ { int verification; + X509 *peer_cert; + PyObject *result; - if (!self->handshake_done) { + if (!SSL_is_init_finished(self->ssl)) { PyErr_SetString(PyExc_ValueError, "handshake not done yet"); return NULL; } - if (!self->peer_cert) + peer_cert = SSL_get_peer_certificate(self->ssl); + if (peer_cert == NULL) Py_RETURN_NONE; if (binary_mode) { /* return cert in DER-encoded format */ - return _certificate_to_der(self->peer_cert); + result = _certificate_to_der(peer_cert); } else { verification = SSL_CTX_get_verify_mode(SSL_get_SSL_CTX(self->ssl)); if ((verification & SSL_VERIFY_PEER) == 0) - return PyDict_New(); + result = PyDict_New(); else - return _decode_certificate(self->peer_cert); + result = _decode_certificate(peer_cert); } + X509_free(peer_cert); + return result; } static PyObject * @@ -1860,8 +1853,6 @@ Passed as \"self\" in servername callback."); static void PySSL_dealloc(PySSLSocket *self) { - if (self->peer_cert) /* Possible not to have one? */ - X509_free (self->peer_cert); if (self->ssl) SSL_free(self->ssl); Py_XDECREF(self->Socket); @@ -2457,7 +2448,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value, "Cannot set session for server-side SSLSocket."); return -1; } - if (self->handshake_done) { + if (SSL_is_init_finished(self->ssl)) { PyErr_SetString(PyExc_ValueError, "Cannot set session after handshake."); return -1; |