mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-31 04:43:06 +02:00
This greatly simplifies the test since everything is now in a single process and possible bugs / quirks in libdbus-1 will not interfere with the tests. On the other hand, we no longer test interoperability with libdbus-1. This is somewhat moot, however, since other tests that involve a message bus (e.g. GTestDBus users which include most of the GDBus test suite itself) will test this. Also ensure that we don't pollute existing D-Bus keyrings for the DBUS_COOKIE_SHA1 authentication method (e.g. files in the ~/.dbus-keyrings directory) by setting the environment variables G_DBUS_COOKIE_SHA1_KEYRING_DIR and G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION. All in all, this change avoids some thorny issues where the GDBus and libdbus-1 implementations disagree on whether an item in the D-Bus keyring is still valid (items have an age etc.). In reality, since the DBUS_COOKIE_SHA1 authentication method is never used in production, this is never hit in production. This bug was, however, frequently hit if you just ran the test suite repeatedly for 15 minutes or so. Also add TODO items to mention that we currently don't test corner cases involving - DBUS_COOKIE_SHA1 timeouts - libdbus-1 interoperability Signed-off-by: David Zeuthen <zeuthen@gmail.com>
313 lines
8.4 KiB
C
313 lines
8.4 KiB
C
/* 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 <davidz@redhat.com>
|
|
*/
|
|
|
|
#include <locale.h>
|
|
#include <gio/gio.h>
|
|
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <dbus/dbus.h>
|
|
|
|
#include "gdbus-tests.h"
|
|
|
|
#ifdef G_OS_UNIX
|
|
#include <gio/gunixconnection.h>
|
|
#include <gio/gnetworkingprivate.h>
|
|
#include <gio/gunixsocketaddress.h>
|
|
#include <gio/gunixfdlist.h>
|
|
#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);
|
|
|
|
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);
|
|
|
|
temp_dbus_keyrings_dir = NULL;
|
|
g_setenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR", NULL, TRUE);
|
|
g_setenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION", NULL, TRUE);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
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;
|
|
}
|
|
|