summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorChristian Heimes <christian@python.org>2017-09-05 20:43:05 (GMT)
committerGitHub <noreply@github.com>2017-09-05 20:43:05 (GMT)
commit63b3f2b19cc96801c3b8619e4cf8aa9028e7a33c (patch)
tree2e27789a66a12671ebdbf2b3c0cd99909ca67a33 /Modules
parentf201e886fc7aaeb50f5e945578c6aec2a59a5323 (diff)
downloadcpython-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.c33
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;