]> git.0d.be Git - empathy.git/blobdiff - tests/empathy-tls-test.c
libempathy-gtk: fix uninitialized variable
[empathy.git] / tests / empathy-tls-test.c
index f2b667d0bf0aa84bb48906e6bffb9aabf12280c9..91b05761f9b9ebb44157bc40ffb4606c4f3650e7 100644 (file)
@@ -1,21 +1,12 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <libempathy/empathy-tls-certificate.h>
-#include <libempathy/empathy-tls-verifier.h>
-#include "test-helper.h"
-
-#include <gcr/gcr.h>
+#include "config.h"
 
 #include <gnutls/gnutls.h>
-
-#include <telepathy-glib/dbus-properties-mixin.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/svc-tls.h>
-#include <telepathy-glib/svc-generic.h>
 #include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+
+#include "empathy-tls-verifier.h"
+#include "mock-pkcs11.h"
+#include "test-helper.h"
 
 #define MOCK_TLS_CERTIFICATE_PATH "/mock/certificate"
 
@@ -61,7 +52,8 @@ mock_tls_certificate_init (MockTLSCertificate *self)
 {
   self->state = TP_TLS_CERTIFICATE_STATE_PENDING;
   self->cert_type = g_strdup ("x509");
-  self->cert_data = g_ptr_array_new_with_free_func((GDestroyNotify) g_array_unref);
+  self->cert_data = g_ptr_array_new_with_free_func ((GDestroyNotify)
+      g_array_unref);
   self->rejections = g_ptr_array_new ();
 }
 
@@ -102,7 +94,7 @@ mock_tls_certificate_finalize (GObject *object)
       &self->rejections);
   g_free (self->cert_type);
   self->cert_type = NULL;
-  g_ptr_array_free (self->cert_data, TRUE);
+  g_ptr_array_unref (self->cert_data);
   self->cert_data = NULL;
 
   G_OBJECT_CLASS (mock_tls_certificate_parent_class)->finalize (object);
