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