summaryrefslogtreecommitdiff
path: root/tests/ssl-test.c
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2014-05-02 16:01:24 -0400
committerDan Winship <danw@gnome.org>2014-05-03 13:30:52 -0400
commit0ee90b166ba4a9ca3c8c66a531d97c661536087d (patch)
tree33cfad46af6a6e677bb4ababc3d087483acc4a19 /tests/ssl-test.c
parentba5f2e307b2ee45f4cc166f6b488c7bc8559bfc7 (diff)
downloadlibsoup-0ee90b166ba4a9ca3c8c66a531d97c661536087d.tar.gz
Add tls-interaction property to SoupSession
This can be used by applications to do client-side certificates via the new g_tls_interaction_request_certificate(). Will be used by OSTree at least. Also add a test to tls-test. Based on a patch from Colin Walters. https://bugzilla.gnome.org/show_bug.cgi?id=334021
Diffstat (limited to 'tests/ssl-test.c')
-rw-r--r--tests/ssl-test.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/tests/ssl-test.c b/tests/ssl-test.c
index 989c48d3..8ff50a36 100644
--- a/tests/ssl-test.c
+++ b/tests/ssl-test.c
@@ -235,6 +235,172 @@ do_session_property_tests (void)
soup_test_session_abort_unref (session);
}
+/* GTlsInteraction subclass for do_interaction_test */
+typedef GTlsInteraction TestTlsInteraction;
+typedef GTlsInteractionClass TestTlsInteractionClass;
+
+GType test_tls_interaction_get_type (void);
+
+G_DEFINE_TYPE (TestTlsInteraction, test_tls_interaction, G_TYPE_TLS_INTERACTION);
+
+static void
+test_tls_interaction_init (TestTlsInteraction *interaction)
+{
+
+}
+
+static GTlsInteractionResult
+test_tls_interaction_request_certificate (GTlsInteraction *interaction,
+ GTlsConnection *connection,
+ GTlsCertificateRequestFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GTlsCertificate *cert;
+ const char *ssl_cert_file, *ssl_key_file;
+ GError *my_error = NULL;
+
+ /* Yes, we use the same certificate for the client as for the server. Shrug */
+ ssl_cert_file = g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL);
+ ssl_key_file = g_test_get_filename (G_TEST_DIST, "test-key.pem", NULL);
+ cert = g_tls_certificate_new_from_files (ssl_cert_file,
+ ssl_key_file,
+ &my_error);
+ g_assert_no_error (my_error);
+
+ g_tls_connection_set_certificate (connection, cert);
+ g_object_unref (cert);
+
+ return G_TLS_INTERACTION_HANDLED;
+}
+
+static void
+test_tls_interaction_class_init (TestTlsInteractionClass *klass)
+{
+ GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass);
+
+ interaction_class->request_certificate = test_tls_interaction_request_certificate;
+}
+
+
+#define INTERACTION_TEST_HTTP_RESPONSE "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nOK\r\n"
+
+static gboolean
+accept_client_certificate (GTlsConnection *server,
+ GTlsCertificate *client_cert,
+ GTlsCertificateFlags errors)
+{
+ return TRUE;
+}
+
+static void
+got_connection (GThreadedSocketService *service,
+ GSocketConnection *connection,
+ GObject *source_object)
+{
+ GIOStream *tls;
+ GTlsCertificate *server_cert;
+ GError *error = NULL;
+ const char *ssl_cert_file, *ssl_key_file;
+ GMainContext *thread_context;
+
+ thread_context = g_main_context_new ();
+ g_main_context_push_thread_default (thread_context);
+
+ ssl_cert_file = g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL);
+ ssl_key_file = g_test_get_filename (G_TEST_DIST, "test-key.pem", NULL);
+ server_cert = g_tls_certificate_new_from_files (ssl_cert_file,
+ ssl_key_file,
+ &error);
+ g_assert_no_error (error);
+
+ tls = g_tls_server_connection_new (G_IO_STREAM (connection),
+ server_cert, &error);
+ g_assert_no_error (error);
+ g_object_unref (server_cert);
+
+ g_object_set (G_OBJECT (tls),
+ "authentication-mode", G_TLS_AUTHENTICATION_REQUIRED,
+ NULL);
+ g_signal_connect (tls, "accept-certificate",
+ G_CALLBACK (accept_client_certificate), NULL);
+
+ if (g_tls_connection_handshake (G_TLS_CONNECTION (tls), NULL, &error)) {
+ g_output_stream_write_all (g_io_stream_get_output_stream (tls),
+ INTERACTION_TEST_HTTP_RESPONSE,
+ strlen (INTERACTION_TEST_HTTP_RESPONSE),
+ NULL, NULL, &error);
+ g_assert_no_error (error);
+ } else {
+ g_assert_error (error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED);
+ g_clear_error (&error);
+ }
+
+ g_io_stream_close (tls, NULL, &error);
+ g_assert_no_error (error);
+
+ g_object_unref (tls);
+
+ g_main_context_pop_thread_default (thread_context);
+ g_main_context_unref (thread_context);
+}
+
+static void
+do_tls_interaction_test (void)
+{
+ GSocketService *service;
+ GSocketAddress *address, *bound_address;
+ SoupSession *session;
+ SoupMessage *msg;
+ GTlsInteraction *interaction;
+ SoupURI *test_uri;
+ GError *error = NULL;
+
+ SOUP_TEST_SKIP_IF_NO_TLS;
+
+ service = g_threaded_socket_service_new (1);
+ address = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
+ g_socket_listener_add_address (G_SOCKET_LISTENER (service), address,
+ G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP,
+ NULL, &bound_address, &error);
+ g_assert_no_error (error);
+ g_object_unref (address);
+ g_signal_connect (service, "run", G_CALLBACK (got_connection), NULL);
+ g_socket_service_start (service);
+
+ test_uri = soup_uri_new ("https://127.0.0.1");
+ soup_uri_set_port (test_uri, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (bound_address)));
+ g_object_unref (bound_address);
+
+ session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
+
+ /* Without a GTlsInteraction */
+ msg = soup_message_new_from_uri ("GET", test_uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_SSL_FAILED);
+ g_object_unref (msg);
+
+ interaction = g_object_new (test_tls_interaction_get_type (), NULL);
+ g_object_set (G_OBJECT (session),
+ SOUP_SESSION_TLS_INTERACTION, interaction,
+ NULL);
+ g_object_unref (interaction);
+
+ /* With a GTlsInteraction */
+ msg = soup_message_new_from_uri ("GET", test_uri);
+ soup_session_send_message (session, msg);
+ soup_test_assert_message_status (msg, SOUP_STATUS_OK);
+ g_assert_true (soup_message_get_https_status (msg, NULL, NULL));
+ g_object_unref (msg);
+
+ soup_uri_free (test_uri);
+ soup_test_session_abort_unref (session);
+
+ g_socket_service_stop (service);
+ g_object_unref (service);
+}
+
static void
server_handler (SoupServer *server,
SoupMessage *msg,
@@ -267,6 +433,7 @@ main (int argc, char **argv)
g_test_add_func ("/ssl/session-properties", do_session_property_tests);
g_test_add_func ("/ssl/message-properties/async", do_async_properties_tests);
g_test_add_func ("/ssl/message-properties/sync", do_sync_properties_tests);
+ g_test_add_func ("/ssl/tls-interaction", do_tls_interaction_test);
for (i = 0; i < G_N_ELEMENTS (strictness_tests); i++) {
g_test_add_data_func (strictness_tests[i].name,