@@ -137,7 +129,7 @@ mock_tls_certificate_class_init (MockTLSCertificateClass *klass)
   pspec = g_param_spec_uint ("state",
       "State of this certificate",
       "The state of this TLS certificate.",
-      0, NUM_TP_TLS_CERTIFICATE_STATES - 1,
+      0, TP_NUM_TLS_CERTIFICATE_STATES - 1,
       TP_TLS_CERTIFICATE_STATE_PENDING,
       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
   g_object_class_install_property (oclass, PROP_STATE, pspec);
@@ -194,7 +186,7 @@ mock_tls_certificate_iface_init (gpointer g_iface,
         gpointer iface_data)
 {
   TpSvcAuthenticationTLSCertificateClass *klass =
-    (TpSvcAuthenticationTLSCertificateClass*)g_iface;
+    (TpSvcAuthenticationTLSCertificateClass *) g_iface;
 
   tp_svc_authentication_tls_certificate_implement_accept (klass,
       mock_tls_certificate_accept);
@@ -205,10 +197,10 @@ mock_tls_certificate_iface_init (gpointer g_iface,
 #if 0
 static void
 mock_tls_certificate_assert_rejected (MockTLSCertificate *self,
-        EmpTLSCertificateRejectReason reason)
+        TpTLSCertificateRejectReason reason)
 {
   GValueArray *rejection;
-  EmpTLSCertificateRejectReason rejection_reason;
+  TpTLSCertificateRejectReason rejection_reason;
   gchar *rejection_error;
   GHashTable *rejection_details;
   guint i;
@@ -226,7 +218,7 @@ mock_tls_certificate_assert_rejected (MockTLSCertificate *self,
               TP_HASH_TYPE_STRING_VARIANT_MAP, &rejection_details,
               NULL);
       g_free (rejection_error);
-      g_hash_table_destroy (rejection_details);
+      g_hash_table_unref (rejection_details);
 
       if (rejection_reason == reason)
         return;
@@ -236,7 +228,7 @@ mock_tls_certificate_assert_rejected (MockTLSCertificate *self,
 }
 #endif
 
-static MockTLSCertificate*
+static MockTLSCertificate *
 mock_tls_certificate_new_and_register (TpDBusDaemon *dbus,
         const gchar *path,
         ...)
@@ -281,7 +273,7 @@ typedef struct {
   TpDBusDaemon *dbus;
   const gchar *dbus_name;
   MockTLSCertificate *mock;
-  EmpathyTLSCertificate *cert;
+  TpTLSCertificate *cert;
   GAsyncResult *result;
 } Test;
 
@@ -289,6 +281,9 @@ static void
 setup (Test *test, gconstpointer data)
 {
   GError *error = NULL;
+  GckModule *module;
+  const gchar *trust_uris[2] = { MOCK_SLOT_ONE_URI, NULL };
+
   test->loop = g_main_loop_new (NULL, FALSE);
 
   test->dbus = tp_dbus_daemon_dup (&error);
@@ -299,13 +294,20 @@ setup (Test *test, gconstpointer data)
   test->result = NULL;
   test->cert = NULL;
 
-  /* No PKCS#11 modules by default, tests add them */
+  /* Add our mock module as the only PKCS#11 module */
+  module = gck_module_new (&mock_default_functions);
+  mock_C_Initialize (NULL);
+
   gcr_pkcs11_set_modules (NULL);
+  gcr_pkcs11_add_module (module);
+  gcr_pkcs11_set_trust_lookup_uris (trust_uris);
 }
 
 static void
 teardown (Test *test, gconstpointer data)
 {
+  mock_C_Finalize (NULL);
+
   test->dbus_name = NULL;
 
   if (test->mock)
@@ -331,42 +333,30 @@ teardown (Test *test, gconstpointer data)
 }
 
 static void
-add_pkcs11_module_for_testing (Test *test,
-        const gchar *filename,
-        const gchar *subdir)
+add_certificate_to_mock (Test *test,
+        const gchar *certificate,
+        const gchar *peer)
 {
   GError *error = NULL;
-  gchar *args, *path, *directory;
-  gchar *standalone, *error_output;
-  gint exit_status;
+  GcrCertificate *cert;
+  gchar *contents;
+  gsize length;
+  gchar *path;
 
-  directory = g_build_filename (g_getenv ("EMPATHY_SRCDIR"),
-          "tests", "certificates", subdir, NULL);
+  path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"),
+                           "tests", "certificates", certificate, NULL);
 
-  /*
-   * Lookup the directory for standalone pkcs11 modules installed by
-   * gnome-keyring. We use these for testing our implementation.
-   */
-  g_spawn_command_line_sync ("pkg-config --variable=pkcs11standalonedir gcr-3",
-          &standalone, &error_output, &exit_status, &error);
+  g_file_get_contents (path, &contents, &length, &error);
   g_assert_no_error (error);
-  if (exit_status != 0)
-    {
-      g_warning ("couldn't determine standalone pkcs11 module directory: %d: %s",
-              exit_status, error_output);
-      g_assert_not_reached ();
-    }
 
-  g_strstrip (standalone);
-  args = g_strdup_printf ("directory=\"%s\"", directory);
-  path = g_build_filename (standalone, filename, NULL);
-  gcr_pkcs11_add_module_from_file (path, args, &error);
-  g_assert_no_error (error);
+  cert = gcr_simple_certificate_new ((const guchar *)contents, length);
+  mock_module_add_certificate (cert);
+  mock_module_add_assertion (cert,
+          peer ? CKT_X_PINNED_CERTIFICATE : CKT_X_ANCHORED_CERTIFICATE,
+          GCR_PURPOSE_SERVER_AUTH, peer);
+  g_object_unref (cert);
 
-  g_free (directory);
-  g_free (standalone);
-  g_free (error_output);
-  g_free (args);
+  g_free (contents);
   g_free (path);
 }
 
@@ -385,17 +375,22 @@ static void
 ensure_certificate_proxy (Test *test)
 {
   GError *error = NULL;
+  GQuark features[] = { TP_TLS_CERTIFICATE_FEATURE_CORE, 0 };
 
   if (test->cert)
     return;
 
   /* Create and prepare a certificate */
-  test->cert = empathy_tls_certificate_new (test->dbus, test->dbus_name,
-          MOCK_TLS_CERTIFICATE_PATH, &error);
-  g_assert_no_error (error);
-  empathy_tls_certificate_prepare_async (test->cert, fetch_callback_result, test);
+  /* We don't use tp_tls_certificate_new() as we don't pass a parent */
+  test->cert = g_object_new (TP_TYPE_TLS_CERTIFICATE,
+      "dbus-daemon", test->dbus,
+      "bus-name", test->dbus_name,
+      "object-path", MOCK_TLS_CERTIFICATE_PATH,
+      NULL);
+
+  tp_proxy_prepare_async (test->cert, features, fetch_callback_result, test);
   g_main_loop_run (test->loop);
-  empathy_tls_certificate_prepare_finish (test->cert, test->result, &error);
+  tp_proxy_prepare_finish (test->cert, test->result, &error);
   g_assert_no_error (error);
 
   /* Clear for any future async stuff */
@@ -411,13 +406,13 @@ test_certificate_mock_basics (Test *test,
   GError *error = NULL;
 
   test->mock = mock_tls_certificate_new_and_register (test->dbus,
-          "dhansak-collabora.cer", NULL);
+          "server-cert.cer", NULL);
 
   ensure_certificate_proxy (test);
 
-  empathy_tls_certificate_accept_async (test->cert, fetch_callback_result, test);
+  tp_tls_certificate_accept_async (test->cert, fetch_callback_result, test);
   g_main_loop_run (test->loop);
-  empathy_tls_certificate_accept_finish (test->cert, test->result, &error);
+  tp_tls_certificate_accept_finish (test->cert, test->result, &error);
   g_assert_no_error (error);
 
   g_assert (test->mock->state == TP_TLS_CERTIFICATE_STATE_ACCEPTED);
@@ -427,11 +422,11 @@ static void
 test_certificate_verify_success_with_pkcs11_lookup (Test *test,
         gconstpointer data G_GNUC_UNUSED)
 {
-  EmpTLSCertificateRejectReason reason = 0;
+  TpTLSCertificateRejectReason reason = 0;
   GError *error = NULL;
   EmpathyTLSVerifier *verifier;
   const gchar *reference_identities[] = {
-    "www.collabora.co.uk",
+    "test-server.empathy.gnome.org",
     NULL
   };
 
@@ -442,21 +437,21 @@ test_certificate_verify_success_with_pkcs11_lookup (Test *test,
    */
 
   test->mock = mock_tls_certificate_new_and_register (test->dbus,
-          "dhansak-collabora.cer", NULL);
+          "server-cert.cer", NULL);
 
   /* We add the collabora directory with the collabora root */
-  add_pkcs11_module_for_testing (test, "gkm-roots-store-standalone.so",
-          "collabora-ca");
+  add_certificate_to_mock (test, "certificate-authority.cer", NULL);
 
   ensure_certificate_proxy (test);
 
-  verifier = empathy_tls_verifier_new (test->cert, "www.collabora.co.uk",
+  verifier = empathy_tls_verifier_new (test->cert, "test-server.empathy.gnome.org",
       reference_identities);
   empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test);
   g_main_loop_run (test->loop);
-  if (!empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
-          NULL, &error))
-    g_assert_not_reached ();
+
+  empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
+      NULL, &error);
+  g_assert_no_error (error);
 
   /* Yay the verification was a success! */
 
@@ -468,11 +463,11 @@ static void
 test_certificate_verify_success_with_full_chain (Test *test,
         gconstpointer data G_GNUC_UNUSED)
 {
-  EmpTLSCertificateRejectReason reason = 0;
+  TpTLSCertificateRejectReason reason = 0;
   GError *error = NULL;
   EmpathyTLSVerifier *verifier;
   const gchar *reference_identities[] = {
-    "www.collabora.co.uk",
+    "test-server.empathy.gnome.org",
     NULL
   };
 
@@ -482,21 +477,20 @@ test_certificate_verify_success_with_full_chain (Test *test,
    */
 
   test->mock = mock_tls_certificate_new_and_register (test->dbus,
-          "dhansak-collabora.cer", "collabora-ca/collabora-ca.cer", NULL);
+          "server-cert.cer", "certificate-authority.cer", NULL);
 
   /* We add the collabora directory with the collabora root */
-  add_pkcs11_module_for_testing (test, "gkm-roots-store-standalone.so",
-          "collabora-ca");
+  add_certificate_to_mock (test, "certificate-authority.cer", NULL);
 
   ensure_certificate_proxy (test);
 
-  verifier = empathy_tls_verifier_new (test->cert, "www.collabora.co.uk",
+  verifier = empathy_tls_verifier_new (test->cert, "test-server.empathy.gnome.org",
       reference_identities);
   empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test);
   g_main_loop_run (test->loop);
-  if (!empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
-          NULL, &error))
-    g_assert_not_reached ();
+  empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
+      NULL, &error);
+  g_assert_no_error (error);
 
   /* Yay the verification was a success! */
 
@@ -508,32 +502,32 @@ static void
 test_certificate_verify_root_not_found (Test *test,
         gconstpointer data G_GNUC_UNUSED)
 {
-  EmpTLSCertificateRejectReason reason = 0;
+  TpTLSCertificateRejectReason reason = 0;
   GError *error = NULL;
   EmpathyTLSVerifier *verifier;
   const gchar *reference_identities[] = {
-    "www.collabora.co.uk",
+    "test-server.empathy.gnome.org",
     NULL
   };
 
   test->mock = mock_tls_certificate_new_and_register (test->dbus,
-          "dhansak-collabora.cer", NULL);
+          "server-cert.cer", NULL);
 
   /* Note that we're not adding any place to find root certs */
 
   ensure_certificate_proxy (test);
 
-  verifier = empathy_tls_verifier_new (test->cert, "www.collabora.co.uk",
+  verifier = empathy_tls_verifier_new (test->cert, "test-server.empathy.gnome.org",
       reference_identities);
   empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test);
   g_main_loop_run (test->loop);
 
-  if (empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
-          NULL, &error))
-    g_assert_not_reached ();
+  empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
+      NULL, &error);
 
   /* And it should say we're self-signed (oddly enough) */
