[glib-networking/wip/danw/tls-info: 1/2] gnutls: implement GTlsConnection:connection-info
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/wip/danw/tls-info: 1/2] gnutls: implement GTlsConnection:connection-info
- Date: Wed, 31 May 2017 19:04:18 +0000 (UTC)
commit 3e4be903728e744e41d44ba62d6e35f1575205d5
Author: Dan Winship <danw gnome org>
Date: Mon Mar 23 09:56:21 2015 -0400
gnutls: implement GTlsConnection:connection-info
tls/gnutls/gtlsconnection-gnutls.c | 110 ++++++++++++++++++++++++++-
tls/tests/connection.c | 150 +++++++++++++++++++++++++++++++-----
2 files changed, 239 insertions(+), 21 deletions(-)
---
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index 7436451..afc5655 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -87,7 +87,8 @@ enum
PROP_CERTIFICATE,
PROP_INTERACTION,
PROP_PEER_CERTIFICATE,
- PROP_PEER_CERTIFICATE_ERRORS
+ PROP_PEER_CERTIFICATE_ERRORS,
+ PROP_CONNECTION_INFO
};
struct _GTlsConnectionGnutlsPrivate
@@ -372,6 +373,102 @@ g_tls_connection_gnutls_finalize (GObject *object)
}
static void
+get_connection_info (GTlsConnectionGnutls *gnutls,
+ GValue *value)
+{
+ GVariantBuilder builder;
+ gnutls_protocol_t proto;
+ GTlsVersion version;
+ gnutls_kx_algorithm_t kx, cur_kx;
+ gnutls_cipher_algorithm_t cipher, cur_cipher;
+ gnutls_mac_algorithm_t mac, cur_mac;
+ char *cipher_suite, *p;
+ int dh_prime_size;
+
+ /* Unfortunately GNUTLS doesn't provide any API for this...
+ * If this becomes a problem, we could snoop the version
+ * from g_tls_connection_gnutls_pull_func()...
+ */
+ switch (gnutls_protocol_get_version (gnutls->priv->session))
+ {
+ case GNUTLS_SSL3:
+ version = G_TLS_VERSION_SSL_3_0;
+ case GNUTLS_TLS1_0:
+ version = G_TLS_VERSION_TLS_1_0;
+ case GNUTLS_TLS1_1:
+ version = G_TLS_VERSION_TLS_1_1;
+ case GNUTLS_TLS1_2:
+ version = G_TLS_VERSION_TLS_1_2;
+ case GNUTLS_DTLS1_0:
+ version = G_TLS_VERSION_DTLS_1_0;
+ case GNUTLS_DTLS1_2:
+ version = G_TLS_VERSION_DTLS_1_2;
+ case GNUTLS_VERSION_UNKNOWN:
+ g_value_set_variant (value, NULL);
+ return;
+ default:
+ g_warning ("Unrecognized gnutls_protocol_t value!");
+ version = G_TLS_VERSION_INVALID;
+ }
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add (&builder, "{sv}",
+ "version",
+ g_variant_new_int16 (version));
+
+ cur_kx = gnutls_kx_get (gnutls->priv->session);
+ cur_cipher = gnutls_cipher_get (gnutls->priv->session);
+ cur_mac = gnutls_mac_get (gnutls->priv->session);
+
+ g_variant_builder_add (&builder, "{sv}",
+ "key-exchange",
+ g_variant_new_string (gnutls_kx_get_name (cur_kx)));
+ g_variant_builder_add (&builder, "{sv}",
+ "cipher",
+ g_variant_new_string (gnutls_cipher_get_name (cur_cipher)));
+ g_variant_builder_add (&builder, "{sv}",
+ "key-size",
+ g_variant_new_int32 (gnutls_cipher_get_key_size (cur_cipher)));
+ g_variant_builder_add (&builder, "{sv}",
+ "mac",
+ g_variant_new_string (gnutls_mac_get_name (cur_mac)));
+ g_variant_builder_add (&builder, "{sv}",
+ "mac-size",
+ g_variant_new_int32 (gnutls_mac_get_key_size (cur_mac)));
+
+ /* The names returned by gnutls_cipher_suite_info() aren't in
+ * the form used in the spec.
+ */
+ cipher_suite = g_strdup_printf ("%s_%s_WITH_%s_%s",
+ version == G_TLS_VERSION_SSL3 ? "SSL" : "TLS",
+ gnutls_kx_get_name (cur_kx),
+ gnutls_cipher_get_name (cur_cipher),
+ gnutls_mac_get_name (cur_mac));
+ for (p = cipher_suite; *p; p++)
+ {
+ if (*p == '-')
+ *p = '_';
+ }
+ g_variant_builder_add (&builder, "{sv}",
+ "cipher-suite",
+ g_variant_new_take_string (cipher_suite));
+
+ dh_prime_size = gnutls_dh_get_prime_bits (gnutls->priv->session);
+ if (dh_prime_size)
+ {
+ g_variant_builder_add (&builder, "{sv}",
+ "dh-prime-size",
+ g_variant_new_int32 (dh_prime_size));
+ }
+
+ g_variant_builder_add (&builder, "{sv}",
+ "ext-renegotiation-info",
+ g_variant_new_boolean (gnutls_safe_renegotiation_status (gnutls->priv->session) !=
0));
+
+ g_value_take_variant (value, g_variant_builder_end (&builder));
+}
+
+static void
g_tls_connection_gnutls_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -424,6 +521,13 @@ g_tls_connection_gnutls_get_property (GObject *object,
g_value_set_flags (value, gnutls->priv->peer_certificate_errors);
break;
+ case PROP_CONNECTION_INFO:
+ if (!gnutls->priv->ever_handshaked)
+ g_value_set_variant (value, NULL);
+ else
+ get_connection_info (gnutls, value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -1768,6 +1872,10 @@ g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
g_object_class_override_property (gobject_class, PROP_INTERACTION, "interaction");
g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE, "peer-certificate");
g_object_class_override_property (gobject_class, PROP_PEER_CERTIFICATE_ERRORS, "peer-certificate-errors");
+ g_object_class_override_property (gobject_class, PROP_VERSION, "version");
+ g_object_class_override_property (gobject_class, PROP_VERSION_NAME, "version-name");
+ g_object_class_override_property (gobject_class, PROP_CIPHER_SUITE, "cipher-suite");
+ g_object_class_override_property (gobject_class, PROP_CIPHER_SUITE_NAME, "cipher-suite-name");
}
static void
diff --git a/tls/tests/connection.c b/tls/tests/connection.c
index 6bcb9c2..155ab58 100644
--- a/tls/tests/connection.c
+++ b/tls/tests/connection.c
@@ -1417,25 +1417,28 @@ quit_on_handshake_complete (GObject *object,
return;
}
-#define PRIORITY_SSL_FALLBACK "NORMAL:+VERS-SSL3.0"
-#define PRIORITY_TLS_FALLBACK "NORMAL:+VERS-TLS-ALL:-VERS-SSL3.0"
+typedef struct {
+ GTlsVersion version;
+ const char *version_name;
+} TestVersionData;
static void
-test_fallback (gconstpointer data)
+test_priority_string (gconstpointer data)
{
- const char *priority_string = (const char *) data;
- char *test_name;
+ const char *subtest_name = (const char *) data;
- test_name = g_strdup_printf ("/tls/connection/fallback/subprocess/%s", priority_string);
- g_test_trap_subprocess (test_name, 0, 0);
+ g_test_trap_subprocess (subtest_name, 0, 0);
g_test_trap_assert_passed ();
- g_free (test_name);
}
+#define PRIORITY_SSL_FALLBACK "NORMAL:+VERS-SSL3.0"
+#define PRIORITY_TLS_FALLBACK "NORMAL:+VERS-TLS-ALL:-VERS-SSL3.0"
+
static void
test_fallback_subprocess (TestConnection *test,
- gconstpointer data)
+ gconstpointer test_data)
{
+ const TestVersionData *data = (const TestVersionData *) test_data;
GIOStream *connection;
GTlsConnection *tlsconn;
GError *error = NULL;
@@ -1446,6 +1449,9 @@ test_fallback_subprocess (TestConnection *test,
tlsconn = G_TLS_CONNECTION (test->client_connection);
g_object_unref (connection);
+ g_assert_cmpint (g_tls_connection_get_version (tlsconn), ==, G_TLS_VERSION_INVALID);
+ g_assert_cmpstr (g_tls_connection_get_version_name (tlsconn), ==, NULL);
+
g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (test->client_connection),
0);
g_tls_client_connection_set_use_ssl3 (G_TLS_CLIENT_CONNECTION (test->client_connection),
@@ -1454,9 +1460,79 @@ test_fallback_subprocess (TestConnection *test,
quit_on_handshake_complete, test);
g_main_loop_run (test->loop);
- /* In 2.42 we don't have the API to test that the correct version was negotiated,
- * so we merely test that the connection succeeded at all.
- */
+ g_assert_cmpint (g_tls_connection_get_version (tlsconn), ==, data->version);
+ g_assert_cmpstr (g_tls_connection_get_version_name (tlsconn), ==, data->version_name);
+
+ g_io_stream_close (test->client_connection, NULL, &error);
+ g_assert_no_error (error);
+}
+
+#define PRIORITY_TLS_1_0_ONLY "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0"
+#define PRIORITY_TLS_1_1_ONLY "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1"
+#define PRIORITY_RSA_ONLY "NONE:+VERS-TLS-ALL:+RSA:+AES-256-CBC:+SHA256:+SIGN-ALL:+COMP-NULL"
+
+static void
+test_version (TestConnection *test,
+ gconstpointer test_data)
+{
+ const TestVersionData *data = (const TestVersionData *) test_data;
+ GIOStream *connection;
+ GTlsConnection *tlsconn;
+ GError *error = NULL;
+
+ connection = start_echo_server_and_connect_to_it (test);
+ test->client_connection = g_tls_client_connection_new (connection, NULL, &error);
+ g_assert_no_error (error);
+ tlsconn = G_TLS_CONNECTION (test->client_connection);
+ g_object_unref (connection);
+
+ g_assert_cmpint (g_tls_connection_get_version (tlsconn), ==, G_TLS_VERSION_INVALID);
+ g_assert_cmpstr (g_tls_connection_get_version_name (tlsconn), ==, NULL);
+
+ g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (test->client_connection),
+ 0);
+ g_tls_connection_handshake_async (tlsconn, G_PRIORITY_DEFAULT, NULL,
+ quit_on_handshake_complete, test);
+ g_main_loop_run (test->loop);
+
+ g_assert_cmpint (g_tls_connection_get_version (tlsconn), ==, data->version);
+ g_assert_cmpstr (g_tls_connection_get_version_name (tlsconn), ==, data->version_name);
+
+ g_io_stream_close (test->client_connection, NULL, &error);
+ g_assert_no_error (error);
+}
+
+typedef struct {
+ guint cipher_suite;
+ const char *cipher_suite_name;
+} TestCipherSuiteData;
+
+static void
+test_cipher_suite (TestConnection *test,
+ gconstpointer test_data)
+{
+ const TestCipherSuiteData *data = (const TestCipherSuiteData *) test_data;
+ GIOStream *connection;
+ GTlsConnection *tlsconn;
+ GError *error = NULL;
+
+ connection = start_echo_server_and_connect_to_it (test);
+ test->client_connection = g_tls_client_connection_new (connection, NULL, &error);
+ g_assert_no_error (error);
+ tlsconn = G_TLS_CONNECTION (test->client_connection);
+ g_object_unref (connection);
+
+ g_assert_cmpint (g_tls_connection_get_cipher_suite (tlsconn), ==, 0x0000);
+ g_assert_cmpstr (g_tls_connection_get_cipher_suite_name (tlsconn), ==, "TLS_NULL_WITH_NULL_NULL");
+
+ g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (test->client_connection),
+ 0);
+ g_tls_connection_handshake_async (tlsconn, G_PRIORITY_DEFAULT, NULL,
+ quit_on_handshake_complete, test);
+ g_main_loop_run (test->loop);
+
+ g_assert_cmpint (g_tls_connection_get_cipher_suite (tlsconn), ==, data->cipher_suite);
+ g_assert_cmpstr (g_tls_connection_get_cipher_suite_name (tlsconn), ==, data->cipher_suite_name);
g_io_stream_close (test->client_connection, NULL, &error);
g_assert_no_error (error);
@@ -1535,14 +1611,48 @@ main (int argc,
g_test_add ("/tls/connection/async-implicit-handshake", TestConnection, NULL,
setup_connection, test_async_implicit_handshake, teardown_connection);
- g_test_add_data_func ("/tls/connection/fallback/SSL", PRIORITY_SSL_FALLBACK, test_fallback);
- g_test_add ("/tls/connection/fallback/subprocess/" PRIORITY_SSL_FALLBACK,
- TestConnection, NULL,
- setup_connection, test_fallback_subprocess, teardown_connection);
- g_test_add_data_func ("/tls/connection/fallback/TLS", PRIORITY_TLS_FALLBACK, test_fallback);
- g_test_add ("/tls/connection/fallback/subprocess/" PRIORITY_TLS_FALLBACK,
- TestConnection, NULL,
- setup_connection, test_fallback_subprocess, teardown_connection);
+ {
+ TestVersionData ssl3 = { G_TLS_VERSION_SSL_3_0, "SSL3.0" };
+ TestVersionData tls10 = { G_TLS_VERSION_TLS_1_0, "TLS1.0" };
+ TestVersionData tls11 = { G_TLS_VERSION_TLS_1_1, "TLS1.1" };
+
+ g_test_add_data_func ("/tls/connection/fallback/SSL",
+ "/tls/connection/fallback/subprocess/" PRIORITY_SSL_FALLBACK,
+ test_priority_string);
+ g_test_add ("/tls/connection/fallback/subprocess/" PRIORITY_SSL_FALLBACK,
+ TestConnection, &ssl3,
+ setup_connection, test_fallback_subprocess, teardown_connection);
+ g_test_add_data_func ("/tls/connection/fallback/TLS",
+ "/tls/connection/fallback/subprocess/" PRIORITY_TLS_FALLBACK,
+ test_priority_string);
+ g_test_add ("/tls/connection/fallback/subprocess/" PRIORITY_TLS_FALLBACK,
+ TestConnection, &tls10,
+ setup_connection, test_fallback_subprocess, teardown_connection);
+
+ g_test_add_data_func ("/tls/connection/version/TLS1.0",
+ "/tls/connection/version/TLS1.0/subprocess/" PRIORITY_TLS_1_0_ONLY,
+ test_priority_string);
+ g_test_add ("/tls/connection/version/TLS1.0/subprocess/" PRIORITY_TLS_1_0_ONLY,
+ TestConnection, &tls10,
+ setup_connection, test_version, teardown_connection);
+ g_test_add_data_func ("/tls/connection/version/TLS1.1",
+ "/tls/connection/version/TLS1.1/subprocess/" PRIORITY_TLS_1_1_ONLY,
+ test_priority_string);
+ g_test_add ("/tls/connection/version/TLS1.1/subprocess/" PRIORITY_TLS_1_1_ONLY,
+ TestConnection, &tls11,
+ setup_connection, test_version, teardown_connection);
+ }
+
+ {
+ TestCipherSuiteData rsa = { 0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256" };
+
+ g_test_add_data_func ("/tls/connection/cipher-suite/RSA",
+ "/tls/connection/cipher-suite/RSA/subprocess/" PRIORITY_RSA_ONLY,
+ test_priority_string);
+ g_test_add ("/tls/connection/cipher-suite/RSA/subprocess/" PRIORITY_RSA_ONLY,
+ TestConnection, &rsa,
+ setup_connection, test_cipher_suite, teardown_connection);
+ }
ret = g_test_run();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]