[daemon-fix] Fixed sending daemon match rules for kdbus broadcasts
[platform/upstream/dbus.git] / test / manual-authz.c
1 /* Simple sanity-check for authentication and authorization.
2  *
3  * Copyright © 2010-2011 Nokia Corporation
4  * Copyright © 2012 Collabora Ltd.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation files
8  * (the "Software"), to deal in the Software without restriction,
9  * including without limitation the rights to use, copy, modify, merge,
10  * publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26
27 #include <config.h>
28
29 #include <glib.h>
30
31 #include <dbus/dbus.h>
32
33 #ifdef G_OS_UNIX
34 #include <unistd.h>
35 #include <sys/types.h>
36 #endif
37
38 #include "test-utils.h"
39
40 typedef struct {
41     DBusError e;
42     TestMainContext *ctx;
43
44     DBusServer *normal_server;
45     DBusServer *anon_allowed_server;
46     DBusServer *anon_only_server;
47     DBusServer *anon_mech_only_server;
48     DBusServer *anon_disallowed_server;
49     DBusServer *permissive_server;
50     DBusServer *unhappy_server;
51     DBusServer *same_uid_server;
52     DBusServer *same_uid_or_anon_server;
53 } Fixture;
54
55 static void oom (void) G_GNUC_NORETURN;
56 static void
57 oom (void)
58 {
59   g_error ("out of memory");
60 }
61
62 static void
63 assert_no_error (const DBusError *e)
64 {
65   if (G_UNLIKELY (dbus_error_is_set (e)))
66     g_error ("expected success but got error: %s: %s", e->name, e->message);
67 }
68
69 static DBusHandlerResult
70 server_message_cb (DBusConnection *conn,
71     DBusMessage *message,
72     void *data)
73 {
74   if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected"))
75     {
76       dbus_connection_unref (conn);
77
78       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
79     }
80
81   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
82     {
83       DBusMessage *reply = dbus_message_new_method_return (message);
84       const char *hello = "Hello, world!";
85       unsigned long uid;
86       char *sid;
87
88       if (dbus_connection_get_unix_user (conn, &uid))
89         {
90           g_message ("message from uid %lu", uid);
91         }
92       else if (dbus_connection_get_windows_user (conn, &sid))
93         {
94           if (sid == NULL)
95             oom ();
96
97           g_message ("message from sid \"%s\"", sid);
98           dbus_free (sid);
99         }
100       else if (dbus_connection_get_is_anonymous (conn))
101         {
102           g_message ("message from Anonymous");
103         }
104       else
105         {
106           g_message ("message from ... someone?");
107         }
108
109       if (reply == NULL)
110         oom ();
111
112       if (!dbus_message_append_args (reply,
113             DBUS_TYPE_STRING, &hello,
114             DBUS_TYPE_INVALID))
115         oom ();
116
117       if (!dbus_connection_send (conn, reply, NULL))
118         oom ();
119
120       dbus_message_unref (reply);
121
122       return DBUS_HANDLER_RESULT_HANDLED;
123     }
124
125   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
126 }
127
128 static dbus_bool_t
129 permissive_unix_func (DBusConnection *conn,
130     unsigned long uid,
131     void *data)
132 {
133   g_message ("accepting Unix user %lu", uid);
134   return TRUE;
135 }
136
137 static dbus_bool_t
138 permissive_win_func (DBusConnection *conn,
139     const char *sid,
140     void *data)
141 {
142   g_message ("accepting Windows user \"%s\"", sid);
143   return TRUE;
144 }
145
146 static dbus_bool_t
147 broken_unix_func (DBusConnection *conn,
148     unsigned long uid,
149     void *data)
150 {
151   g_error ("libdbus called the Unix user function for an ANONYMOUS-only "
152       "connection");
153   return FALSE;
154 }
155
156 static dbus_bool_t
157 broken_win_func (DBusConnection *conn,
158     const char *sid,
159     void *data)
160 {
161   g_error ("libdbus called the Windows user function for an ANONYMOUS-only "
162       "connection");
163   return FALSE;
164 }
165
166 static dbus_bool_t
167 unhappy_unix_func (DBusConnection *conn,
168     unsigned long uid,
169     void *data)
170 {
171   g_message ("rejecting Unix user %lu", uid);
172   return FALSE;
173 }
174
175 static dbus_bool_t
176 unhappy_win_func (DBusConnection *conn,
177     const char *sid,
178     void *data)
179 {
180   g_message ("rejecting Windows user \"%s\"", sid);
181   return FALSE;
182 }
183
184 static dbus_bool_t
185 same_uid_unix_func (DBusConnection *conn,
186     unsigned long uid,
187     void *data)
188 {
189   g_message ("checking whether Unix user %lu owns this process", uid);
190   /* I'd use _dbus_unix_user_is_process_owner(), but it's private... */
191 #ifdef G_OS_UNIX
192   return (geteuid () == uid);
193 #else
194   return FALSE;
195 #endif
196 }
197
198 static dbus_bool_t
199 same_uid_win_func (DBusConnection *conn,
200     const char *sid,
201     void *data)
202 {
203   g_message ("checking whether Windows user \"%s\" owns this process", sid);
204   g_message ("Stub implementation consistent with dbus-sysdeps-util-win: "
205       "assume they do");
206   return TRUE;
207 }
208
209 static void
210 new_conn_cb (DBusServer *server,
211     DBusConnection *conn,
212     void *data)
213 {
214   Fixture *f = data;
215
216   dbus_connection_ref (conn);
217   test_connection_setup (f->ctx, conn);
218
219   if (!dbus_connection_add_filter (conn, server_message_cb, f, NULL))
220     oom ();
221
222   if (server == f->normal_server)
223     {
224     }
225   else if (server == f->anon_allowed_server)
226     {
227       dbus_connection_set_allow_anonymous (conn, TRUE);
228     }
229   else if (server == f->anon_only_server)
230     {
231       dbus_connection_set_allow_anonymous (conn, TRUE);
232
233       dbus_connection_set_unix_user_function (conn, unhappy_unix_func,
234           f, NULL);
235       dbus_connection_set_windows_user_function (conn, unhappy_win_func,
236           f, NULL);
237     }
238   else if (server == f->anon_mech_only_server)
239     {
240       dbus_connection_set_allow_anonymous (conn, TRUE);
241
242       /* should never get called */
243       dbus_connection_set_unix_user_function (conn, broken_unix_func,
244           f, NULL);
245       dbus_connection_set_windows_user_function (conn, broken_win_func,
246           f, NULL);
247     }
248   else if (server == f->anon_disallowed_server)
249     {
250       dbus_connection_set_allow_anonymous (conn, FALSE);
251
252       /* should never get called */
253       dbus_connection_set_unix_user_function (conn, broken_unix_func,
254           f, NULL);
255       dbus_connection_set_windows_user_function (conn, broken_win_func,
256           f, NULL);
257     }
258   else if (server == f->permissive_server)
259     {
260       dbus_connection_set_unix_user_function (conn, permissive_unix_func,
261           f, NULL);
262       dbus_connection_set_windows_user_function (conn, permissive_win_func,
263           f, NULL);
264     }
265   else if (server == f->unhappy_server)
266     {
267       dbus_connection_set_unix_user_function (conn, unhappy_unix_func,
268           f, NULL);
269       dbus_connection_set_windows_user_function (conn, unhappy_win_func,
270           f, NULL);
271     }
272   else if (server == f->same_uid_server)
273     {
274       dbus_connection_set_unix_user_function (conn, same_uid_unix_func,
275           f, NULL);
276       dbus_connection_set_windows_user_function (conn, same_uid_win_func,
277           f, NULL);
278     }
279   else if (server == f->same_uid_or_anon_server)
280     {
281       dbus_connection_set_allow_anonymous (conn, TRUE);
282
283       dbus_connection_set_unix_user_function (conn, same_uid_unix_func,
284           f, NULL);
285       dbus_connection_set_windows_user_function (conn, same_uid_win_func,
286           f, NULL);
287     }
288   else
289     {
290       g_assert_not_reached ();
291     }
292 }
293
294 static void
295 setup (Fixture *f,
296     const gchar *listen_addr)
297 {
298   const char *only_anon[] = { "ANONYMOUS", NULL };
299   char *connect_addr;
300
301   f->normal_server = dbus_server_listen (listen_addr, &f->e);
302   assert_no_error (&f->e);
303   g_assert (f->normal_server != NULL);
304   dbus_server_set_new_connection_function (f->normal_server,
305       new_conn_cb, f, NULL);
306   test_server_setup (f->ctx, f->normal_server);
307   connect_addr = dbus_server_get_address (f->normal_server);
308   g_message ("Normal server:\n%s", connect_addr);
309   dbus_free (connect_addr);
310
311   f->anon_allowed_server = dbus_server_listen (listen_addr, &f->e);
312   assert_no_error (&f->e);
313   g_assert (f->anon_allowed_server != NULL);
314   dbus_server_set_new_connection_function (f->anon_allowed_server,
315       new_conn_cb, f, NULL);
316   test_server_setup (f->ctx, f->anon_allowed_server);
317   connect_addr = dbus_server_get_address (f->anon_allowed_server);
318   g_message ("Anonymous-allowed server:\n%s", connect_addr);
319   dbus_free (connect_addr);
320
321   f->anon_only_server = dbus_server_listen (listen_addr, &f->e);
322   assert_no_error (&f->e);
323   g_assert (f->anon_only_server != NULL);
324   dbus_server_set_new_connection_function (f->anon_only_server,
325       new_conn_cb, f, NULL);
326   test_server_setup (f->ctx, f->anon_only_server);
327   connect_addr = dbus_server_get_address (f->anon_only_server);
328   g_message ("Anonymous-only server:\n%s", connect_addr);
329   dbus_free (connect_addr);
330
331   f->anon_mech_only_server = dbus_server_listen (listen_addr, &f->e);
332   assert_no_error (&f->e);
333   g_assert (f->anon_mech_only_server != NULL);
334   dbus_server_set_auth_mechanisms (f->anon_mech_only_server, only_anon);
335   dbus_server_set_new_connection_function (f->anon_mech_only_server,
336       new_conn_cb, f, NULL);
337   test_server_setup (f->ctx, f->anon_mech_only_server);
338   connect_addr = dbus_server_get_address (f->anon_mech_only_server);
339   g_message ("Anon mech only server:\n%s", connect_addr);
340   dbus_free (connect_addr);
341
342   f->anon_disallowed_server = dbus_server_listen (listen_addr, &f->e);
343   assert_no_error (&f->e);
344   g_assert (f->anon_disallowed_server != NULL);
345   dbus_server_set_auth_mechanisms (f->anon_disallowed_server, only_anon);
346   dbus_server_set_new_connection_function (f->anon_disallowed_server,
347       new_conn_cb, f, NULL);
348   test_server_setup (f->ctx, f->anon_disallowed_server);
349   connect_addr = dbus_server_get_address (f->anon_disallowed_server);
350   g_message ("Anonymous-disallowed server:\n%s", connect_addr);
351   dbus_free (connect_addr);
352
353   f->permissive_server = dbus_server_listen (listen_addr, &f->e);
354   assert_no_error (&f->e);
355   g_assert (f->permissive_server != NULL);
356   dbus_server_set_new_connection_function (f->permissive_server,
357       new_conn_cb, f, NULL);
358   test_server_setup (f->ctx, f->permissive_server);
359   connect_addr = dbus_server_get_address (f->permissive_server);
360   g_message ("Permissive server:\n%s", connect_addr);
361   dbus_free (connect_addr);
362
363   f->unhappy_server = dbus_server_listen (listen_addr, &f->e);
364   assert_no_error (&f->e);
365   g_assert (f->unhappy_server != NULL);
366   dbus_server_set_new_connection_function (f->unhappy_server,
367       new_conn_cb, f, NULL);
368   test_server_setup (f->ctx, f->unhappy_server);
369   connect_addr = dbus_server_get_address (f->unhappy_server);
370   g_message ("Unhappy server:\n%s", connect_addr);
371   dbus_free (connect_addr);
372
373   f->same_uid_server = dbus_server_listen (listen_addr, &f->e);
374   assert_no_error (&f->e);
375   g_assert (f->same_uid_server != NULL);
376   dbus_server_set_new_connection_function (f->same_uid_server,
377       new_conn_cb, f, NULL);
378   test_server_setup (f->ctx, f->same_uid_server);
379   connect_addr = dbus_server_get_address (f->same_uid_server);
380   g_message ("Same-UID server:\n%s", connect_addr);
381   dbus_free (connect_addr);
382
383   f->same_uid_or_anon_server = dbus_server_listen (listen_addr, &f->e);
384   assert_no_error (&f->e);
385   g_assert (f->same_uid_or_anon_server != NULL);
386   dbus_server_set_new_connection_function (f->same_uid_or_anon_server,
387       new_conn_cb, f, NULL);
388   test_server_setup (f->ctx, f->same_uid_or_anon_server);
389   connect_addr = dbus_server_get_address (f->same_uid_or_anon_server);
390   g_message ("Same-UID-or-anon server:\n%s", connect_addr);
391   dbus_free (connect_addr);
392 }
393
394 int
395 main (int argc,
396     char **argv)
397 {
398   Fixture f = { DBUS_ERROR_INIT, test_main_context_get () };
399
400   if (argc >= 2)
401     setup (&f, argv[1]);
402   else
403     setup (&f, "tcp:host=127.0.0.1");
404
405   for (;;)
406     test_main_context_iterate (f.ctx, TRUE);
407
408   /* never returns */
409 }