-  g_assert_cmpuint (reason, ==, EMP_TLS_CERTIFICATE_REJECT_REASON_SELF_SIGNED);
+  g_assert_error (error, G_IO_ERROR,
+      TP_TLS_CERTIFICATE_REJECT_REASON_SELF_SIGNED);
 
   g_clear_error (&error);
   g_object_unref (verifier);
@@ -543,32 +537,32 @@ static void
 test_certificate_verify_root_not_anchored (Test *test,
         gconstpointer data G_GNUC_UNUSED)
 {
-  EmpTLSCertificateRejectReason reason = 0;
+  TpTLSCertificateRejectReason reason = 0;
   GError *error = NULL;
   EmpathyTLSVerifier *verifier;
   const gchar *reference_identities[] = {
-    "www.collabora.co.uk",
+    "test-server.empathy.gnome.org",
     NULL
   };
 
   test->mock = mock_tls_certificate_new_and_register (test->dbus,
-          "dhansak-collabora.cer", "collabora-ca/collabora-ca.cer", NULL);
+          "server-cert.cer", "certificate-authority.cer", NULL);
 
   /* Note that we're not adding any place to find root certs */
 
   ensure_certificate_proxy (test);
 
-  verifier = empathy_tls_verifier_new (test->cert, "www.collabora.co.uk",
+  verifier = empathy_tls_verifier_new (test->cert, "test-server.empathy.gnome.org",
       reference_identities);
   empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test);
   g_main_loop_run (test->loop);
 
