dbus-marshal-byteswap: Byte-swap Unix fd indexes if needed
[platform/upstream/dbus.git] / test / uid-permissions.c
1 /* Integration tests for the dbus-daemon's uid-based hardening
2  *
3  * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
4  * Copyright © 2010-2011 Nokia Corporation
5  * Copyright © 2015 Collabora Ltd.
6  *
7  * Permission is hereby granted, free of charge, to any person
8  * obtaining a copy of this software and associated documentation files
9  * (the "Software"), to deal in the Software without restriction,
10  * including without limitation the rights to use, copy, modify, merge,
11  * publish, distribute, sublicense, and/or sell copies of the Software,
12  * and to permit persons to whom the Software is furnished to do so,
13  * subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27
28 #include <config.h>
29
30 #include "test-utils-glib.h"
31
32 typedef struct {
33     gboolean skip;
34
35     TestMainContext *ctx;
36
37     DBusError e;
38     GError *ge;
39
40     GPid daemon_pid;
41
42     DBusConnection *conn;
43 } Fixture;
44
45 typedef struct {
46     const char *config_file;
47     TestUser user;
48     gboolean expect_success;
49 } Config;
50
51 static void
52 setup (Fixture *f,
53     gconstpointer context)
54 {
55   const Config *config = context;
56   gchar *address;
57
58   f->ctx = test_main_context_get ();
59   f->ge = NULL;
60   dbus_error_init (&f->e);
61
62   address = test_get_dbus_daemon (config ? config->config_file : NULL,
63                                   TEST_USER_MESSAGEBUS, NULL,
64                                   &f->daemon_pid);
65
66   if (address == NULL)
67     {
68       f->skip = TRUE;
69       return;
70     }
71
72   f->conn = test_connect_to_bus_as_user (f->ctx, address,
73       config ? config->user : TEST_USER_ME);
74
75   if (f->conn == NULL)
76     f->skip = TRUE;
77
78   g_free (address);
79 }
80
81 static void
82 test_uae (Fixture *f,
83     gconstpointer context)
84 {
85   const Config *config = context;
86   DBusMessage *m;
87   DBusPendingCall *pc;
88   DBusMessageIter args_iter;
89   DBusMessageIter arr_iter;
90
91   if (f->skip)
92     return;
93
94   m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
95       DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "UpdateActivationEnvironment");
96
97   if (m == NULL)
98     g_error ("OOM");
99
100   dbus_message_iter_init_append (m, &args_iter);
101
102   /* Append an empty a{ss} (string => string dictionary). */
103   if (!dbus_message_iter_open_container (&args_iter, DBUS_TYPE_ARRAY,
104         "{ss}", &arr_iter) ||
105       !dbus_message_iter_close_container (&args_iter, &arr_iter))
106     g_error ("OOM");
107
108   if (!dbus_connection_send_with_reply (f->conn, m, &pc,
109                                         DBUS_TIMEOUT_USE_DEFAULT) ||
110       pc == NULL)
111     g_error ("OOM");
112
113   dbus_message_unref (m);
114   m = NULL;
115
116   if (dbus_pending_call_get_completed (pc))
117     test_pending_call_store_reply (pc, &m);
118   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
119                                           &m, NULL))
120     g_error ("OOM");
121
122   while (m == NULL)
123     test_main_context_iterate (f->ctx, TRUE);
124
125   if (config->expect_success)
126     {
127       /* it succeeds */
128       g_assert_cmpint (dbus_message_get_type (m), ==,
129           DBUS_MESSAGE_TYPE_METHOD_RETURN);
130     }
131   else
132     {
133       /* it fails, yielding an error message with one string argument */
134       g_assert_cmpint (dbus_message_get_type (m), ==, DBUS_MESSAGE_TYPE_ERROR);
135       g_assert_cmpstr (dbus_message_get_error_name (m), ==,
136           DBUS_ERROR_ACCESS_DENIED);
137       g_assert_cmpstr (dbus_message_get_signature (m), ==, "s");
138     }
139
140   dbus_message_unref (m);
141 }
142
143 static void
144 test_monitor (Fixture *f,
145     gconstpointer context)
146 {
147   const Config *config = context;
148   DBusMessage *m;
149   DBusPendingCall *pc;
150   DBusMessageIter args_iter;
151   DBusMessageIter arr_iter;
152   dbus_uint32_t no_flags = 0;
153
154   if (f->skip)
155     return;
156
157   m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
158       DBUS_PATH_DBUS, DBUS_INTERFACE_MONITORING, "BecomeMonitor");
159
160   if (m == NULL)
161     g_error ("OOM");
162
163   dbus_message_iter_init_append (m, &args_iter);
164
165   /* Append an empty as (string array). */
166   if (!dbus_message_iter_open_container (&args_iter, DBUS_TYPE_ARRAY,
167         "s", &arr_iter) ||
168       !dbus_message_iter_close_container (&args_iter, &arr_iter) ||
169       !dbus_message_iter_append_basic (&args_iter,
170         DBUS_TYPE_UINT32, &no_flags))
171     g_error ("OOM");
172
173   if (!dbus_connection_send_with_reply (f->conn, m, &pc,
174                                         DBUS_TIMEOUT_USE_DEFAULT) ||
175       pc == NULL)
176     g_error ("OOM");
177
178   dbus_message_unref (m);
179   m = NULL;
180
181   if (dbus_pending_call_get_completed (pc))
182     test_pending_call_store_reply (pc, &m);
183   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
184                                           &m, NULL))
185     g_error ("OOM");
186
187   while (m == NULL)
188     test_main_context_iterate (f->ctx, TRUE);
189
190   if (config->expect_success)
191     {
192       /* it succeeds */
193       g_assert_cmpint (dbus_message_get_type (m), ==,
194           DBUS_MESSAGE_TYPE_METHOD_RETURN);
195     }
196   else
197     {
198       /* it fails, yielding an error message with one string argument */
199       g_assert_cmpint (dbus_message_get_type (m), ==, DBUS_MESSAGE_TYPE_ERROR);
200       g_assert_cmpstr (dbus_message_get_error_name (m), ==,
201           DBUS_ERROR_ACCESS_DENIED);
202       g_assert_cmpstr (dbus_message_get_signature (m), ==, "s");
203     }
204
205   dbus_message_unref (m);
206 }
207
208 static void
209 teardown (Fixture *f,
210     gconstpointer context G_GNUC_UNUSED)
211 {
212   dbus_error_free (&f->e);
213   g_clear_error (&f->ge);
214
215   if (f->conn != NULL)
216     {
217       dbus_connection_close (f->conn);
218       dbus_connection_unref (f->conn);
219       f->conn = NULL;
220     }
221
222   if (f->daemon_pid != 0)
223     {
224       test_kill_pid (f->daemon_pid);
225       g_spawn_close_pid (f->daemon_pid);
226       f->daemon_pid = 0;
227     }
228
229   test_main_context_unref (f->ctx);
230 }
231
232 static Config root_ok_config = {
233     "valid-config-files/multi-user.conf",
234     TEST_USER_ROOT,
235     TRUE
236 };
237
238 static Config messagebus_ok_config = {
239     "valid-config-files/multi-user.conf",
240     TEST_USER_MESSAGEBUS,
241     TRUE
242 };
243
244 static Config other_fail_config = {
245     "valid-config-files/multi-user.conf",
246     TEST_USER_OTHER,
247     FALSE
248 };
249
250 int
251 main (int argc,
252     char **argv)
253 {
254   test_init (&argc, &argv);
255
256   /* UpdateActivationEnvironment used to be allowed by dbus-daemon for root
257    * and messagebus but not for other users (although system.conf forbids it
258    * for everyone, and it's useless). It is now hard-coded to fail on a
259    * system bus for everyone, so don't assert that root and messagebus
260    * may call it; continue to assert that it is denied for unprivileged
261    * users though. */
262   g_test_add ("/uid-permissions/uae/other", Fixture, &other_fail_config,
263       setup, test_uae, teardown);
264
265   /* BecomeMonitor has the behaviour that UAE used to have. */
266   g_test_add ("/uid-permissions/monitor/root", Fixture, &root_ok_config,
267       setup, test_monitor, teardown);
268   g_test_add ("/uid-permissions/monitor/messagebus", Fixture, &messagebus_ok_config,
269       setup, test_monitor, teardown);
270   g_test_add ("/uid-permissions/monitor/other", Fixture, &other_fail_config,
271       setup, test_monitor, teardown);
272
273   return g_test_run ();
274 }