Fix dbus tests.
[platform/core/test/security-tests.git] / tests / security-server-tests / security_server_tests_dbus.cpp
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/smack.h>
4 #include <dpl/test/test_runner.h>
5 #include <dpl/test/test_runner_multiprocess.h>
6 #include <dpl/log/log.h>
7 #include <dbus/dbus.h>
8 #include <dbus-glib.h>
9 #include <glib-object.h>
10 #include <summary_collector.h>
11 #include "tests_common.h"
12 #include "security-server.h"
13 #include "privilege-control.h"
14
15 #define API_DATA_SHARE  "security-server::api-data-share"
16 #define API_FREE_ACCESS "------"
17
18 #define DBUS_SERVER_NAME                        "test.method.server"
19 #define DBUS_SERVER_OBJECT                      "/test/method/server/Object"
20 #define DBUS_SERVER_INTERFACE DBUS_SERVER_NAME  ".Type"
21 #define DBUS_SERVER_METHOD                      "Method"
22 #define DBUS_CALLER_NAME                        "test.method.caller"
23
24 #define DBUS_SMACK_NAME                         "org.freedesktop.DBus"
25 #define DBUS_SMACK_OBJECT                       "/org/freedesktop/DBus"
26 #define DBUS_SMACK_INTERFACE                    "org.freedesktop.DBus"
27 #define DBUS_SMACK_METHOD                       "GetConnectionCredentials"
28
29 RUNNER_TEST_GROUP_INIT(SECURITY_SERVER_TESTS_DBUS);
30
31 RUNNER_MULTIPROCESS_TEST_SMACK(tc01_smack_context_from_DBus)
32 {
33     int ret = -1;
34     const char *subject_parent = "subject_parent";
35     const char *subject_child = "subject_child";
36     struct smack_accesses *handle = NULL;
37
38     DBusMessage* msg = NULL;
39     DBusMessageIter args, iter, var, var_iter, var_value;
40     DBusConnection* conn = NULL;
41     DBusError err;
42     DBusPendingCall *pending = NULL;
43     const char *dbus_server_name = DBUS_SERVER_NAME;
44     char *smack_context = NULL;
45
46     pid_t pid = fork();
47     RUNNER_ASSERT_MSG_BT(-1 != pid, "fork() failed");
48
49     if (pid == 0) {
50         // child
51         ret = smack_set_label_for_self(subject_child);
52         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
53             "smack_set__label_for_self() failed, ret: " << ret);
54
55         ret = smack_accesses_new(&handle);
56         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
57             "smack_accesses_new() failed, ret: " << ret);
58
59         ret = smack_accesses_add(handle, subject_child, API_DATA_SHARE, API_FREE_ACCESS);
60         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
61             "smack_accesses_add() failed, ret: " << ret);
62
63         ret = smack_accesses_apply(handle);
64         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
65             "smack_accesses_apply() failed, ret: " << ret);
66
67         ret = smack_set_label_for_self(subject_child);
68         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
69             "smack_set_label_for_self() failed, ret: " << ret);
70
71         smack_accesses_free(handle);
72
73         // initialize the errors
74         dbus_error_init(&err);
75
76         // connect to the system bus and check for errors
77         conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
78         ret = dbus_error_is_set(&err);
79         if (1 == ret) {
80             dbus_error_free(&err);
81             RUNNER_ASSERT_MSG_BT(0 == ret, "dbus_bus_get() failed, ret: " << ret);
82         }
83
84         // request our name on the bus
85         ret = dbus_bus_request_name(conn, DBUS_CALLER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
86         if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
87         dbus_error_free(&err);
88         RUNNER_ASSERT_MSG_BT(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret,
89             "dbus_bus_request_name() failed, ret: " << ret);
90         }
91
92         // crate a new method call for checking SMACK context from DBus interface
93         msg = dbus_message_new_method_call(DBUS_SMACK_NAME,
94                                            DBUS_SMACK_OBJECT,
95                                            DBUS_SMACK_INTERFACE,
96                                            DBUS_SMACK_METHOD);
97
98         RUNNER_ASSERT_MSG_BT(NULL != msg,
99             "dbus_message_new_method_call() failed, ret: " << ret);
100
101         // append arguments, we need SMACK context for our parent process "test.method.server"
102         dbus_message_iter_init_append(msg, &args);
103         ret = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &dbus_server_name);
104         RUNNER_ASSERT_MSG_BT(1 == ret, "Out of memory");
105
106         // wait for parent to connect to DBus
107         sleep(3);
108
109         // send message and get a handle for a reply
110         // -1 is default timeout
111         ret = dbus_connection_send_with_reply (conn, msg, &pending, -1);
112         RUNNER_ASSERT_MSG_BT(1 == ret, "Out of memory");
113         RUNNER_ASSERT_MSG_BT(NULL != pending, "Pending call null");
114
115         dbus_connection_flush(conn);
116
117         // free message
118         dbus_message_unref(msg);
119
120         // block until reply
121         dbus_pending_call_block(pending);
122
123         // get the reply
124         msg = dbus_pending_call_steal_reply(pending);
125         RUNNER_ASSERT_MSG_BT(NULL != msg, "Reply null");
126
127         // free message handle
128         dbus_pending_call_unref(pending);
129
130         ret = dbus_message_iter_init(msg, &iter);
131         RUNNER_ASSERT_MSG_BT(0 != ret, "Message has no arguments");
132
133         dbus_message_iter_recurse(&iter, &var);
134
135         while (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_INVALID) {
136             dbus_message_iter_recurse(&var, &var_iter);
137             while(dbus_message_iter_get_arg_type(&var_iter) != DBUS_TYPE_INVALID) {
138                 dbus_message_iter_recurse(&var_iter, &var_value);
139                 switch(dbus_message_iter_get_arg_type(&var_value)) {
140                     case DBUS_TYPE_STRING:
141                         dbus_message_iter_get_basic(&var_value, &smack_context);
142                         break;
143                     default:
144                         ;
145                 }
146                 dbus_message_iter_next(&var_iter);
147             }
148             dbus_message_iter_next(&var);
149         }
150
151         // free reply and close connection
152         dbus_message_unref(msg);
153         dbus_connection_unref(conn);
154
155         RUNNER_ASSERT_BT(smack_context != NULL);
156         ret = strcmp(smack_context, subject_parent);
157         RUNNER_ASSERT_MSG_BT(0 == ret,
158             "Context mismatch! context from dbus: " << smack_context);
159
160         exit(0);
161
162     } else {
163         // parent
164         ret = smack_set_label_for_self(subject_parent);
165         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
166             "smack_set_label_for_self() failed, ret: " << ret);
167
168         ret = smack_accesses_new(&handle);
169         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
170             "smack_accesses_new() failed, ret: " << ret);
171
172         ret = smack_accesses_add(handle, subject_parent, API_DATA_SHARE, API_FREE_ACCESS);
173         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
174             "smack_accesses_add() failed, ret: " << ret);
175
176         ret = smack_accesses_apply(handle);
177         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
178             "smack_accesses_apply() failed, ret: " << ret);
179
180         ret = smack_set_label_for_self(subject_parent);
181         RUNNER_ASSERT_MSG_BT(ret == PC_OPERATION_SUCCESS,
182             "smack_set_label_for_self() failed, ret: " << ret);
183
184         smack_accesses_free(handle);
185
186         // initialise the error
187         dbus_error_init(&err);
188
189         // connect to the bus and check for errors
190         conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
191         ret = dbus_error_is_set(&err);
192         if (1 == ret) {
193             dbus_error_free(&err);
194             RUNNER_ASSERT_MSG_BT(0 == ret, "dbus_bus_get() failed, ret: " << ret);
195         }
196
197         // request our name on the bus and check for errors
198         ret = dbus_bus_request_name(conn, DBUS_SERVER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
199         if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
200             dbus_error_free(&err);
201             RUNNER_ASSERT_MSG_BT(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret,
202                 "dbus_bus_request_name() failed, ret: " << ret);
203         }
204
205         // close the connection
206         dbus_connection_unref(conn);
207     }
208 }
209
210 ///////////////////////////////////////
211 //////NOSMACK ENV TESTS////////////////
212 ///////////////////////////////////////
213
214 /**
215  * NOSMACK version of tc01 test.
216  *
217  * This is almost an exact copy of the original SMACK DBus test. As in previous security-server
218  * tests, parts where SMACK is used are skipped, because most important functions will return error.
219  */
220 RUNNER_MULTIPROCESS_TEST_NOSMACK(tc01_smack_context_from_DBus_nosmack)
221 {
222     int ret = -1;
223     const char* subject_parent = "subject_parent";
224
225     DBusMessage* msg = NULL;
226     DBusMessageIter args, iter, var, var_iter, var_value;
227     DBusConnection* conn = NULL;
228     DBusError err;
229     DBusPendingCall *pending = NULL;
230     const char *dbus_server_name = DBUS_SERVER_NAME;
231     char *smack_context = NULL;
232
233     pid_t pid = fork();
234     RUNNER_ASSERT_MSG_BT(-1 != pid, "fork() failed");
235
236     if (pid == 0) {
237         // child
238
239         // initialize the errors
240         dbus_error_init(&err);
241
242         // connect to the system bus and check for errors; failure = exit with result 1
243         conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
244         ret = dbus_error_is_set(&err);
245         if (1 == ret) {
246             dbus_error_free(&err);
247             RUNNER_ASSERT_MSG_BT(false, "Failed to connect to system bus. Ret " << ret);
248         }
249
250         // request our name on the bus; failure = exit with result 2
251         ret = dbus_bus_request_name(conn, DBUS_CALLER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
252         if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
253             dbus_error_free(&err);
254             RUNNER_ASSERT_MSG_BT(false, "Failed to request name on the bus. Ret " << ret);
255         }
256
257         // crate a new method call for checking SMACK context from DBus interface
258         msg = dbus_message_new_method_call(DBUS_SMACK_NAME,
259                                            DBUS_SMACK_OBJECT,
260                                            DBUS_SMACK_INTERFACE,
261                                            DBUS_SMACK_METHOD);
262
263         RUNNER_ASSERT_MSG_BT(msg != NULL, "dbus_message_new_method_call() failed.");
264
265         // append arguments, we need SMACK context for our parent process "test.method.server"
266         dbus_message_iter_init_append(msg, &args);
267         ret = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &dbus_server_name);
268         RUNNER_ASSERT_MSG_BT(ret == 1, "Out of memory. Ret " << ret);
269
270         // wait for parent to connect to DBus
271         sleep(3);
272
273         // send message and get a handle for a reply
274         // -1 is default timeout
275         ret = dbus_connection_send_with_reply (conn, msg, &pending, -1);
276         RUNNER_ASSERT_MSG_BT(ret == 1, "Out of memory. Ret " << ret);
277         RUNNER_ASSERT_MSG_BT(pending != NULL, "Pending call is NULL.");
278
279         dbus_connection_flush(conn);
280
281         // free message
282         dbus_message_unref(msg);
283
284         // block until reply
285         dbus_pending_call_block(pending);
286
287         // get the reply
288         msg = dbus_pending_call_steal_reply(pending);
289         RUNNER_ASSERT_MSG_BT(msg != NULL, "Failed to get the reply from bus.");
290
291         // free message handle
292         dbus_pending_call_unref(pending);
293
294         ret = dbus_message_iter_init(msg, &iter);
295         RUNNER_ASSERT_MSG_BT(ret != 0, "DBus message has no arguments. Ret " << ret);
296
297         dbus_message_iter_recurse(&iter, &var);
298         while (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_INVALID) {
299             dbus_message_iter_recurse(&var, &var_iter);
300             while(dbus_message_iter_get_arg_type(&var_iter) != DBUS_TYPE_INVALID) {
301                 dbus_message_iter_recurse(&var_iter, &var_value);
302                 switch(dbus_message_iter_get_arg_type(&var_value)) {
303                     case DBUS_TYPE_STRING:
304                         dbus_message_iter_get_basic(&var_value, &smack_context);
305                         break;
306                     default:
307                         ;
308                 }
309                 dbus_message_iter_next(&var_iter);
310             }
311             dbus_message_iter_next(&var);
312         }
313
314         // free reply and close connection
315         dbus_message_unref(msg);
316         dbus_connection_unref(conn);
317
318         RUNNER_ASSERT_BT(smack_context != NULL);
319         ret = strcmp(smack_context, subject_parent);
320         RUNNER_ASSERT_MSG_BT(ret == 0, "Context mismatch. Context " << smack_context);
321
322         exit(0);
323
324     } else {
325         // parent
326
327         // initialise the error
328         dbus_error_init(&err);
329
330         // connect to the bus and check for errors
331         conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
332         ret = dbus_error_is_set(&err);
333         if (1 == ret) {
334             dbus_error_free(&err);
335             RUNNER_ASSERT_MSG_BT(0 == ret, "dbus_bus_get() failed, ret: " << ret);
336         }
337
338         // request our name on the bus and check for errors
339         ret = dbus_bus_request_name(conn, DBUS_SERVER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
340         if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
341             dbus_error_free(&err);
342             RUNNER_ASSERT_MSG_BT(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret,
343                 "dbus_bus_request_name() failed, ret: " << ret);
344         }
345
346         // close the connection
347         dbus_connection_unref(conn);
348     }
349 }
350
351 int main(int argc, char *argv[])
352 {
353     SummaryCollector::Register();
354     return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
355 }