-  if (empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
-          NULL, &error))
-    g_assert_not_reached ();
+  empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
+      NULL, &error);
 
   /* And it should say we're self-signed (oddly enough) */
-  g_assert_cmpuint (reason, ==, EMP_TLS_CERTIFICATE_REJECT_REASON_SELF_SIGNED);
+  g_assert_error (error, G_IO_ERROR,
+      TP_TLS_CERTIFICATE_REJECT_REASON_SELF_SIGNED);
 
   g_clear_error (&error);
   g_object_unref (verifier);
@@ -578,7 +572,7 @@ static void
 test_certificate_verify_identities_invalid (Test *test,
         gconstpointer data G_GNUC_UNUSED)
 {
-  EmpTLSCertificateRejectReason reason = 0;
+  TpTLSCertificateRejectReason reason = 0;
   GError *error = NULL;
   EmpathyTLSVerifier *verifier;
   const gchar *reference_identities[] = {
@@ -587,11 +581,10 @@ test_certificate_verify_identities_invalid (Test *test,
   };
 
   test->mock = mock_tls_certificate_new_and_register (test->dbus,
-          "dhansak-collabora.cer", "collabora-ca/collabora-ca.cer", NULL);
+          "server-cert.cer", "certificate-authority.cer", NULL);
 
   /* We add the collabora directory with the collabora root */
-  add_pkcs11_module_for_testing (test, "gkm-roots-store-standalone.so",
-          "collabora-ca");
+  add_certificate_to_mock (test, "certificate-authority.cer", NULL);
 
   ensure_certificate_proxy (test);
 
@@ -600,12 +593,12 @@ test_certificate_verify_identities_invalid (Test *test,
   empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test);
   g_main_loop_run (test->loop);
 
-  if (empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
-          NULL, &error))
-    g_assert_not_reached ();
+  empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
+      NULL, &error);
 
   /* And it should say we're self-signed (oddly enough) */
