Branch data Line data Source code
1 : : /* GLib testing framework examples and tests
2 : : *
3 : : * Copyright (C) 2008-2013 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: David Zeuthen <davidz@redhat.com>
21 : : */
22 : :
23 : : #include <locale.h>
24 : : #include <gio/gio.h>
25 : :
26 : : #include <string.h>
27 : : #include <unistd.h>
28 : :
29 : : #include "gdbus-tests.h"
30 : :
31 : : #ifdef G_OS_UNIX
32 : : #include <gio/gunixconnection.h>
33 : : #include <gio/gnetworkingprivate.h>
34 : : #include <gio/gunixsocketaddress.h>
35 : : #include <gio/gunixfdlist.h>
36 : : #endif
37 : :
38 : : /* ---------------------------------------------------------------------------------------------------- */
39 : :
40 : : static gboolean
41 : 30 : server_on_allow_mechanism (GDBusAuthObserver *observer,
42 : : const gchar *mechanism,
43 : : gpointer user_data)
44 : : {
45 : 30 : const gchar *allowed_mechanism = user_data;
46 : 30 : if (allowed_mechanism == NULL || g_strcmp0 (mechanism, allowed_mechanism) == 0)
47 : 20 : return TRUE;
48 : : else
49 : 10 : return FALSE;
50 : : }
51 : :
52 : : /* pass NULL to allow any mechanism */
53 : : static GDBusServer *
54 : 5 : server_new_for_mechanism (const gchar *allowed_mechanism)
55 : : {
56 : : gchar *addr;
57 : : gchar *guid;
58 : : GDBusServer *server;
59 : : GDBusAuthObserver *auth_observer;
60 : : GError *error;
61 : : GDBusServerFlags flags;
62 : :
63 : 5 : guid = g_dbus_generate_guid ();
64 : :
65 : : #ifdef G_OS_UNIX
66 : : gchar *tmpdir;
67 : 5 : tmpdir = g_dir_make_tmp ("gdbus-test-XXXXXX", NULL);
68 : 5 : addr = g_strdup_printf ("unix:tmpdir=%s", tmpdir);
69 : 5 : g_free (tmpdir);
70 : : #else
71 : : addr = g_strdup ("nonce-tcp:");
72 : : #endif
73 : :
74 : 5 : auth_observer = g_dbus_auth_observer_new ();
75 : :
76 : 5 : flags = G_DBUS_SERVER_FLAGS_NONE;
77 : 5 : if (g_strcmp0 (allowed_mechanism, "ANONYMOUS") == 0)
78 : 1 : flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
79 : :
80 : 5 : error = NULL;
81 : 5 : server = g_dbus_server_new_sync (addr,
82 : : flags,
83 : : guid,
84 : : auth_observer,
85 : : NULL, /* cancellable */
86 : : &error);
87 : 5 : g_assert_no_error (error);
88 : 5 : g_assert (server != NULL);
89 : :
90 : 5 : g_signal_connect (auth_observer,
91 : : "allow-mechanism",
92 : : G_CALLBACK (server_on_allow_mechanism),
93 : : (gpointer) allowed_mechanism);
94 : :
95 : 5 : g_free (addr);
96 : 5 : g_free (guid);
97 : 5 : g_object_unref (auth_observer);
98 : :
99 : 5 : return server;
100 : : }
101 : :
102 : : /* ---------------------------------------------------------------------------------------------------- */
103 : :
104 : : static gboolean
105 : 5 : test_auth_on_new_connection (GDBusServer *server,
106 : : GDBusConnection *connection,
107 : : gpointer user_data)
108 : : {
109 : 5 : GMainLoop *loop = user_data;
110 : 5 : g_main_loop_quit (loop);
111 : 5 : return FALSE;
112 : : }
113 : :
114 : : typedef struct
115 : : {
116 : : const gchar *address;
117 : : const gchar *allowed_client_mechanism;
118 : : const gchar *allowed_server_mechanism;
119 : : } TestAuthData;
120 : :
121 : : static gpointer
122 : 5 : test_auth_client_thread_func (gpointer user_data)
123 : : {
124 : 5 : TestAuthData *data = user_data;
125 : 5 : GDBusConnection *c = NULL;
126 : 5 : GError *error = NULL;
127 : 5 : GDBusAuthObserver *auth_observer = NULL;
128 : :
129 : 5 : auth_observer = g_dbus_auth_observer_new ();
130 : :
131 : 5 : g_signal_connect (auth_observer,
132 : : "allow-mechanism",
133 : : G_CALLBACK (server_on_allow_mechanism),
134 : : (gpointer) data->allowed_client_mechanism);
135 : :
136 : 5 : c = g_dbus_connection_new_for_address_sync (data->address,
137 : : G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
138 : : auth_observer,
139 : : NULL, /* GCancellable */
140 : : &error);
141 : 5 : g_assert_no_error (error);
142 : 5 : g_assert (c != NULL);
143 : 5 : g_clear_object (&c);
144 : 5 : g_clear_object (&auth_observer);
145 : 5 : return NULL;
146 : : }
147 : :
148 : : static void
149 : 5 : test_auth_mechanism (const gchar *allowed_client_mechanism,
150 : : const gchar *allowed_server_mechanism)
151 : : {
152 : : GDBusServer *server;
153 : : GMainLoop *loop;
154 : : GThread *client_thread;
155 : : TestAuthData data;
156 : :
157 : 5 : server = server_new_for_mechanism (allowed_server_mechanism);
158 : :
159 : 5 : loop = g_main_loop_new (NULL, FALSE);
160 : :
161 : 5 : g_signal_connect (server,
162 : : "new-connection",
163 : : G_CALLBACK (test_auth_on_new_connection),
164 : : loop);
165 : :
166 : 5 : data.allowed_client_mechanism = allowed_client_mechanism;
167 : 5 : data.allowed_server_mechanism = allowed_server_mechanism;
168 : 5 : data.address = g_dbus_server_get_client_address (server);
169 : :
170 : : /* Run the D-Bus client in a thread. If this hangs forever, the test harness
171 : : * (typically Meson) will eventually kill the test. */
172 : 5 : client_thread = g_thread_new ("gdbus-client-thread",
173 : : test_auth_client_thread_func,
174 : : &data);
175 : :
176 : 5 : g_dbus_server_start (server);
177 : :
178 : 5 : g_main_loop_run (loop);
179 : :
180 : 5 : g_dbus_server_stop (server);
181 : :
182 : 5 : g_thread_join (client_thread);
183 : :
184 : 15 : while (g_main_context_iteration (NULL, FALSE));
185 : 5 : g_main_loop_unref (loop);
186 : :
187 : 5 : g_object_unref (server);
188 : 5 : }
189 : :
190 : : /* ---------------------------------------------------------------------------------------------------- */
191 : :
192 : : static void
193 : 1 : auth_client_external (void)
194 : : {
195 : 1 : test_auth_mechanism ("EXTERNAL", NULL);
196 : 1 : }
197 : :
198 : : static void
199 : 1 : auth_client_dbus_cookie_sha1 (void)
200 : : {
201 : 1 : test_auth_mechanism ("DBUS_COOKIE_SHA1", NULL);
202 : 1 : }
203 : :
204 : : static void
205 : 1 : auth_server_anonymous (void)
206 : : {
207 : 1 : test_auth_mechanism (NULL, "ANONYMOUS");
208 : 1 : }
209 : :
210 : : static void
211 : 1 : auth_server_external (void)
212 : : {
213 : 1 : test_auth_mechanism (NULL, "EXTERNAL");
214 : 1 : }
215 : :
216 : : static void
217 : 1 : auth_server_dbus_cookie_sha1 (void)
218 : : {
219 : 1 : test_auth_mechanism (NULL, "DBUS_COOKIE_SHA1");
220 : 1 : }
221 : :
222 : : /* ---------------------------------------------------------------------------------------------------- */
223 : :
224 : : static gchar *temp_dbus_keyrings_dir = NULL;
225 : :
226 : : static void
227 : 1 : temp_dbus_keyrings_setup (void)
228 : : {
229 : 1 : GError *error = NULL;
230 : :
231 : 1 : g_assert (temp_dbus_keyrings_dir == NULL);
232 : 1 : temp_dbus_keyrings_dir = g_dir_make_tmp ("gdbus-test-dbus-keyrings-XXXXXX", &error);
233 : 1 : g_assert_no_error (error);
234 : 1 : g_assert (temp_dbus_keyrings_dir != NULL);
235 : 1 : g_setenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR", temp_dbus_keyrings_dir, TRUE);
236 : 1 : g_setenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION", "1", TRUE);
237 : 1 : }
238 : :
239 : : static void
240 : 1 : temp_dbus_keyrings_teardown (void)
241 : : {
242 : : GDir *dir;
243 : 1 : GError *error = NULL;
244 : : const gchar *name;
245 : :
246 : 1 : g_assert (temp_dbus_keyrings_dir != NULL);
247 : :
248 : 1 : dir = g_dir_open (temp_dbus_keyrings_dir, 0, &error);
249 : 1 : g_assert_no_error (error);
250 : 1 : g_assert (dir != NULL);
251 : 2 : while ((name = g_dir_read_name (dir)) != NULL)
252 : : {
253 : 1 : gchar *path = g_build_filename (temp_dbus_keyrings_dir, name, NULL);
254 : 1 : g_assert (unlink (path) == 0);
255 : 1 : g_free (path);
256 : : }
257 : 1 : g_dir_close (dir);
258 : 1 : g_assert (rmdir (temp_dbus_keyrings_dir) == 0);
259 : :
260 : 1 : g_free (temp_dbus_keyrings_dir);
261 : 1 : temp_dbus_keyrings_dir = NULL;
262 : 1 : g_unsetenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR");
263 : 1 : g_unsetenv ("G_DBUS_COOKIE_SHA1_KEYRING_DIR_IGNORE_PERMISSION");
264 : 1 : }
265 : :
266 : : /* ---------------------------------------------------------------------------------------------------- */
267 : :
268 : : int
269 : 1 : main (int argc,
270 : : char *argv[])
271 : : {
272 : : gint ret;
273 : :
274 : 1 : setlocale (LC_ALL, "C");
275 : :
276 : 1 : temp_dbus_keyrings_setup ();
277 : :
278 : 1 : g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
279 : :
280 : 1 : g_test_add_func ("/gdbus/auth/client/EXTERNAL", auth_client_external);
281 : 1 : g_test_add_func ("/gdbus/auth/client/DBUS_COOKIE_SHA1", auth_client_dbus_cookie_sha1);
282 : 1 : g_test_add_func ("/gdbus/auth/server/ANONYMOUS", auth_server_anonymous);
283 : 1 : g_test_add_func ("/gdbus/auth/server/EXTERNAL", auth_server_external);
284 : 1 : g_test_add_func ("/gdbus/auth/server/DBUS_COOKIE_SHA1", auth_server_dbus_cookie_sha1);
285 : :
286 : : /* TODO: we currently don't have tests for
287 : : *
288 : : * - DBUS_COOKIE_SHA1 timeouts (and clock changes etc)
289 : : * - interoperability with libdbus-1 implementations of authentication methods (both client and server)
290 : : */
291 : :
292 : 1 : ret = g_test_run();
293 : :
294 : 1 : temp_dbus_keyrings_teardown ();
295 : :
296 : 1 : return ret;
297 : : }
|