From c4165d097e84f60d0bcaf67a8bf7fc34474d02c4 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Mon, 14 Jun 2021 11:38:54 +0200 Subject: 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); -- cgit v1.2.1