-  g_assert_cmpuint (reason, ==, EMP_TLS_CERTIFICATE_REJECT_REASON_HOSTNAME_MISMATCH);
+  g_assert_error (error, G_IO_ERROR,
+      TP_TLS_CERTIFICATE_REJECT_REASON_HOSTNAME_MISMATCH);
 
   g_clear_error (&error);
   g_object_unref (verifier);
@@ -615,7 +608,7 @@ static void
 test_certificate_verify_uses_reference_identities (Test *test,
         gconstpointer data G_GNUC_UNUSED)
 {
-  EmpTLSCertificateRejectReason reason = 0;
+  TpTLSCertificateRejectReason reason = 0;
   GError *error = NULL;
   EmpathyTLSVerifier *verifier;
   const gchar *reference_identities[] = {
@@ -624,26 +617,99 @@ test_certificate_verify_uses_reference_identities (Test *test,
   };
 
   test->mock = mock_tls_certificate_new_and_register (test->dbus,
-          "dhansak-collabora.cer", "collabora-ca/collabora-ca.cer", NULL);
+          "server-cert.cer", "certificate-authority.cer", NULL);
 
   /* We add the collabora directory with the collabora root */
-  add_pkcs11_module_for_testing (test, "gkm-roots-store-standalone.so",
-          "collabora-ca");
+  add_certificate_to_mock (test, "certificate-authority.cer", NULL);
 
   ensure_certificate_proxy (test);
 
   /* Should be using the reference_identities and not host name for checks */
-  verifier = empathy_tls_verifier_new (test->cert, "www.collabora.co.uk",
+  verifier = empathy_tls_verifier_new (test->cert, "test-server.empathy.gnome.org",
       reference_identities);
   empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test);
   g_main_loop_run (test->loop);
 
-  if (empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
-          NULL, &error))
-    g_assert_not_reached ();
+  empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
+      NULL, &error);
 
   /* And it should say we're self-signed (oddly enough) */
