cmake: Add X11 include path for tools
[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 #include <stdlib.h>
34 #ifdef G_OS_UNIX
35 #include <unistd.h>
36 #include <sys/types.h>
37 #endif
38
39 #include "test-utils.h"
40
41 typedef struct {
42     DBusError e;
43     TestMainContext *ctx;
44
45     DBusServer *normal_server;
46     DBusServer *anon_allowed_server;
47     DBusServer *anon_only_server;
48     DBusServer *anon_mech_only_server;
49     DBusServer *anon_disallowed_server;
50     DBusServer *permissive_server;
51     DBusServer *unhappy_server;
52     DBusServer *same_uid_server;
53     DBusServer *same_uid_or_anon_server;
54 } Fixture;
55
56 static void oom (void) G_GNUC_NORETURN;
57 static void
58 oom (void)
59 {
60   g_error ("out of memory");
61   abort ();
62 }
63
64 static void
65 assert_no_error (const DBusError *e)
66 {
67   if (G_UNLIKELY (dbus_error_is_set (e)))
68     g_error ("expected success but got error: %s: %s", e->name, e->message);
69 }
70
71 static DBusHandlerResult
72 server_message_cb (DBusConnection *conn,
73     DBusMessage *message,
74     void *data)
75 {
76   if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected"))
77     {
78       dbus_connection_unref (conn);
79
80       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
81     }
82
83   if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
84     {
85       DBusMessage *reply = dbus_message_new_method_return (message);
86       const char *hello = "Hello, world!";
87       unsigned long uid;
88       char *sid;
89
90       if (dbus_connection_get_unix_user (conn, &uid))
91         {
92           g_message ("message from uid %lu", uid);
93         }
94       else if (dbus_connection_get_windows_user (conn, &sid))
95         {
96           if (sid == NULL)
97             oom ();
98
99           g_message ("message from sid \"%s\"", sid);
100           dbus_free (sid);
101         }
102       else if (dbus_connection_get_is_anonymous (conn))
103         {
104           g_message ("message from Anonymous");
105         }
106       else
107         {
108           g_message ("message from ... someone?");
109         }
110
111       if (reply == NULL)
112         oom ();
113
114       if (!dbus_message_append_args (reply,
115             DBUS_TYPE_STRING, &hello,
116             DBUS_TYPE_INVALID))
117         oom ();
118
119       if (!dbus_connection_send (conn, reply, NULL))
120         oom ();
121
122       dbus_message_unref (reply);
123
124       return DBUS_HANDLER_RESULT_HANDLED;
125     }
126
127   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
128 }
129
130 static dbus_bool_t
131 permissive_unix_func (DBusConnection *conn,
132     unsigned long uid,
133     void *data)
134 {
135   g_message ("accepting Unix user %lu", uid);
136   return TRUE;
137 }
138
139 static dbus_bool_t
140 permissive_win_func (DBusConnection *conn,
141     const char *sid,
142     void *data)
143 {
144   g_message ("accepting Windows user \"%s\"", sid);
145   return TRUE;
146 }
147
148 static dbus_bool_t
149 broken_unix_func (DBusConnection *conn,
150     unsigned long uid,
151     void *data)
152 {
153   g_error ("libdbus called the Unix user function for an ANONYMOUS-only "
154       "connection");
155   return FALSE;
156 }
157
158 static dbus_bool_t
159 broken_win_func (DBusConnection *conn,
160     const char *sid,
161     void *data)
162 {
163   g_error ("libdbus called the Windows user function for an ANONYMOUS-only "
164       "connection");
165   return FALSE;
166 }
167
168 static dbus_bool_t
169 unhappy_unix_func (DBusConnection *conn,
170     unsigned long uid,
171     void *data)
172 {
173   g_message ("rejecting Unix user %lu", uid);
174   return FALSE;
175 }
176
177 static dbus_bool_t
178 unhappy_win_func (DBusConnection *conn,
179     const char *sid,
180     void *data)
181 {
182   g_message ("rejecting Windows user \"%s\"", sid);
183   return FALSE;
184 }
185
186 static dbus_bool_t
187 same_uid_unix_func (DBusConnection *conn,
188     unsigned long uid,
189     void *data)
190 {
191   g_message ("checking whether Unix user %lu owns this process", uid);
192   /* I'd use _dbus_unix_user_is_process_owner(), but it's private... */
193 #ifdef G_OS_UNIX
194   return (geteuid () == uid);
195 #else
196   return FALSE;
197 #endif
198 }
199
200 static dbus_bool_t
201 same_uid_win_func (DBusConnection *conn,
202     const char *sid,
203     void *data)
204 {
205   g_message ("checking whether Windows user \"%s\" owns this process", sid);
206   g_message ("Stub implementation consistent with dbus-sysdeps-util-win: "
207       "assume they do");
208   return TRUE;
209 }
210
211 static void
212 new_conn_cb (DBusServer *server,
213     DBusConnection *conn,
214     void *data)
215 {
216   Fixture *f = data;
217
218   dbus_connection_ref (conn);
219   test_connection_setup (f->ctx, conn);
220
221   if (!dbus_connection_add_filter (conn, server_message_cb, f, NULL))
222     oom ();
223
224   if (server == f->normal_server)
225     {
226     }
227   else if (server == f->anon_allowed_server)
228     {
229       dbus_connection_set_allow_anonymous (conn, TRUE);
230     }
231   else if (server == f->anon_only_server)
232     {
233       dbus_connection_set_allow_anonymous (conn, TRUE);
234
235       dbus_connection_set_unix_user_function (conn, unhappy_unix_func,
236           f, NULL);
237       dbus_connection_set_windows_user_function (conn, unhappy_win_func,
238           f, NULL);
239     }
240   else if (server == f->anon_mech_only_server)
241     {
242       dbus_connection_set_allow_anonymous (conn, TRUE);
243
244       /* should never get called */
245       dbus_connection_set_unix_user_function (conn, broken_unix_func,
246           f, NULL);
247       dbus_connection_set_windows_user_function (conn, broken_win_func,
248           f, NULL);
249     }
250   else if (server == f->anon_disallowed_server)
251     {
252       dbus_connection_set_allow_anonymous (conn, FALSE);
253
254       /* should never get called */
255       dbus_connection_set_unix_user_function (conn, broken_unix_func,
256           f, NULL);
257       dbus_connection_set_windows_user_function (conn, broken_win_func,
258           f, NULL);
259     }
260   else if (server == f->permissive_server)
261     {
262       dbus_connection_set_unix_user_function (conn, permissive_unix_func,
263           f, NULL);
264       dbus_connection_set_windows_user_function (conn, permissive_win_func,
265           f, NULL);
266     }
267   else if (server == f->unhappy_server)
268     {
269       dbus_connection_set_unix_user_function (conn, unhappy_unix_func,
270           f, NULL);
271       dbus_connection_set_windows_user_function (conn, unhappy_win_func,
272           f, NULL);
273     }
274   else if (server == f->same_uid_server)
275     {
276       dbus_connection_set_unix_user_function (conn, same_uid_unix_func,
277           f, NULL);
278       dbus_connection_set_windows_user_function (conn, same_uid_win_func,
279           f, NULL);
280     }
281   else if (server == f->same_uid_or_anon_server)
282     {
283       dbus_connection_set_allow_anonymous (conn, TRUE);
284
285       dbus_connection_set_unix_user_function (conn, same_uid_unix_func,
286           f, NULL);
287       dbus_connection_set_windows_user_function (conn, same_uid_win_func,
288           f, NULL);
289     }
290   else
291     {
292       g_assert_not_reached ();
293     }
294 }
295
296 static void
297 setup (Fixture *f,
298     const gchar *listen_addr)
299 {
300   const char *only_anon[] = { "ANONYMOUS", NULL };
301   char *connect_addr;
302
303   f->normal_server = dbus_server_listen (listen_addr, &f->e);
304   assert_no_error (&f->e);
305   g_assert (f->normal_server != NULL);
306   dbus_server_set_new_connection_function (f->normal_server,
307       new_conn_cb, f, NULL);
308   test_server_setup (f->ctx, f->normal_server);
309   connect_addr = dbus_server_get_address (f->normal_server);
310   g_message ("Normal server:\n%s", connect_addr);
311   dbus_free (connect_addr);
312
313   f->anon_allowed_server = dbus_server_listen (listen_addr, &f->e);
314   assert_no_error (&f->e);
315   g_assert (f->anon_allowed_server != NULL);
316   dbus_server_set_new_connection_function (f->anon_allowed_server,
317       new_conn_cb, f, NULL);
318   test_server_setup (f->ctx, f->anon_allowed_server);
319   connect_addr = dbus_server_get_address (f->anon_allowed_server);
320   g_message ("Anonymous-allowed server:\n%s", connect_addr);
321   dbus_free (connect_addr);
322
323   f->anon_only_server = dbus_server_listen (listen_addr, &f->e);
324   assert_no_error (&f->e);
325   g_assert (f->anon_only_server != NULL);
326   dbus_server_set_new_connection_function (f->anon_only_server,
327       new_conn_cb, f, NULL);
328   test_server_setup (f->ctx, f->anon_only_server);
329   connect_addr = dbus_server_get_address (f->anon_only_server);
330   g_message ("Anonymous-only server:\n%s", connect_addr);
331   dbus_free (connect_addr);
332
333   f->anon_mech_only_server = dbus_server_listen (listen_addr, &f->e);
334   assert_no_error (&f->e);
335   g_assert (f->anon_mech_only_server != NULL);
336   dbus_server_set_auth_mechanisms (f->anon_mech_only_server, only_anon);
337   dbus_server_set_new_connection_function (f->anon_mech_only_server,
338       new_conn_cb, f, NULL);
339   test_server_setup (f->ctx, f->anon_mech_only_server);
340   connect_addr = dbus_server_get_address (f->anon_mech_only_server);
341   g_message ("Anon mech only server:\n%s", connect_addr);
342   dbus_free (connect_addr);
343
344   f->anon_disallowed_server = dbus_server_listen (listen_addr, &f->e);
345   assert_no_error (&f->e);
346   g_assert (f->anon_disallowed_server != NULL);
347   dbus_server_set_auth_mechanisms (f->anon_disallowed_server, only_anon);
348   dbus_server_set_new_connection_function (f->anon_disallowed_server,
349       new_conn_cb, f, NULL);
350   test_server_setup (f->ctx, f->anon_disallowed_server);
351   connect_addr = dbus_server_get_address (f->anon_disallowed_server);
352   g_message ("Anonymous-disallowed server:\n%s", connect_addr);
353   dbus_free (connect_addr);
354
355   f->permissive_server = dbus_server_listen (listen_addr, &f->e);
356   assert_no_error (&f->e);
357   g_assert (f->permissive_server != NULL);
358   dbus_server_set_new_connection_function (f->permissive_server,
359       new_conn_cb, f, NULL);
360   test_server_setup (f->ctx, f->permissive_server);
361   connect_addr = dbus_server_get_address (f->permissive_server);
362   g_message ("Permissive server:\n%s", connect_addr);
363   dbus_free (connect_addr);
364
365   f->unhappy_server = dbus_server_listen (listen_addr, &f->e);
366   assert_no_error (&f->e);
367   g_assert (f->unhappy_server != NULL);
368   dbus_server_set_new_connection_function (f->unhappy_server,
369       new_conn_cb, f, NULL);
370   test_server_setup (f->ctx, f->unhappy_server);
371   connect_addr = dbus_server_get_address (f->unhappy_server);
372   g_message ("Unhappy server:\n%s", connect_addr);
373   dbus_free (connect_addr);
374
375   f->same_uid_server = dbus_server_listen (listen_addr, &f->e);
376   assert_no_error (&f->e);
377   g_assert (f->same_uid_server != NULL);
378   dbus_server_set_new_connection_function (f->same_uid_server,
379       new_conn_cb, f, NULL);
380   test_server_setup (f->ctx, f->same_uid_server);
381   connect_addr = dbus_server_get_address (f->same_uid_server);
382   g_message ("Same-UID server:\n%s", connect_addr);
383   dbus_free (connect_addr);
384
385   f->same_uid_or_anon_server = dbus_server_listen (listen_addr, &f->e);
386   assert_no_error (&f->e);
387   g_assert (f->same_uid_or_anon_server != NULL);
388   dbus_server_set_new_connection_function (f->same_uid_or_anon_server,
389       new_conn_cb, f, NULL);
390   test_server_setup (f->ctx, f->same_uid_or_anon_server);
391   connect_addr = dbus_server_get_address (f->same_uid_or_anon_server);
392   g_message ("Same-UID-or-anon server:\n%s", connect_addr);
393   dbus_free (connect_addr);
394 }
395
396 int
397 main (int argc,
398     char **argv)
399 {
400   Fixture f = { DBUS_ERROR_INIT, test_main_context_get () };
401
402   if (argc >= 2)
403     setup (&f, argv[1]);
404   else
405     setup (&f, "tcp:host=127.0.0.1");
406
407   for (;;)
408     test_main_context_iterate (f.ctx, TRUE);
409
410   /* never returns */
411 }