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