-  g_assert_cmpuint (reason, ==, EMP_TLS_CERTIFICATE_REJECT_REASON_HOSTNAME_MISMATCH);
+  g_assert_error (error, G_IO_ERROR,
+      TP_TLS_CERTIFICATE_REJECT_REASON_HOSTNAME_MISMATCH);
+
+  g_clear_error (&error);
+  g_object_unref (verifier);
+}
+
+static void
+test_certificate_verify_success_with_pinned (Test *test,
+        gconstpointer data G_GNUC_UNUSED)
+{
+  TpTLSCertificateRejectReason reason = 0;
+  GError *error = NULL;
+  EmpathyTLSVerifier *verifier;
+  const gchar *reference_identities[] = {
+    "test-server.empathy.gnome.org",
+    NULL
+  };
+
+  /*
+   * In this test the mock TLS connection has a full certificate
+   * chain. We look for an anchor certificate in the chain.
+   */
+
+  test->mock = mock_tls_certificate_new_and_register (test->dbus,
+          "server-cert.cer", NULL);
+
+  /* We add the collabora directory with the collabora root */
+  add_certificate_to_mock (test, "server-cert.cer", "test-server.empathy.gnome.org");
+
+  ensure_certificate_proxy (test);
+
+  verifier = empathy_tls_verifier_new (test->cert, "test-server.empathy.gnome.org",
+      reference_identities);
+  empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test);
+  g_main_loop_run (test->loop);
+  empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
+      NULL, &error);
+  g_assert_no_error (error);
+
+  /* Yay the verification was a success! */
+
+  g_clear_error (&error);
+  g_object_unref (verifier);
+}
+
+static void
+test_certificate_verify_pinned_wrong_host (Test *test,
+        gconstpointer data G_GNUC_UNUSED)
+{
+  TpTLSCertificateRejectReason reason = 0;
+  GError *error = NULL;
+  EmpathyTLSVerifier *verifier;
+  const gchar *reference_identities[] = {
+    "test-server.empathy.gnome.org",
+    NULL
+  };
+
+  test->mock = mock_tls_certificate_new_and_register (test->dbus,
+          "server-cert.cer", NULL);
+
+  /* Note that we're not adding any place to find root certs */
+
+  ensure_certificate_proxy (test);
+
+  verifier = empathy_tls_verifier_new (test->cert, "another.gnome.org",
+      reference_identities);
+  empathy_tls_verifier_verify_async (verifier, fetch_callback_result, test);
+  g_main_loop_run (test->loop);
+
+  empathy_tls_verifier_verify_finish (verifier, test->result, &reason,
+      NULL, &error);
+
+  /* And it should say we're self-signed */
+  g_assert_error (error, G_IO_ERROR,
+      TP_TLS_CERTIFICATE_REJECT_REASON_SELF_SIGNED);
 
   g_clear_error (&error);
   g_object_unref (verifier);
@@ -672,6 +738,10 @@ main (int argc,
           setup, test_certificate_verify_identities_invalid, teardown);
   g_test_add ("/tls/certificate_verify_uses_reference_identities", Test, NULL,
           setup, test_certificate_verify_uses_reference_identities, teardown);
+  g_test_add ("/tls/certificate_verify_success_with_pinned", Test, NULL,
+          setup, test_certificate_verify_success_with_pinned, teardown);
+  g_test_add ("/tls/certificate_verify_pinned_wrong_host", Test, NULL,
+          setup, test_certificate_verify_pinned_wrong_host, teardown);
 
   result = g_test_run ();
   test_deinit ();