diff options
author | Dan Winship <danw@gnome.org> | 2014-05-02 16:01:24 -0400 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2014-05-03 13:30:52 -0400 |
commit | 0ee90b166ba4a9ca3c8c66a531d97c661536087d (patch) | |
tree | 33cfad46af6a6e677bb4ababc3d087483acc4a19 /tests/ssl-test.c | |
parent | ba5f2e307b2ee45f4cc166f6b488c7bc8559bfc7 (diff) | |
download | libsoup-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.c | 167 |
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, |