[libsoup] tls-interaction: allow to pass a NULL client side certificate



commit c4165d097e84f60d0bcaf67a8bf7fc34474d02c4
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Mon Jun 14 11:38:54 2021 +0200

    tls-interaction: allow to pass a NULL client side certificate
    
    To complete the operation without providing a certificate.

 libsoup/soup-connection.c |  4 ++--
 libsoup/soup-message.c    |  9 ++++----
 tests/ssl-test.c          | 54 +++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 54 insertions(+), 13 deletions(-)
---
diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 8fb9b819..24b084f4 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -1152,7 +1152,7 @@ soup_connection_set_tls_client_certificate (SoupConnection  *conn,
 {
         SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn);
 
-        if (G_IS_TLS_CONNECTION (priv->connection)) {
+        if (G_IS_TLS_CONNECTION (priv->connection) && certificate) {
                 g_tls_connection_set_certificate (G_TLS_CONNECTION (priv->connection),
                                                   certificate);
                 g_clear_object (&priv->tls_client_cert);
@@ -1163,7 +1163,7 @@ soup_connection_set_tls_client_certificate (SoupConnection  *conn,
                 return;
 
         g_clear_object (&priv->tls_client_cert);
-        priv->tls_client_cert = g_object_ref (certificate);
+        priv->tls_client_cert = certificate ? g_object_ref (certificate) : NULL;
 }
 
 void
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index 0beae103..0f977816 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -2234,12 +2234,13 @@ soup_message_get_tls_peer_certificate_errors (SoupMessage *msg)
 /**
  * soup_message_set_tls_client_certificate:
  * @msg: a #SoupMessage
- * @certificate: the #GTlsCertificate to set
+ * @certificate: (nullable): the #GTlsCertificate to set, or %NULL
  *
  * Sets the @certificate to be used by @msg's connection when a
  * client certificate is requested during the TLS handshake.
  * You can call this as a response to #SoupMessage::request-certificate
- * signal, or before the connection is started.
+ * signal, or before the connection is started. If @certificate is %NULL
+ * the handshake will continue without providing a GTlsCertificate.
  * Note that the #GTlsCertificate set by this function will be ignored if
  * #SoupSession::tls-interaction is not %NULL.
  */
@@ -2250,7 +2251,7 @@ soup_message_set_tls_client_certificate (SoupMessage     *msg,
         SoupMessagePrivate *priv;
 
         g_return_if_fail (SOUP_IS_MESSAGE (msg));
-        g_return_if_fail (G_IS_TLS_CERTIFICATE (certificate));
+        g_return_if_fail (certificate == NULL || G_IS_TLS_CERTIFICATE (certificate));
 
         priv = soup_message_get_instance_private (msg);
         if (priv->pending_tls_cert_request) {
@@ -2271,7 +2272,7 @@ soup_message_set_tls_client_certificate (SoupMessage     *msg,
                 return;
 
         g_clear_object (&priv->tls_client_certificate);
-        priv->tls_client_certificate = g_object_ref (certificate);
+        priv->tls_client_certificate = certificate ? g_object_ref (certificate) : NULL;
 }
 
 /**
diff --git a/tests/ssl-test.c b/tests/ssl-test.c
index 47d32e26..5b41246a 100644
--- a/tests/ssl-test.c
+++ b/tests/ssl-test.c
@@ -360,6 +360,38 @@ do_tls_interaction_msg_test (gconstpointer data)
         g_bytes_unref (body);
         g_object_unref (msg);
 
+        /* Using the wrong certificate fails */
+        wrong_certificate = g_tls_certificate_new_from_files (
+                g_test_get_filename (G_TEST_DIST, "test-cert-2.pem", NULL),
+                g_test_get_filename (G_TEST_DIST, "test-key-2.pem", NULL),
+                NULL
+        );
+        g_assert_nonnull (wrong_certificate);
+        msg = soup_message_new_from_uri ("GET", uri);
+        soup_message_add_flags (msg, SOUP_MESSAGE_NEW_CONNECTION);
+        g_signal_connect (msg, "request-certificate",
+                          G_CALLBACK (request_certificate_cb),
+                          wrong_certificate);
+        body = soup_test_session_async_send (session, msg, NULL, &error);
+        if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
+                g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED);
+        g_assert_null (body);
+        g_clear_error (&error);
+        g_object_unref (msg);
+
+        /* Passing NULL certificate fails */
+        msg = soup_message_new_from_uri ("GET", uri);
+        soup_message_add_flags (msg, SOUP_MESSAGE_NEW_CONNECTION);
+        g_signal_connect (msg, "request-certificate",
+                          G_CALLBACK (request_certificate_cb),
+                          NULL);
+        body = soup_test_session_async_send (session, msg, NULL, &error);
+        if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
+                g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED);
+        g_clear_error (&error);
+        g_bytes_unref (body);
+        g_object_unref (msg);
+
         /* request-certificate is not emitted if the certificate is set before the load */
         msg = soup_message_new_from_uri ("GET", uri);
         soup_message_add_flags (msg, SOUP_MESSAGE_NEW_CONNECTION);
@@ -385,19 +417,27 @@ do_tls_interaction_msg_test (gconstpointer data)
         g_object_unref (msg);
 
         /* Using the wrong certificate fails */
-        wrong_certificate = g_tls_certificate_new_from_files (
-                g_test_get_filename (G_TEST_DIST, "test-cert-2.pem", NULL),
-                g_test_get_filename (G_TEST_DIST, "test-key-2.pem", NULL),
-                NULL
-        );
-        g_assert_nonnull (wrong_certificate);
         msg = soup_message_new_from_uri ("GET", uri);
         soup_message_add_flags (msg, SOUP_MESSAGE_NEW_CONNECTION);
         g_signal_connect (msg, "request-certificate",
                           G_CALLBACK (request_certificate_async_cb),
                           wrong_certificate);
         body = soup_test_session_async_send (session, msg, NULL, &error);
-        g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED);
+        if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
+                g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED);
+        g_assert_null (body);
+        g_clear_error (&error);
+        g_object_unref (msg);
+
+        /* Passing NULL certificate fails */
+        msg = soup_message_new_from_uri ("GET", uri);
+        soup_message_add_flags (msg, SOUP_MESSAGE_NEW_CONNECTION);
+        g_signal_connect (msg, "request-certificate",
+                          G_CALLBACK (request_certificate_async_cb),
+                          NULL);
+        body = soup_test_session_async_send (session, msg, NULL, &error);
+        if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
+                g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED);
         g_assert_null (body);
         g_clear_error (&error);
         g_object_unref (msg);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]