diff --git a/gio/gcredentials.c b/gio/gcredentials.c index c350e3c88..c4794ded7 100644 --- a/gio/gcredentials.c +++ b/gio/gcredentials.c @@ -265,6 +265,35 @@ g_credentials_to_string (GCredentials *credentials) /* ---------------------------------------------------------------------------------------------------- */ +#if G_CREDENTIALS_USE_LINUX_UCRED +/* + * Check whether @native contains invalid data. If getsockopt SO_PEERCRED + * is used on a TCP socket, it succeeds but yields a credentials structure + * with pid 0, uid -1 and gid -1. Similarly, if SO_PASSCRED is used on a + * receiving Unix socket when the sending socket did not also enable + * SO_PASSCRED, it can succeed but yield a credentials structure with + * pid 0, uid /proc/sys/kernel/overflowuid and gid + * /proc/sys/kernel/overflowgid. + */ +static gboolean +linux_ucred_check_valid (struct ucred *native, + GError **error) +{ + if (native->pid == 0 + || native->uid == -1 + || native->gid == -1) + { + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + _("GCredentials contains invalid data")); + return FALSE; + } + + return TRUE; +} +#endif + /** * g_credentials_is_same_user: * @credentials: A #GCredentials. @@ -294,7 +323,8 @@ g_credentials_is_same_user (GCredentials *credentials, ret = FALSE; #if G_CREDENTIALS_USE_LINUX_UCRED - if (credentials->native.uid == other_credentials->native.uid) + if (linux_ucred_check_valid (&credentials->native, NULL) + && credentials->native.uid == other_credentials->native.uid) ret = TRUE; #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid) @@ -453,7 +483,10 @@ g_credentials_get_unix_user (GCredentials *credentials, g_return_val_if_fail (error == NULL || *error == NULL, -1); #if G_CREDENTIALS_USE_LINUX_UCRED - ret = credentials->native.uid; + if (linux_ucred_check_valid (&credentials->native, error)) + ret = credentials->native.uid; + else + ret = -1; #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED ret = credentials->native.cmcred_euid; #elif G_CREDENTIALS_USE_NETBSD_UNPCBID @@ -499,7 +532,10 @@ g_credentials_get_unix_pid (GCredentials *credentials, g_return_val_if_fail (error == NULL || *error == NULL, -1); #if G_CREDENTIALS_USE_LINUX_UCRED - ret = credentials->native.pid; + if (linux_ucred_check_valid (&credentials->native, error)) + ret = credentials->native.pid; + else + ret = -1; #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED ret = credentials->native.cmcred_pid; #elif G_CREDENTIALS_USE_NETBSD_UNPCBID diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h index 4d1c420a8..e9ec09b9f 100644 --- a/gio/gcredentialsprivate.h +++ b/gio/gcredentialsprivate.h @@ -22,6 +22,77 @@ #include "gio/gcredentials.h" #include "gio/gnetworking.h" +/* + * G_CREDENTIALS_SUPPORTED: + * + * Defined to 1 if GCredentials works. + */ +#undef G_CREDENTIALS_SUPPORTED + +/* + * G_CREDENTIALS_USE_LINUX_UCRED, etc.: + * + * Defined to 1 if GCredentials uses Linux `struct ucred`, etc. + */ +#undef G_CREDENTIALS_USE_LINUX_UCRED +#undef G_CREDENTIALS_USE_FREEBSD_CMSGCRED +#undef G_CREDENTIALS_USE_NETBSD_UNPCBID +#undef G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED +#undef G_CREDENTIALS_USE_SOLARIS_UCRED + +/* + * G_CREDENTIALS_NATIVE_TYPE: + * + * Defined to one of G_CREDENTIALS_TYPE_LINUX_UCRED, etc. + */ +#undef G_CREDENTIALS_NATIVE_TYPE + +/* + * G_CREDENTIALS_NATIVE_SIZE: + * + * Defined to the size of the %G_CREDENTIALS_NATIVE_TYPE + */ +#undef G_CREDENTIALS_NATIVE_SIZE + +/* + * G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED: + * + * Defined to 1 if we have a message-passing API in which credentials + * are attached to a particular message, such as `SCM_CREDENTIALS` on Linux + * or `SCM_CREDS` on FreeBSD. + */ +#undef G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED + +/* + * G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED: + * + * Defined to 1 if we have a `getsockopt()`-style API in which one end of + * a socket connection can directly query the credentials of the process + * that initiated the other end, such as `getsockopt SO_PEERCRED` on Linux + * or `getpeereid()` on multiple operating systems. + */ +#undef G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED + +/* + * G_CREDENTIALS_SPOOFING_SUPPORTED: + * + * Defined to 1 if privileged processes can spoof their credentials when + * using the message-passing API. + */ +#undef G_CREDENTIALS_SPOOFING_SUPPORTED + +/* + * G_CREDENTIALS_PREFER_MESSAGE_PASSING: + * + * Defined to 1 if the data structure transferred by the message-passing + * API is strictly more informative than the one transferred by the + * `getsockopt()`-style API, and hence should be preferred, even for + * protocols like D-Bus that are defined in terms of the credentials of + * the (process that opened the) socket, as opposed to the credentials + * of an individual message. + */ +#undef G_CREDENTIALS_PREFER_MESSAGE_PASSING + #ifdef __linux__ #define G_CREDENTIALS_SUPPORTED 1 #define G_CREDENTIALS_USE_LINUX_UCRED 1 @@ -41,6 +112,12 @@ #define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct cmsgcred)) #define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 #define G_CREDENTIALS_SPOOFING_SUPPORTED 1 +/* GLib doesn't implement it yet, but FreeBSD's getsockopt()-style API + * is getpeereid(), which is not as informative as struct cmsgcred - + * it does not tell us the PID. As a result, libdbus prefers to use + * SCM_CREDS, and if we implement getpeereid() in future, we should + * do the same. */ +#define G_CREDENTIALS_PREFER_MESSAGE_PASSING 1 #elif defined(__NetBSD__) #define G_CREDENTIALS_SUPPORTED 1 diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c index 752ec23fc..14cc5d70e 100644 --- a/gio/gdbusauth.c +++ b/gio/gdbusauth.c @@ -31,6 +31,7 @@ #include "gdbusutils.h" #include "gioenumtypes.h" #include "gcredentials.h" +#include "gcredentialsprivate.h" #include "gdbusprivate.h" #include "giostream.h" #include "gdatainputstream.h" @@ -969,9 +970,31 @@ _g_dbus_auth_run_server (GDBusAuth *auth, g_data_input_stream_set_newline_type (dis, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); - /* first read the NUL-byte */ + /* read the NUL-byte, possibly with credentials attached */ #ifdef G_OS_UNIX - if (G_IS_UNIX_CONNECTION (auth->priv->stream)) +#ifndef G_CREDENTIALS_PREFER_MESSAGE_PASSING + if (G_IS_SOCKET_CONNECTION (auth->priv->stream)) + { + GSocket *sock = g_socket_connection_get_socket (G_SOCKET_CONNECTION (auth->priv->stream)); + + local_error = NULL; + credentials = g_socket_get_credentials (sock, &local_error); + + if (credentials == NULL && !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) + { + g_propagate_error (error, local_error); + goto out; + } + else + { + /* Clear the error indicator, so we can retry with + * g_unix_connection_receive_credentials() if necessary */ + g_clear_error (&local_error); + } + } +#endif + + if (credentials == NULL && G_IS_UNIX_CONNECTION (auth->priv->stream)) { local_error = NULL; credentials = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (auth->priv->stream), diff --git a/gio/tests/gdbus-server-auth.c b/gio/tests/gdbus-server-auth.c new file mode 100644 index 000000000..6a72ba6c1 --- /dev/null +++ b/gio/tests/gdbus-server-auth.c @@ -0,0 +1,491 @@ +/* + * Copyright 2019 Collabora Ltd. + * + * 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.1 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, see . + */ + +#include "config.h" + +#include + +#ifdef HAVE_DBUS1 +#include +#endif + +typedef enum +{ + INTEROP_FLAGS_EXTERNAL = (1 << 0), + INTEROP_FLAGS_ANONYMOUS = (1 << 1), + INTEROP_FLAGS_SHA1 = (1 << 2), + INTEROP_FLAGS_TCP = (1 << 3), + INTEROP_FLAGS_LIBDBUS = (1 << 4), + INTEROP_FLAGS_NONE = 0 +} InteropFlags; + +static gboolean +allow_external_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + const char *mechanism, + G_GNUC_UNUSED gpointer user_data) +{ + if (g_strcmp0 (mechanism, "EXTERNAL") == 0) + { + g_debug ("Accepting EXTERNAL authentication"); + return TRUE; + } + else + { + g_debug ("Rejecting \"%s\" authentication: not EXTERNAL", mechanism); + return FALSE; + } +} + +static gboolean +allow_anonymous_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + const char *mechanism, + G_GNUC_UNUSED gpointer user_data) +{ + if (g_strcmp0 (mechanism, "ANONYMOUS") == 0) + { + g_debug ("Accepting ANONYMOUS authentication"); + return TRUE; + } + else + { + g_debug ("Rejecting \"%s\" authentication: not ANONYMOUS", mechanism); + return FALSE; + } +} + +static gboolean +allow_sha1_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + const char *mechanism, + G_GNUC_UNUSED gpointer user_data) +{ + if (g_strcmp0 (mechanism, "DBUS_COOKIE_SHA1") == 0) + { + g_debug ("Accepting DBUS_COOKIE_SHA1 authentication"); + return TRUE; + } + else + { + g_debug ("Rejecting \"%s\" authentication: not DBUS_COOKIE_SHA1", + mechanism); + return FALSE; + } +} + +static gboolean +allow_any_mechanism_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + const char *mechanism, + G_GNUC_UNUSED gpointer user_data) +{ + g_debug ("Accepting \"%s\" authentication", mechanism); + return TRUE; +} + +static gboolean +authorize_any_authenticated_peer_cb (G_GNUC_UNUSED GDBusAuthObserver *observer, + G_GNUC_UNUSED GIOStream *stream, + GCredentials *credentials, + G_GNUC_UNUSED gpointer user_data) +{ + if (credentials == NULL) + { + g_debug ("Authorizing peer with no credentials"); + } + else + { + gchar *str = g_credentials_to_string (credentials); + + g_debug ("Authorizing peer with credentials: %s", str); + g_free (str); + } + + return TRUE; +} + +static GDBusMessage * +whoami_filter_cb (GDBusConnection *connection, + GDBusMessage *message, + gboolean incoming, + G_GNUC_UNUSED gpointer user_data) +{ + if (!incoming) + return message; + + if (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL && + g_strcmp0 (g_dbus_message_get_member (message), "WhoAmI") == 0) + { + GDBusMessage *reply = g_dbus_message_new_method_reply (message); + gint64 uid = -1; + gint64 pid = -1; +#ifdef G_OS_UNIX + GCredentials *credentials = g_dbus_connection_get_peer_credentials (connection); + + if (credentials != NULL) + { + uid = (gint64) g_credentials_get_unix_user (credentials, NULL); + pid = (gint64) g_credentials_get_unix_pid (credentials, NULL); + } +#endif + + g_dbus_message_set_body (reply, + g_variant_new ("(xx)", uid, pid)); + g_dbus_connection_send_message (connection, reply, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + NULL, NULL); + + /* handled */ + g_object_unref (message); + return NULL; + } + + return message; +} + +static gboolean +new_connection_cb (G_GNUC_UNUSED GDBusServer *server, + GDBusConnection *connection, + G_GNUC_UNUSED gpointer user_data) +{ + GCredentials *credentials = g_dbus_connection_get_peer_credentials (connection); + + if (credentials == NULL) + { + g_debug ("New connection from peer with no credentials"); + } + else + { + gchar *str = g_credentials_to_string (credentials); + + g_debug ("New connection from peer with credentials: %s", str); + g_free (str); + } + + g_object_ref (connection); + g_dbus_connection_add_filter (connection, whoami_filter_cb, NULL, NULL); + return TRUE; +} + +#ifdef HAVE_DBUS1 +typedef struct +{ + DBusError error; + DBusConnection *conn; + DBusMessage *call; + DBusMessage *reply; +} LibdbusCall; + +static void +libdbus_call_task_cb (GTask *task, + G_GNUC_UNUSED gpointer source_object, + gpointer task_data, + G_GNUC_UNUSED GCancellable *cancellable) +{ + LibdbusCall *libdbus_call = task_data; + + libdbus_call->reply = dbus_connection_send_with_reply_and_block (libdbus_call->conn, + libdbus_call->call, + -1, + &libdbus_call->error); +} +#endif /* HAVE_DBUS1 */ + +static void +store_result_cb (G_GNUC_UNUSED GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GAsyncResult **result = user_data; + + g_assert_nonnull (result); + g_assert_null (*result); + *result = g_object_ref (res); +} + +static void +assert_expected_uid_pid (InteropFlags flags, + gint64 uid, + gint64 pid) +{ +#ifdef G_OS_UNIX + if (flags & (INTEROP_FLAGS_ANONYMOUS | INTEROP_FLAGS_SHA1 | INTEROP_FLAGS_TCP)) + { + /* No assertion. There is no guarantee whether credentials will be + * passed even though we didn't send them. Conversely, if + * credentials were not passed, + * g_dbus_connection_get_peer_credentials() always returns the + * credentials of the socket, and not the uid that a + * client might have proved it has by using DBUS_COOKIE_SHA1. */ + } + else /* We should prefer EXTERNAL whenever it is allowed. */ + { +#ifdef __linux__ + /* We know that both GDBus and libdbus support full credentials-passing + * on Linux. */ + g_assert_cmpint (uid, ==, getuid ()); + g_assert_cmpint (pid, ==, getpid ()); +#else + g_test_message ("Please open a merge request to add appropriate " + "assertions for your platform"); +#endif + } +#endif /* G_OS_UNIX */ +} + +static void +do_test_server_auth (const char *listenable_address, + InteropFlags flags) +{ + GError *error = NULL; + GDBusServer *server; + GDBusAuthObserver *observer; + GDBusServerFlags server_flags = G_DBUS_SERVER_FLAGS_RUN_IN_THREAD; + gchar *guid; + const char *connectable_address; + GDBusConnection *client; + GAsyncResult *result = NULL; + GVariant *tuple; + gint64 uid, pid; +#ifdef HAVE_DBUS1 + /* GNOME/glib#1831 seems to involve a race condition, so try a few times + * to see if we can trigger it. */ + gsize i; + gsize n = 20; +#endif + + if (g_str_has_prefix (listenable_address, "tcp:") || + g_str_has_prefix (listenable_address, "nonce-tcp:")) + g_assert_cmpint (flags & INTEROP_FLAGS_TCP, !=, 0); + else + g_assert_cmpint (flags & INTEROP_FLAGS_TCP, ==, 0); + + g_test_message ("Testing GDBus server at %s / libdbus client, with flags: " + "external:%s " + "anonymous:%s " + "sha1:%s " + "tcp:%s", + listenable_address, + (flags & INTEROP_FLAGS_EXTERNAL) ? "true" : "false", + (flags & INTEROP_FLAGS_ANONYMOUS) ? "true" : "false", + (flags & INTEROP_FLAGS_SHA1) ? "true" : "false", + (flags & INTEROP_FLAGS_TCP) ? "true" : "false"); + +#ifndef G_OS_UNIX + if (g_str_has_prefix (listenable_address, "unix:")) + { + g_test_skip ("unix: addresses only work on Unix"); + return; + } +#endif + +#if !defined(G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED) \ + && !defined(G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED) + if (flags & INTEROP_FLAGS_EXTERNAL) + { + g_test_skip ("EXTERNAL authentication not implemented on this platform"); + return; + } +#endif + + if (flags & INTEROP_FLAGS_ANONYMOUS) + server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; + + observer = g_dbus_auth_observer_new (); + + if (flags & INTEROP_FLAGS_EXTERNAL) + g_signal_connect (observer, "allow-mechanism", + G_CALLBACK (allow_external_cb), NULL); + else if (flags & INTEROP_FLAGS_ANONYMOUS) + g_signal_connect (observer, "allow-mechanism", + G_CALLBACK (allow_anonymous_cb), NULL); + else if (flags & INTEROP_FLAGS_SHA1) + g_signal_connect (observer, "allow-mechanism", + G_CALLBACK (allow_sha1_cb), NULL); + else + g_signal_connect (observer, "allow-mechanism", + G_CALLBACK (allow_any_mechanism_cb), NULL); + + g_signal_connect (observer, "authorize-authenticated-peer", + G_CALLBACK (authorize_any_authenticated_peer_cb), + NULL); + + guid = g_dbus_generate_guid (); + server = g_dbus_server_new_sync (listenable_address, + server_flags, + guid, + observer, + NULL, + &error); + g_assert_no_error (error); + g_assert_nonnull (server); + g_signal_connect (server, "new-connection", G_CALLBACK (new_connection_cb), NULL); + g_dbus_server_start (server); + connectable_address = g_dbus_server_get_client_address (server); + + result = NULL; + g_dbus_connection_new_for_address (connectable_address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, NULL, store_result_cb, &result); + + while (result == NULL) + g_main_context_iteration (NULL, TRUE); + + client = g_dbus_connection_new_for_address_finish (result, &error); + g_assert_no_error (error); + g_assert_nonnull (client); + g_clear_object (&result); + + g_dbus_connection_call (client, NULL, "/", "com.example.Test", "WhoAmI", + NULL, G_VARIANT_TYPE ("(xx)"), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, store_result_cb, + &result); + + while (result == NULL) + g_main_context_iteration (NULL, TRUE); + + tuple = g_dbus_connection_call_finish (client, result, &error); + g_assert_no_error (error); + g_assert_nonnull (tuple); + g_clear_object (&result); + g_clear_object (&client); + + uid = -2; + pid = -2; + g_variant_get (tuple, "(xx)", &uid, &pid); + + g_debug ("Server says GDBus client is uid %" G_GINT64_FORMAT ", pid %" G_GINT64_FORMAT, + uid, pid); + + assert_expected_uid_pid (flags, uid, pid); + + g_clear_pointer (&tuple, g_variant_unref); + +#ifdef HAVE_DBUS1 + for (i = 0; i < n; i++) + { + LibdbusCall libdbus_call = { DBUS_ERROR_INIT, NULL, NULL, NULL }; + GTask *task; + + libdbus_call.conn = dbus_connection_open_private (connectable_address, + &libdbus_call.error); + g_assert_cmpstr (libdbus_call.error.name, ==, NULL); + g_assert_nonnull (libdbus_call.conn); + + libdbus_call.call = dbus_message_new_method_call (NULL, "/", + "com.example.Test", + "WhoAmI"); + + if (libdbus_call.call == NULL) + g_error ("Out of memory"); + + result = NULL; + task = g_task_new (NULL, NULL, store_result_cb, &result); + g_task_set_task_data (task, &libdbus_call, NULL); + g_task_run_in_thread (task, libdbus_call_task_cb); + + while (result == NULL) + g_main_context_iteration (NULL, TRUE); + + g_clear_object (&result); + + g_assert_cmpstr (libdbus_call.error.name, ==, NULL); + g_assert_nonnull (libdbus_call.reply); + + uid = -2; + pid = -2; + dbus_message_get_args (libdbus_call.reply, &libdbus_call.error, + DBUS_TYPE_INT64, &uid, + DBUS_TYPE_INT64, &pid, + DBUS_TYPE_INVALID); + g_assert_cmpstr (libdbus_call.error.name, ==, NULL); + + g_debug ("Server says libdbus client %" G_GSIZE_FORMAT " is uid %" G_GINT64_FORMAT ", pid %" G_GINT64_FORMAT, + i, uid, pid); + assert_expected_uid_pid (flags | INTEROP_FLAGS_LIBDBUS, uid, pid); + + dbus_connection_close (libdbus_call.conn); + dbus_connection_unref (libdbus_call.conn); + dbus_message_unref (libdbus_call.call); + dbus_message_unref (libdbus_call.reply); + g_clear_object (&task); + } +#else /* !HAVE_DBUS1 */ + g_test_skip ("Testing interop with libdbus not supported"); +#endif /* !HAVE_DBUS1 */ + + g_dbus_server_stop (server); + g_clear_object (&server); + g_clear_object (&observer); + g_free (guid); +} + +static void +test_server_auth (void) +{ + do_test_server_auth ("unix:tmpdir=/tmp/gdbus-test", INTEROP_FLAGS_NONE); +} + +static void +test_server_auth_tcp (void) +{ + do_test_server_auth ("tcp:host=127.0.0.1", INTEROP_FLAGS_TCP); +} + +static void +test_server_auth_anonymous (void) +{ + do_test_server_auth ("unix:tmpdir=/tmp/gdbus-test", INTEROP_FLAGS_ANONYMOUS); +} + +static void +test_server_auth_anonymous_tcp (void) +{ + do_test_server_auth ("tcp:host=127.0.0.1", INTEROP_FLAGS_ANONYMOUS | INTEROP_FLAGS_TCP); +} + +static void +test_server_auth_external (void) +{ + do_test_server_auth ("unix:tmpdir=/tmp/gdbus-test", INTEROP_FLAGS_EXTERNAL); +} + +static void +test_server_auth_sha1 (void) +{ + do_test_server_auth ("unix:tmpdir=/tmp/gdbus-test", INTEROP_FLAGS_SHA1); +} + +static void +test_server_auth_sha1_tcp (void) +{ + do_test_server_auth ("tcp:host=127.0.0.1", INTEROP_FLAGS_SHA1 | INTEROP_FLAGS_TCP); +} + +int +main (int argc, + char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/gdbus/server-auth", test_server_auth); + g_test_add_func ("/gdbus/server-auth/tcp", test_server_auth_tcp); + g_test_add_func ("/gdbus/server-auth/anonymous", test_server_auth_anonymous); + g_test_add_func ("/gdbus/server-auth/anonymous/tcp", test_server_auth_anonymous_tcp); + g_test_add_func ("/gdbus/server-auth/external", test_server_auth_external); + g_test_add_func ("/gdbus/server-auth/sha1", test_server_auth_sha1); + g_test_add_func ("/gdbus/server-auth/sha1/tcp", test_server_auth_sha1_tcp); + + return g_test_run(); +} diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 382dfccad..2c84a20f3 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -115,7 +115,15 @@ if dbus1_dep.found() 'gdbus-serialization' : { 'extra_sources' : ['gdbus-tests.c'], 'dependencies' : [dbus1_dep], - } + }, + 'gdbus-server-auth' : { + 'dependencies' : [dbus1_dep], + }, + } +else + # We can build a cut-down version of this test without libdbus + gio_tests += { + 'gdbus-server-auth' : {}, } endif