]> granicus.if.org Git - python/commitdiff
Issue #19095: SSLSocket.getpeercert() now raises ValueError when the SSL handshake...
authorAntoine Pitrou <solipsis@pitrou.net>
Sun, 29 Sep 2013 17:50:53 +0000 (19:50 +0200)
committerAntoine Pitrou <solipsis@pitrou.net>
Sun, 29 Sep 2013 17:50:53 +0000 (19:50 +0200)
Doc/library/ssl.rst
Lib/test/test_ssl.py
Misc/NEWS
Modules/_ssl.c

index 983c144c1eb7492d4ee4f1f7fef1f82f802d31a9..bb4cecad57fb38dcd25b127692074dec3b3e69aa 100644 (file)
@@ -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
index 89153052131bf760280e07cf4000454f1d95964b..2605e68cceda24af37b402c2cf49add0891d4e7f 100644 (file)
@@ -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()
index 6c17c04800f82d952ef5636a62c3b3bc02009e72..48851db01fdf0e4352b20815169ba3f85a030b04 100644 (file)
--- 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.
 
index e116d3dd4d782be2e4933a34f5c57f9e5591b6ed..3afe89308e4e7ca42a9379bdb4c8ddca57415d34 100644 (file)
@@ -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;