2 * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file test_cases_helpers.cpp
18 * @author Aleksander Zdyb <a.zdyb@samsung.com>
20 * @brief Tests for cynara-helper-credentials-socket and cynara-helper-credentials-dbus
26 #include <sys/types.h>
31 #include <dbus/dbus.h>
32 #include <glib-object.h>
35 #include <tests_common.h>
36 #include <access_provider.h>
37 #include <dpl/test/test_runner.h>
39 #include <synchronization_pipe.h>
40 #include <tests_common.h>
42 #include <passwd_access.h>
43 #include <cynara_helpers_creds.h>
44 #include <cynara_helpers_dbus.h>
46 #include <cynara-creds-gdbus.h>
47 #include <cynara-creds-self.h>
49 class ProcessCredentials {
51 ProcessCredentials() {}
53 const std::string &label(void) const {
57 uid_t uid(void) const {
58 return PasswdAccess::uid(APP_USER);
61 gid_t gid(void) const {
62 return PasswdAccess::gid("users");
66 std::string m_label = "cynara_helpers";
69 cynara_client_creds getClientDefaultMethod() {
70 cynara_client_creds def;
71 int ret = cynara_creds_get_default_client_method(&def);
72 RUNNER_ASSERT_MSG(ret == CYNARA_API_SUCCESS,
73 "cynara_creds_get_default_client_method failed with " << ret);
77 cynara_user_creds getUserDefaultMethod() {
78 cynara_user_creds def;
79 int ret = cynara_creds_get_default_user_method(&def);
80 RUNNER_ASSERT_MSG(ret == CYNARA_API_SUCCESS,
81 "cynara_creds_get_default_user_method failed with " << ret);
86 void udsServer(SynchronizationPipe &pipe, const struct sockaddr_un &sockaddr,
87 const struct ProcessCredentials &peerCredentials) {
88 SecurityServer::AccessProvider ap(peerCredentials.label());
89 ap.applyAndSwithToUser(peerCredentials.uid(), peerCredentials.gid());
92 int sock = UDSHelpers::createServer(&sockaddr);
93 SockUniquePtr sockPtr(&sock);
95 int clientSock = UDSHelpers::acceptClient(sock);
97 UDSHelpers::waitForDisconnect(clientSock);
100 typedef std::function<void(int sock, pid_t pid,
101 const ProcessCredentials &peerCredentials)> SocketAssertionFn;
103 void socketTestTemplate(SocketAssertionFn assertion, const std::string &scope) {
104 const auto sockaddr = UDSHelpers::makeAbstractAddress("helper_" + scope + ".socket");
105 const ProcessCredentials peerCredentials;
107 SynchronizationPipe pipe;
109 pid_t pid = runInChild(std::bind(udsServer, std::ref(pipe), std::cref(sockaddr),
110 std::cref(peerCredentials)));
112 pipe.claimParentEp();
114 int sock = UDSHelpers::createClient(&sockaddr);
115 SockUniquePtr sockPtr(&sock);
117 assertion(sock, pid, peerCredentials);
120 RUNNER_TEST_GROUP_INIT(cynara_creds_socket)
122 void testSocketClientSmack(cynara_client_creds method = CLIENT_METHOD_SMACK) {
123 socketTestTemplate([method] (int sock, pid_t, const ProcessCredentials &peerCredentials) {
124 CStringPtr label(CynaraHelperCredentials::socketGetClient(sock, method));
125 RUNNER_ASSERT_MSG(peerCredentials.label() == label.get(),
126 "Labels don't match ret = " << label.get()
127 << "; expected = " << peerCredentials.label());
131 void testSocketClientPid(cynara_client_creds method = CLIENT_METHOD_PID) {
132 socketTestTemplate([method] (int sock, pid_t pid, const ProcessCredentials &) {
133 CStringPtr clientPidStr(CynaraHelperCredentials::socketGetClient(sock, method));
134 pid_t clientPid = std::stoi(clientPidStr.get());
135 RUNNER_ASSERT_MSG(pid == clientPid, "PIDs don't match ret = " << clientPid
136 << "; expected = " << pid);
140 RUNNER_MULTIPROCESS_TEST_SMACK(tccs01_socket_credentials_client_smack)
142 testSocketClientSmack();
145 RUNNER_MULTIPROCESS_TEST(tccs02_socket_credentials_client_pid)
147 testSocketClientPid();
150 RUNNER_MULTIPROCESS_TEST_SMACK(tccs03_socket_credentials_client_default)
152 auto method = getClientDefaultMethod();
154 case CLIENT_METHOD_SMACK:
155 testSocketClientSmack(CLIENT_METHOD_DEFAULT);
157 case CLIENT_METHOD_PID:
158 testSocketClientPid(CLIENT_METHOD_DEFAULT);
161 RUNNER_FAIL_MSG("cynara_creds_get_default_client_method returned unexpected value "
166 void testSocketUserUid(cynara_user_creds method = USER_METHOD_UID) {
167 socketTestTemplate([method] (int sock, pid_t, const ProcessCredentials &peerCredentials) {
168 CStringPtr uidStr(CynaraHelperCredentials::socketGetUser(sock, method));
169 uid_t uid = std::stoul(uidStr.get());
170 RUNNER_ASSERT_MSG(peerCredentials.uid() == uid, "UIDs don't match ret = " << uid
171 << "; expected = "<< peerCredentials.uid());
175 void testSocketUserGid(cynara_user_creds method = USER_METHOD_GID) {
176 socketTestTemplate([method] (int sock, pid_t, const ProcessCredentials &peerCredentials) {
177 CStringPtr gidStr(CynaraHelperCredentials::socketGetUser(sock, method));
178 gid_t gid = std::stoul(gidStr.get());
179 RUNNER_ASSERT_MSG(peerCredentials.gid() == gid, "GIDs don't match ret = " << gid
180 << "; expected = "<< peerCredentials.gid());
184 RUNNER_MULTIPROCESS_TEST(tccs04_socket_credentials_user_uid)
189 RUNNER_MULTIPROCESS_TEST(tccs05_socket_credentials_user_gid)
194 RUNNER_MULTIPROCESS_TEST(tccs06_socket_credentials_user_default)
196 auto method = getUserDefaultMethod();
198 case USER_METHOD_UID:
199 testSocketUserUid(USER_METHOD_DEFAULT);
201 case USER_METHOD_GID:
202 testSocketUserGid(USER_METHOD_DEFAULT);
205 RUNNER_FAIL_MSG("cynara_creds_get_default_user_method returned unexpected value "
210 RUNNER_MULTIPROCESS_TEST(tccs07_socket_credentials_pid)
212 socketTestTemplate([] (int sock, pid_t expectedPid, const ProcessCredentials &) {
213 pid_t peerPid(CynaraHelperCredentials::socketGetPid(sock));
214 RUNNER_ASSERT_MSG(peerPid == expectedPid, "Pids don't match ret = " << peerPid
215 << "; expected = "<< expectedPid);
219 // TODO: Create utility namespace for DBus, maybe?
220 DBusConnectionPtr createDBusConnection(const std::string &name) {
223 dbus_error_init(&err);
224 DBusConnection *conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
225 RUNNER_ASSERT_MSG(dbus_error_is_set(&err) != 1, "Error in dbus_bus_get: " << err.message);
226 dbus_connection_set_exit_on_disconnect(conn, FALSE);
228 DBusConnectionPtr ret(conn, [] (DBusConnection *conn) {
229 dbus_connection_close(conn);
230 dbus_connection_unref(conn);
233 if (name.empty() == false) {
234 dbus_bus_request_name(conn, name.c_str(), DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
235 RUNNER_ASSERT_MSG(dbus_error_is_set(&err) != TRUE,
236 "Error in dbus_bus_request_name: " << err.message);
242 void dbusServer(SynchronizationPipe &pipe, const std::string &requestedName,
243 const ProcessCredentials &peerCredentials) {
244 // for DBus connection, System must have access to our peer creds as well.
245 SecurityServer::AccessProvider systemAp("System");
246 systemAp.addObjectRule(peerCredentials.label(), "rwx");
249 SecurityServer::AccessProvider ap(peerCredentials.label());
250 ap.addObjectRule("System", "w");
251 ap.addObjectRule("System::Run", "x");
252 ap.addObjectRule("System::Shared", "rwx"); // for GDB
253 ap.addSubjectRule("System::Privileged", "rwx"); // for piping
254 ap.addObjectRule("System::Privileged", "rwx"); // for GDB and piping
255 ap.addObjectRule("User", "r"); // for /usr/lib/debug access
256 ap.applyAndSwithToUser(peerCredentials.uid(), peerCredentials.gid());
259 auto conn = createDBusConnection(requestedName);
264 typedef std::function<void(DBusConnectionPtr conn, pid_t pid,
265 const std::string &requestedName,
266 const ProcessCredentials &peerCredentials)> DBusAssertionFn;
268 void dbusTestTemplate(DBusAssertionFn assertion, const std::string &/*scope*/) {
269 std::string requestedName = "tests.dbus.cynara";
270 const ProcessCredentials peerCredentials;
272 SynchronizationPipe pipe;
273 pid_t pid = runInChild(std::bind(dbusServer, std::ref(pipe), std::cref(requestedName),
274 std::cref(peerCredentials)));
276 pipe.claimParentEp();
279 auto conn = createDBusConnection("");
280 assertion(std::move(conn), pid, requestedName, peerCredentials);
284 RUNNER_TEST_GROUP_INIT(cynara_creds_dbus)
286 void testDbusClientPid(cynara_client_creds method = CLIENT_METHOD_PID) {
287 dbusTestTemplate([method] (DBusConnectionPtr conn, pid_t pid, const std::string &requestedName,
288 const ProcessCredentials &) {
289 CStringPtr clientPidStr(CynaraHelperCredentials::dbusGetClient(std::move(conn),
290 requestedName.c_str(), method, CYNARA_API_SUCCESS));
291 pid_t clientPid = std::stoi(clientPidStr.get());
292 RUNNER_ASSERT_MSG(pid == clientPid, "PIDs don't match ret = " << clientPid
293 << "; expected = " << pid);
297 void testDbusClientSmack(cynara_client_creds method = CLIENT_METHOD_SMACK) {
298 dbusTestTemplate([method] (DBusConnectionPtr conn, pid_t, const std::string &requestedName,
299 const ProcessCredentials &peerCredentials) {
300 CStringPtr label(CynaraHelperCredentials::dbusGetClient(std::move(conn),
301 requestedName.c_str(), method, CYNARA_API_SUCCESS));
302 RUNNER_ASSERT_MSG(peerCredentials.label() == label.get(),
303 "Labels don't match ret = " << label.get()
304 << "; expected = " << peerCredentials.label());
308 RUNNER_MULTIPROCESS_TEST(tccd01_dbus_credentials_client_pid)
313 RUNNER_MULTIPROCESS_TEST_SMACK(tccd02_dbus_credentials_client_smack)
315 testDbusClientSmack();
318 RUNNER_MULTIPROCESS_TEST_SMACK(tccd03_dbus_credentials_client_default)
320 auto method = getClientDefaultMethod();
322 case CLIENT_METHOD_SMACK:
323 testDbusClientSmack(CLIENT_METHOD_DEFAULT);
325 case CLIENT_METHOD_PID:
326 testDbusClientPid(CLIENT_METHOD_DEFAULT);
329 RUNNER_FAIL_MSG("cynara_creds_get_default_client_method returned unexpected value "
334 void testDbusUserUid(cynara_user_creds method = USER_METHOD_UID) {
335 dbusTestTemplate([method] (DBusConnectionPtr conn, pid_t, const std::string &requestedName,
336 const ProcessCredentials &peerCredentials) {
337 CStringPtr uidStr(CynaraHelperCredentials::dbusGetUser(std::move(conn),
338 requestedName.c_str(), method, CYNARA_API_SUCCESS));
339 uid_t uid = std::stoul(uidStr.get());
340 RUNNER_ASSERT_MSG(peerCredentials.uid() == uid, "UIDs don't match ret = " << uid
341 << "; expected = "<< peerCredentials.uid());
345 void testDbusUserGid(cynara_user_creds method = USER_METHOD_GID) {
346 // Acquiring gid from dbus connection is not yet implemented for cynara helpers
347 dbusTestTemplate([method] (DBusConnectionPtr conn, pid_t, const std::string &requestedName,
348 const ProcessCredentials &) {
349 CStringPtr gidStr(CynaraHelperCredentials::dbusGetUser(std::move(conn),
350 requestedName.c_str(), method, CYNARA_API_METHOD_NOT_SUPPORTED));
354 RUNNER_MULTIPROCESS_TEST(tccd04_dbus_credentials_user_uid)
359 RUNNER_MULTIPROCESS_TEST(tccd05_dbus_credentials_user_gid)
364 RUNNER_MULTIPROCESS_TEST(tccd06_dbus_credentials_user_default) {
365 auto method = getUserDefaultMethod();
367 case USER_METHOD_UID:
368 testDbusUserUid(USER_METHOD_DEFAULT);
370 case USER_METHOD_GID:
371 testDbusUserGid(USER_METHOD_DEFAULT);
374 RUNNER_FAIL_MSG("cynara_creds_get_default_user_method returned unexpected value "
379 RUNNER_TEST_SMACK(tccd06_dbus_credentials_pid) {
380 dbusTestTemplate([] (DBusConnectionPtr conn, pid_t expectedPid,
381 const std::string &requestedName, const ProcessCredentials &) {
382 auto helperPid = CynaraHelperCredentials::dbusGetPid(std::move(conn),
383 requestedName.c_str(), CYNARA_API_SUCCESS);
384 RUNNER_ASSERT_MSG(helperPid == expectedPid, "PIDs don't match ret = " << helperPid
385 << "; expected = " << expectedPid);
389 GDBusConnectionPtr createGDBusConnection() {
390 GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
392 return GDBusConnectionPtr(conn, [] (GDBusConnection *conn) {
393 g_object_unref(G_OBJECT(conn));
398 typedef std::function<void(GDBusConnectionPtr conn, pid_t pid,
399 const std::string &requestedName,
400 const ProcessCredentials &peerCredentials)> GDBusAssertionFn;
402 void gdbusTestTemplate(GDBusAssertionFn assertion, const std::string &/*scope*/) {
403 std::string requestedName = "tests.dbus.cynara";
404 const ProcessCredentials peerCredentials;
406 SynchronizationPipe pipe;
407 pid_t pid = runInChild(std::bind(dbusServer, std::ref(pipe), std::cref(requestedName),
408 std::cref(peerCredentials)));
410 pipe.claimParentEp();
413 auto conn = createGDBusConnection();
414 assertion(std::move(conn), pid, requestedName, peerCredentials);
419 RUNNER_TEST_GROUP_INIT(cynara_creds_gdbus)
421 void testGdbusClientPid(cynara_client_creds method = CLIENT_METHOD_PID) {
422 gdbusTestTemplate([method] (GDBusConnectionPtr conn, pid_t pid,
423 const std::string &requestedName,
424 const ProcessCredentials &) {
425 GStringPtr clientPidStr(CynaraHelperCredentials::gdbusGetClient(std::move(conn),
426 requestedName.c_str(), method));
427 pid_t clientPid = std::stoi(clientPidStr.get());
428 RUNNER_ASSERT_MSG(pid == clientPid, "PIDs don't match ret = " << clientPid
429 << "; expected = " << pid);
433 void testGdbusClientSmack(cynara_client_creds method = CLIENT_METHOD_SMACK) {
434 gdbusTestTemplate([method] (GDBusConnectionPtr conn, pid_t,
435 const std::string &requestedName,
436 const ProcessCredentials &peerCredentials) {
437 GStringPtr label(CynaraHelperCredentials::gdbusGetClient(std::move(conn),
438 requestedName.c_str(), method));
439 RUNNER_ASSERT_MSG(peerCredentials.label() == label.get(),
440 "Labels don't match ret = " << label.get()
441 << "; expected = " << peerCredentials.label());
445 RUNNER_MULTIPROCESS_TEST(tccgd01_gdbus_credentials_client_pid)
447 testGdbusClientPid();
450 RUNNER_MULTIPROCESS_TEST_SMACK(tccgd02_gdbus_credentials_client_smack)
452 testGdbusClientSmack();
455 RUNNER_MULTIPROCESS_TEST_SMACK(tccgd03_gdbus_credentials_client_default)
457 auto method = getClientDefaultMethod();
459 case CLIENT_METHOD_SMACK:
460 testGdbusClientSmack(CLIENT_METHOD_DEFAULT);
462 case CLIENT_METHOD_PID:
463 testGdbusClientPid(CLIENT_METHOD_DEFAULT);
466 RUNNER_FAIL_MSG("cynara_creds_get_default_client_method returned unexpected value "
471 void testGdbusUserUid(cynara_user_creds method = USER_METHOD_UID) {
472 gdbusTestTemplate([method] (GDBusConnectionPtr conn, pid_t,
473 const std::string &requestedName,
474 const ProcessCredentials &peerCredentials) {
475 GStringPtr uidStr(CynaraHelperCredentials::gdbusGetUser(std::move(conn),
476 requestedName.c_str(), method));
477 uid_t uid = std::stoul(uidStr.get());
478 RUNNER_ASSERT_MSG(peerCredentials.uid() == uid, "UIDs don't match ret = " << uid
479 << "; expected = "<< peerCredentials.uid());
483 void testGdbusUserGid(cynara_user_creds method = USER_METHOD_GID) {
484 // Getting gid for gdbus connection is not yet implemented in cynara helpers
485 gdbusTestTemplate([method] (GDBusConnectionPtr conn, pid_t,
486 const std::string &requestedName,
487 const ProcessCredentials &) {
488 GStringPtr gidStr(CynaraHelperCredentials::gdbusGetUser(std::move(conn),
489 requestedName.c_str(), method, CYNARA_API_METHOD_NOT_SUPPORTED));
493 RUNNER_MULTIPROCESS_TEST(tccgd04_gdbus_credentials_user_uid)
498 RUNNER_MULTIPROCESS_TEST(tccgd05_gdbus_credentials_user_gid)
503 RUNNER_MULTIPROCESS_TEST(tccgd06_gdbus_credentials_user_default) {
504 auto method = getUserDefaultMethod();
506 case USER_METHOD_UID:
507 testGdbusUserUid(USER_METHOD_DEFAULT);
509 case USER_METHOD_GID:
510 testGdbusUserGid(USER_METHOD_DEFAULT);
513 RUNNER_FAIL_MSG("cynara_creds_get_default_user_method returned unexpected value "
518 RUNNER_MULTIPROCESS_TEST(tccgd06_gdbus_credentials_pid) {
519 gdbusTestTemplate([] (GDBusConnectionPtr conn, pid_t expectedPid,
520 const std::string &requestedName, const ProcessCredentials &) {
521 auto helperPid = CynaraHelperCredentials::gdbusGetPid(std::move(conn),
522 requestedName.c_str());
523 RUNNER_ASSERT_MSG(helperPid == expectedPid, "PIDs don't match ret = " << helperPid
524 << "; expected = " << expectedPid);
528 RUNNER_TEST_GROUP_INIT(cynara_creds_self)
530 void testCredsClientSelf(cynara_client_creds method, const std::string &expected) {
532 int ret = cynara_creds_self_get_client(method, &client);
533 CStringPtr clientPtr(client);
534 RUNNER_ASSERT_MSG(ret == CYNARA_API_SUCCESS, "cynara_creds_self_get_client failed with " << ret);
535 RUNNER_ASSERT_MSG(expected == client, "expected client doesn't match, expected: " << expected
536 << ", got : " << client);
539 void testCredsUserSelf(cynara_user_creds method, const std::string &expected) {
541 int ret = cynara_creds_self_get_user(method, &user);
542 CStringPtr clientPtr(user);
543 RUNNER_ASSERT_MSG(ret == CYNARA_API_SUCCESS, "cynara_creds_self_get_user failed with " << ret);
544 RUNNER_ASSERT_MSG(expected == user, "expected user doesn't match, expected: " << expected
545 << ", got : " << user);
548 void testSelfClientSmack(cynara_client_creds method = CLIENT_METHOD_SMACK) {
549 std::string label = "test-label";
550 change_label(label.c_str());
551 testCredsClientSelf(method, label);
554 void testSelfClientPid(cynara_client_creds method = CLIENT_METHOD_PID) {
555 pid_t pid = getpid();
556 testCredsClientSelf(method, std::to_string(pid));
559 void testSelfUserUid(cynara_user_creds method = USER_METHOD_UID) {
560 uid_t uid = getuid();
561 testCredsUserSelf(method, std::to_string(uid));
564 void testSelfUserGid(cynara_user_creds method = USER_METHOD_GID) {
565 gid_t gid = getgid();
566 testCredsUserSelf(method, std::to_string(gid));
569 RUNNER_CHILD_TEST_SMACK(tccsl01_self_credentials_client_smack) {
570 testSelfClientSmack();
573 RUNNER_CHILD_TEST_SMACK(tccsl02_self_credentials_client_pid) {
577 RUNNER_CHILD_TEST_SMACK(tccsl03_self_credentials_user_uid) {
581 RUNNER_CHILD_TEST_SMACK(tccsl04_self_credentials_user_gid) {
585 RUNNER_CHILD_TEST_SMACK(tccsl05_self_credentials_client_default) {
586 auto method = getClientDefaultMethod();
588 case CLIENT_METHOD_SMACK:
589 testSelfClientSmack(CLIENT_METHOD_DEFAULT);
591 case CLIENT_METHOD_PID:
592 testSelfClientPid(CLIENT_METHOD_DEFAULT);
595 RUNNER_FAIL_MSG("cynara_creds_get_default_client_method returned unexpected value " << method);
599 RUNNER_CHILD_TEST_SMACK(tccsl06_self_credentials_user_default) {
600 auto method = getUserDefaultMethod();
602 case USER_METHOD_UID:
603 testSelfUserUid(USER_METHOD_DEFAULT);
605 case USER_METHOD_GID:
606 testSelfUserGid(USER_METHOD_DEFAULT);
609 RUNNER_FAIL_MSG("cynara_creds_get_default_user_method returned unexpected value " << method);