/* GLib testing framework examples and tests * * Copyright (C) 2008-2013 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. * * Author: David Zeuthen */ #include #include #include #include #include "gdbus-tests.h" #ifdef G_OS_UNIX #include #include #include #include #endif /* ---------------------------------------------------------------------------------------------------- */ static gboolean server_on_allow_mechanism (GDBusAuthObserver *observer, const gchar *mechanism, gpointer user_data) { const gchar *allowed_mechanism = user_data; if (allowed_mechanism == NULL || g_strcmp0 (mechanism, allowed_mechanism) == 0) return TRUE; else return FALSE; } /* pass NULL to allow any mechanism */ static GDBusServer * server_new_for_mechanism (const gchar *allowed_mechanism) { gchar *addr; gchar *guid; GDBusServer *server; GDBusAuthObserver *auth_observer; GError *error; GDBusServerFlags flags; guid = g_dbus_generate_guid (); #ifdef G_OS_UNIX if (g_unix_socket_address_abstract_names_supported ()) { addr = g_strdup ("unix:tmpdir=/tmp/gdbus-test-"); } else { gchar *tmpdir; tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL); addr = g_strdup_printf ("unix:tmpdir=%s", tmpdir); g_free (tmpdir); } #else addr = g_strdup ("nonce-tcp:"); #endif auth_observer = g_dbus_auth_observer_new (); flags = G_DBUS_SERVER_FLAGS_NONE; if (g_strcmp0 (allowed_mechanism, "ANONYMOUS") == 0) flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; error = NULL; server = g_dbus_server_new_sync (addr, flags, guid, auth_observer, NULL, /* cancellable */ &error); g_assert_no_error (error); g_assert (server != NULL); g_signal_connect (auth_observer, "allow-mechanism", G_CALLBACK (server_on_allow_mechanism), (gpointer) allowed_mechanism); g_free (addr); g_free (guid); g_object_unref (auth_observer); return server; } /* ---------------------------------------------------------------------------------------------------- */ static gboolean test_auth_on_new_connection (GDBusServer *server, GDBusConnection *connection, gpointer user_data) { GMainLoop *loop = user_data; g_main_loop_quit (loop); return FALSE; } static gboolean test_auth_on_timeout (gpointer user_data) { g_error ("Timeout waiting for client"); g_assert_not_reached (); return FALSE; } typedef struct { const gchar *address; const gchar *allowed_client_mechanism; const gchar *allowed_server_mechanism; } TestAuthData; static gpointer test_auth_client_thread_func (gpointer user_data) { TestAuthData *data = user_data; GDBusConnection *c = NULL; GError *error = NULL; GDBusAuthObserver *auth_observer = NULL; auth_observer = g_dbus_auth_observer_new (); g_signal_connect (auth_observer, "allow-mechanism", G_CALLBACK (server_on_allow_mechanism), (gpointer) data->allowed_client_mechanism); c = g_dbus_connection_new_for_address_sync (data->address, G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, auth_observer, NULL, /* GCancellable */ &error); g_assert_no_error (error); g_assert (c != NULL); g_clear_object (&c); g_clear_object (&auth_observer); return NULL; } static void test_auth_mechanism (const gchar *allowed_client_mechanism, const gchar *allowed_server_mechanism) { GDBusServer *server; GMainLoop *loop; GThread *client_thread; TestAuthData data; server = server_new_for_mechanism (allowed_server_mechanism); loop = g_main_loop_new (NULL, FALSE); g_signal_connect (server, "new-connection", G_CALLBACK (test_auth_on_new_connection), loop); g_timeout_add_seconds (5, test_auth_on_timeout, NULL); data.allowed_client_mechanism = allowed_client_mechanism; data.allowed_server_mechanism = allowed_server_mechanism; data.address = g_dbus_server_get_client_address (server); /* run the D-Bus client in a thread */ client_thread = g_thread_new ("gdbus-client-thread", test_auth_client_thread_func, &data); g_dbus_server_start (server); g_main_loop_run (loop); g_dbus_server_stop (server); g_thread_join (client_thread); while (g_main_context_iteration (NULL, FALSE)); g_main_loop_unref (loop); g_object_unref (server); } /* ---------------------------------------------------------------------------------------------------- */ static void auth_client_external (void) { test_auth_mechanism ("EXTERNAL", NULL); } static void auth_client_dbus_cookie_sha1 (void) { test_auth_mechanism ("DBUS_COOKIE_SHA1", NULL); } static void auth_server_anonymous (void) { test_auth_mechanism (NULL, "ANONYMOUS"); } static void auth_server_external (void) { test_auth_mechanism (NULL, "EXTERNAL"); } static void auth_server_dbus_cookie_sha1 (void) { test_auth_mechanism (NULL, "DBUS_COOKIE_SHA1"); } /* ---------------------------------------------------------------------------------------------------- */ static gchar *temp_dbus_keyrings_dir = NULL; static void temp_dbus_keyrings_setup (void) { GError *error = NULL; g_assert (temp_dbus_keyrings_dir == NULL); temp_dbus_keyrings_dir = g_dir_make_tmp ("gdbus-test-dbus-keyrings-XXXXXX", &error); g_assert_no_error (error); g_assert (temp_dbus_keyrings_dir != NULL); g_setenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR", temp_dbus_keyrings_dir, TRUE); g_setenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION", "1", TRUE); } static void temp_dbus_keyrings_teardown (void) { GDir *dir; GError *error = NULL; const gchar *name; g_assert (temp_dbus_keyrings_dir != NULL); dir = g_dir_open (temp_dbus_keyrings_dir, 0, &error); g_assert_no_error (error); g_assert (dir != NULL); while ((name = g_dir_read_name (dir)) != NULL) { gchar *path = g_build_filename (temp_dbus_keyrings_dir, name, NULL); g_assert (unlink (path) == 0); g_free (path); } g_dir_close (dir); g_assert (rmdir (temp_dbus_keyrings_dir) == 0); g_free (temp_dbus_keyrings_dir); temp_dbus_keyrings_dir = NULL; g_unsetenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR"); g_unsetenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION"); } /* ---------------------------------------------------------------------------------------------------- */ int main (int argc, char *argv[]) { gint ret; setlocale (LC_ALL, "C"); temp_dbus_keyrings_setup (); g_test_init (&argc, &argv, NULL); g_test_add_func ("/gdbus/auth/client/EXTERNAL", auth_client_external); g_test_add_func ("/gdbus/auth/client/DBUS_COOKIE_SHA1", auth_client_dbus_cookie_sha1); g_test_add_func ("/gdbus/auth/server/ANONYMOUS", auth_server_anonymous); g_test_add_func ("/gdbus/auth/server/EXTERNAL", auth_server_external); g_test_add_func ("/gdbus/auth/server/DBUS_COOKIE_SHA1", auth_server_dbus_cookie_sha1); /* TODO: we currently don't have tests for * * - DBUS_COOKIE_SHA1 timeouts (and clock changes etc) * - interoperability with libdbus-1 implementations of authentication methods (both client and server) */ ret = g_test_run(); temp_dbus_keyrings_teardown (); return ret; }