Kaydet (Commit) 20b85557 authored tarafından Antoine Pitrou's avatar Antoine Pitrou

Issue #19095: SSLSocket.getpeercert() now raises ValueError when the SSL…

Issue #19095: SSLSocket.getpeercert() now raises ValueError when the SSL handshake hasn't been done.
üst cf892ace
...@@ -659,7 +659,8 @@ SSL sockets also have the following additional methods and attributes: ...@@ -659,7 +659,8 @@ SSL sockets also have the following additional methods and attributes:
.. method:: SSLSocket.getpeercert(binary_form=False) .. method:: SSLSocket.getpeercert(binary_form=False)
If there is no certificate for the peer on the other end of the connection, 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 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 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: ...@@ -716,6 +717,9 @@ SSL sockets also have the following additional methods and attributes:
The returned dictionary includes additional items such as ``issuer`` The returned dictionary includes additional items such as ``issuer``
and ``notBefore``. and ``notBefore``.
.. versionchanged:: 3.4
:exc:`ValueError` is raised when the handshake isn't done.
.. method:: SSLSocket.cipher() .. method:: SSLSocket.cipher()
Returns a three-value tuple containing the name of the cipher being used, the Returns a three-value tuple containing the name of the cipher being used, the
......
...@@ -1588,8 +1588,14 @@ else: ...@@ -1588,8 +1588,14 @@ else:
context.load_cert_chain(CERTFILE) context.load_cert_chain(CERTFILE)
server = ThreadedEchoServer(context=context, chatty=False) server = ThreadedEchoServer(context=context, chatty=False)
with server: with server:
s = context.wrap_socket(socket.socket()) s = context.wrap_socket(socket.socket(),
do_handshake_on_connect=False)
s.connect((HOST, server.port)) 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() cert = s.getpeercert()
self.assertTrue(cert, "Can't get peer certificate.") self.assertTrue(cert, "Can't get peer certificate.")
cipher = s.cipher() cipher = s.cipher()
......
...@@ -15,6 +15,9 @@ Core and Builtins ...@@ -15,6 +15,9 @@ Core and Builtins
Library 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 - Issue #4366: Fix building extensions on all platforms when --enable-shared
is used. is used.
......
...@@ -220,7 +220,8 @@ typedef struct { ...@@ -220,7 +220,8 @@ typedef struct {
SSL *ssl; SSL *ssl;
PySSLContext *ctx; /* weakref to SSL context */ PySSLContext *ctx; /* weakref to SSL context */
X509 *peer_cert; X509 *peer_cert;
int shutdown_seen_zero; char shutdown_seen_zero;
char handshake_done;
enum py_ssl_server_or_client socket_type; enum py_ssl_server_or_client socket_type;
} PySSLSocket; } PySSLSocket;
...@@ -485,6 +486,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, ...@@ -485,6 +486,7 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
self->ssl = NULL; self->ssl = NULL;
self->Socket = NULL; self->Socket = NULL;
self->ctx = sslctx; self->ctx = sslctx;
self->handshake_done = 0;
Py_INCREF(sslctx); Py_INCREF(sslctx);
/* Make sure the SSL error state is initialized */ /* Make sure the SSL error state is initialized */
...@@ -590,6 +592,7 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self) ...@@ -590,6 +592,7 @@ static PyObject *PySSL_SSLdo_handshake(PySSLSocket *self)
PySSL_BEGIN_ALLOW_THREADS PySSL_BEGIN_ALLOW_THREADS
self->peer_cert = SSL_get_peer_certificate(self->ssl); self->peer_cert = SSL_get_peer_certificate(self->ssl);
PySSL_END_ALLOW_THREADS PySSL_END_ALLOW_THREADS
self->handshake_done = 1;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
...@@ -1153,6 +1156,11 @@ PySSL_peercert(PySSLSocket *self, PyObject *args) ...@@ -1153,6 +1156,11 @@ PySSL_peercert(PySSLSocket *self, PyObject *args)
if (!PyArg_ParseTuple(args, "|p:peer_certificate", &binary_mode)) if (!PyArg_ParseTuple(args, "|p:peer_certificate", &binary_mode))
return NULL; return NULL;
if (!self->handshake_done) {
PyErr_SetString(PyExc_ValueError,
"handshake not done yet");
return NULL;
}
if (!self->peer_cert) if (!self->peer_cert)
Py_RETURN_NONE; Py_RETURN_NONE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment