From: Antoine Pitrou Date: Sun, 29 Sep 2013 17:50:53 +0000 (+0200) Subject: Issue #19095: SSLSocket.getpeercert() now raises ValueError when the SSL handshake... X-Git-Tag: v3.4.0a4~311^2~6 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=20b85557f2cc8f5f10d7d98314a3181c60553e12;p=python Issue #19095: SSLSocket.getpeercert() now raises ValueError when the SSL handshake hasn't been done. --- diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 983c144c1e..bb4cecad57 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -659,7 +659,8 @@ SSL sockets also have the following additional methods and attributes: .. method:: SSLSocket.getpeercert(binary_form=False) If there is no certificate for the peer on the other end of the connection, - returns ``None``. + return ``None``. If the SSL handshake hasn't been done yet, raise + :exc:`ValueError`. If the ``binary_form`` parameter is :const:`False`, and a certificate was received from the peer, this method returns a :class:`dict` instance. If the @@ -716,6 +717,9 @@ SSL sockets also have the following additional methods and attributes: The returned dictionary includes additional items such as ``issuer`` and ``notBefore``. + .. versionchanged:: 3.4 + :exc:`ValueError` is raised when the handshake isn't done. + .. method:: SSLSocket.cipher() Returns a three-value tuple containing the name of the cipher being used, the diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 8915305213..2605e68cce 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1588,8 +1588,14 @@ else: context.load_cert_chain(CERTFILE) server = ThreadedEchoServer(context=context, chatty=False) with server: - s = context.wrap_socket(socket.socket()) + s = context.wrap_socket(socket.socket(), + do_handshake_on_connect=False) s.connect((HOST, server.port)) + # getpeercert() raise ValueError while the handshake isn't + # done. + with self.assertRaises(ValueError): + s.getpeercert() + s.do_handshake() cert = s.getpeercert() self.assertTrue(cert, "Can't get peer certificate.") cipher = s.cipher() diff --git a/Misc/NEWS b/Misc/NEWS index 6c17c04800..48851db01f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Core and Builtins Library ------- +- Issue #19095: SSLSocket.getpeercert() now raises ValueError when the + SSL handshake hasn't been done. + - Issue #4366: Fix building extensions on all platforms when --enable-shared is used. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index e116d3dd4d..3afe89308e 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -220,7 +220,8 @@ typedef struct { SSL *ssl; PySSLContext *ctx; /* weakref to SSL context */ X509 *peer_cert; - int shutdown_seen_zero; + char shutdown_seen_zero; + char handshake_done; enum py_ssl_server_or_client socket_type; } PySSLSocket; @@ -485,6 +486,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, self->ssl = NULL; self->Socket = NULL; self->ctx = sslctx; + self->handshake_done = 0; Py_INCREF(sslctx); /* Make sure the SSL error state is initialized */ @@ -590,6 +592,7 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self) 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; @@ -1153,6 +1156,11 @@ PySSL_peercert(PySSLSocket *self, PyObject *args) if (!PyArg_ParseTuple(args, "|p:peer_certificate", &binary_mode)) return NULL; + if (!self->handshake_done) { + PyErr_SetString(PyExc_ValueError, + "handshake not done yet"); + return NULL; + } if (!self->peer_cert) Py_RETURN_NONE;