[Python-checkins] cpython: Issue #19095: SSLSocket.getpeercert() now raises ValueError when the SSL

antoine.pitrou python-checkins at python.org
Sun Sep 29 19:51:00 CEST 2013


http://hg.python.org/cpython/rev/ddcdf7f7eac8
changeset:   85857:ddcdf7f7eac8
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Sun Sep 29 19:50:53 2013 +0200
summary:
  Issue #19095: SSLSocket.getpeercert() now raises ValueError when the SSL handshake hasn't been done.

files:
  Doc/library/ssl.rst  |   6 +++++-
  Lib/test/test_ssl.py |   8 +++++++-
  Misc/NEWS            |   3 +++
  Modules/_ssl.c       |  10 +++++++++-
  4 files changed, 24 insertions(+), 3 deletions(-)


diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -659,7 +659,8 @@
 .. 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 @@
       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
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -1588,8 +1588,14 @@
             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
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -15,6 +15,9 @@
 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
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -220,7 +220,8 @@
     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 @@
     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 @@
     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 @@
     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;
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list