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