diff options
author | Christian Heimes <christian@python.org> | 2017-05-23 23:02:02 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-23 23:02:02 (GMT) |
commit | 66dc33b6822be93f85d84d24d3f9159ff568fbbb (patch) | |
tree | 90f66c29ee79e83355a5794f5f106ee2aac84fef /Modules/_ssl.c | |
parent | e0918ecf93a458d4e005650f816d64654e73fc2a (diff) | |
download | cpython-66dc33b6822be93f85d84d24d3f9159ff568fbbb.zip cpython-66dc33b6822be93f85d84d24d3f9159ff568fbbb.tar.gz cpython-66dc33b6822be93f85d84d24d3f9159ff568fbbb.tar.bz2 |
bpo-29334: Fix ssl.getpeercert for auto-handshake (#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 <christian@python.org>
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r-- | Modules/_ssl.c | 30 |
1 files changed, 11 insertions, 19 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 68fd2dd..0fb0d88 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,12 +593,10 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, if (self == NULL) return NULL; - self->peer_cert = NULL; self->ssl = NULL; self->Socket = NULL; self->ctx = sslctx; self->shutdown_seen_zero = 0; - self->handshake_done = 0; self->owner = NULL; self->server_hostname = NULL; if (server_hostname != NULL) { @@ -748,13 +744,6 @@ _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_RETURN_NONE; error: @@ -1506,25 +1495,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 * @@ -1845,8 +1839,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); @@ -2442,7 +2434,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; |