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>
44 #include <cynara_test_helpers.h>
45 #include <cynara_test_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 pid_t runInChild(const std::function<void(void)> &process) {
71 RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "fork failed");
81 cynara_client_creds getClientDefaultMethod() {
82 cynara_client_creds def;
83 int ret = cynara_creds_get_default_client_method(&def);
84 RUNNER_ASSERT_MSG(ret == CYNARA_API_SUCCESS,
85 "cynara_creds_get_default_client_method failed with " << ret);
89 cynara_user_creds getUserDefaultMethod() {
90 cynara_user_creds def;
91 int ret = cynara_creds_get_default_user_method(&def);
92 RUNNER_ASSERT_MSG(ret == CYNARA_API_SUCCESS,
93 "cynara_creds_get_default_user_method failed with " << ret);
98 void udsServer(SynchronizationPipe &pipe, const struct sockaddr_un &sockaddr,
99 const struct ProcessCredentials &peerCredentials) {
100 SecurityServer::AccessProvider ap(peerCredentials.label());
101 ap.applyAndSwithToUser(peerCredentials.uid(), peerCredentials.gid());
104 int sock = UDSHelpers::createServer(&sockaddr);
105 SockUniquePtr sockPtr(&sock);
107 int clientSock = UDSHelpers::acceptClient(sock);
109 UDSHelpers::waitForDisconnect(clientSock);
112 typedef std::function<void(int sock, pid_t pid,
113 const ProcessCredentials &peerCredentials)> SocketAssertionFn;
115 void socketTestTemplate(SocketAssertionFn assertion, const std::string &scope) {
116 const auto sockaddr = UDSHelpers::makeAbstractAddress("helper_" + scope + ".socket");
117 const ProcessCredentials peerCredentials;
119 SynchronizationPipe pipe;
121 pid_t pid = runInChild(std::bind(udsServer, std::ref(pipe), std::cref(sockaddr),
122 std::cref(peerCredentials)));
124 pipe.claimParentEp();
126 int sock = UDSHelpers::createClient(&sockaddr);
127 SockUniquePtr sockPtr(&sock);
129 assertion(sock, pid, peerCredentials);
132 RUNNER_TEST_GROUP_INIT(cynara_creds_socket)
134 void testSocketClientSmack(cynara_client_creds method = CLIENT_METHOD_SMACK) {
135 socketTestTemplate([method] (int sock, pid_t, const ProcessCredentials &peerCredentials) {
136 CStringPtr label(CynaraHelperCredentials::socketGetClient(sock, method));
137 RUNNER_ASSERT_MSG(peerCredentials.label() == label.get(),
138 "Labels don't match ret = " << label.get()
139 << "; expected = " << peerCredentials.label());
143 void testSocketClientPid(cynara_client_creds method = CLIENT_METHOD_PID) {
144 socketTestTemplate([method] (int sock, pid_t pid, const ProcessCredentials &) {
145 CStringPtr clientPidStr(CynaraHelperCredentials::socketGetClient(sock, method));
146 pid_t clientPid = std::stoi(clientPidStr.get());
147 RUNNER_ASSERT_MSG(pid == clientPid, "PIDs don't match ret = " << clientPid
148 << "; expected = " << pid);
152 RUNNER_MULTIPROCESS_TEST_SMACK(tccs01_socket_credentials_client_smack)
154 testSocketClientSmack();
157 RUNNER_MULTIPROCESS_TEST(tccs02_socket_credentials_client_pid)
159 testSocketClientPid();
162 RUNNER_MULTIPROCESS_TEST_SMACK(tccs03_socket_credentials_client_default)
164 auto method = getClientDefaultMethod();
166 case CLIENT_METHOD_SMACK:
167 testSocketClientSmack(CLIENT_METHOD_DEFAULT);
169 case CLIENT_METHOD_PID:
170 testSocketClientPid(CLIENT_METHOD_DEFAULT);
173 RUNNER_FAIL_MSG("cynara_creds_get_default_client_method returned unexpected value "
178 void testSocketUserUid(cynara_user_creds method = USER_METHOD_UID) {
179 socketTestTemplate([method] (int sock, pid_t, const ProcessCredentials &peerCredentials) {
180 CStringPtr uidStr(CynaraHelperCredentials::socketGetUser(sock, method));
181 uid_t uid = std::stoul(uidStr.get());
182 RUNNER_ASSERT_MSG(peerCredentials.uid() == uid, "UIDs don't match ret = " << uid
183 << "; expected = "<< peerCredentials.uid());
187 void testSocketUserGid(cynara_user_creds method = USER_METHOD_GID) {
188 socketTestTemplate([method] (int sock, pid_t, const ProcessCredentials &peerCredentials) {
189 CStringPtr gidStr(CynaraHelperCredentials::socketGetUser(sock, method));
190 gid_t gid = std::stoul(gidStr.get());
191 RUNNER_ASSERT_MSG(peerCredentials.gid() == gid, "GIDs don't match ret = " << gid
192 << "; expected = "<< peerCredentials.gid());
196 RUNNER_MULTIPROCESS_TEST(tccs04_socket_credentials_user_uid)
201 RUNNER_MULTIPROCESS_TEST(tccs05_socket_credentials_user_gid)
206 RUNNER_MULTIPROCESS_TEST(tccs06_socket_credentials_user_default)
208 auto method = getUserDefaultMethod();
210 case USER_METHOD_UID:
211 testSocketUserUid(USER_METHOD_DEFAULT);
213 case USER_METHOD_GID:
214 testSocketUserGid(USER_METHOD_DEFAULT);
217 RUNNER_FAIL_MSG("cynara_creds_get_default_user_method returned unexpected value "
222 RUNNER_MULTIPROCESS_TEST(tccs07_socket_credentials_pid)
224 socketTestTemplate([] (int sock, pid_t expectedPid, const ProcessCredentials &) {
225 pid_t peerPid(CynaraHelperCredentials::socketGetPid(sock));
226 RUNNER_ASSERT_MSG(peerPid == expectedPid, "Pids don't match ret = " << peerPid
227 << "; expected = "<< expectedPid);
231 // TODO: Create utility namespace for DBus, maybe?
232 DBusConnectionPtr createDBusConnection(const std::string &name) {
235 dbus_error_init(&err);
236 DBusConnection *conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
237 RUNNER_ASSERT_MSG(dbus_error_is_set(&err) != 1, "Error in dbus_bus_get: " << err.message);
238 dbus_connection_set_exit_on_disconnect(conn, FALSE);
240 DBusConnectionPtr ret(conn, [] (DBusConnection *conn) {
241 dbus_connection_close(conn);
242 dbus_connection_unref(conn);
245 if (name.empty() == false) {
246 dbus_bus_request_name(conn, name.c_str(), DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
247 RUNNER_ASSERT_MSG(dbus_error_is_set(&err) != TRUE,
248 "Error in dbus_bus_request_name: " << err.message);
254 void dbusServer(SynchronizationPipe &pipe, const std::string &requestedName,
255 const ProcessCredentials &peerCredentials) {
256 // for DBus connection, System must have access to our peer creds as well.
257 SecurityServer::AccessProvider systemAp("System");
258 systemAp.addObjectRule(peerCredentials.label(), "rwx");
261 SecurityServer::AccessProvider ap(peerCredentials.label());
262 ap.addObjectRule("System", "w");
263 ap.addObjectRule("System::Run", "x");
264 ap.addObjectRule("System::Shared", "rwx"); // for GDB
265 ap.addSubjectRule("System::Privileged", "rwx"); // for piping
266 ap.addObjectRule("System::Privileged", "rwx"); // for GDB and piping
267 ap.addObjectRule("User", "r"); // for /usr/lib/debug access
268 ap.applyAndSwithToUser(peerCredentials.uid(), peerCredentials.gid());
271 auto conn = createDBusConnection(requestedName);
276 typedef std::function<void(DBusConnectionPtr conn, pid_t pid,
277 const std::string &requestedName,
278 const ProcessCredentials &peerCredentials)> DBusAssertionFn;
280 void dbusTestTemplate(DBusAssertionFn assertion, const std::string &/*scope*/) {
281 std::string requestedName = "tests.dbus.cynara";
282 const ProcessCredentials peerCredentials;
284 SynchronizationPipe pipe;
285 pid_t pid = runInChild(std::bind(dbusServer, std::ref(pipe), std::cref(requestedName),
286 std::cref(peerCredentials)));
288 pipe.claimParentEp();
291 auto conn = createDBusConnection("");
292 assertion(std::move(conn), pid, requestedName, peerCredentials);
296 RUNNER_TEST_GROUP_INIT(cynara_creds_dbus)
298 void testDbusClientPid(cynara_client_creds method = CLIENT_METHOD_PID) {
299 dbusTestTemplate([method] (DBusConnectionPtr conn, pid_t pid, const std::string &requestedName,
300 const ProcessCredentials &) {
301 CStringPtr clientPidStr(CynaraHelperCredentials::dbusGetClient(std::move(conn),
302 requestedName.c_str(), method, CYNARA_API_SUCCESS));
303 pid_t clientPid = std::stoi(clientPidStr.get());
304 RUNNER_ASSERT_MSG(pid == clientPid, "PIDs don't match ret = " << clientPid
305 << "; expected = " << pid);
309 void testDbusClientSmack(cynara_client_creds method = CLIENT_METHOD_SMACK) {
310 dbusTestTemplate([method] (DBusConnectionPtr conn, pid_t, const std::string &requestedName,
311 const ProcessCredentials &peerCredentials) {
312 CStringPtr label(CynaraHelperCredentials::dbusGetClient(std::move(conn),
313 requestedName.c_str(), method, CYNARA_API_SUCCESS));
314 RUNNER_ASSERT_MSG(peerCredentials.label() == label.get(),
315 "Labels don't match ret = " << label.get()
316 << "; expected = " << peerCredentials.label());
320 RUNNER_MULTIPROCESS_TEST(tccd01_dbus_credentials_client_pid)
325 RUNNER_MULTIPROCESS_TEST_SMACK(tccd02_dbus_credentials_client_smack)
327 testDbusClientSmack();
330 RUNNER_MULTIPROCESS_TEST_SMACK(tccd03_dbus_credentials_client_default)
332 auto method = getClientDefaultMethod();
334 case CLIENT_METHOD_SMACK:
335 testDbusClientSmack(CLIENT_METHOD_DEFAULT);
337 case CLIENT_METHOD_PID:
338 testDbusClientPid(CLIENT_METHOD_DEFAULT);
341 RUNNER_FAIL_MSG("cynara_creds_get_default_client_method returned unexpected value "
346 void testDbusUserUid(cynara_user_creds method = USER_METHOD_UID) {
347 dbusTestTemplate([method] (DBusConnectionPtr conn, pid_t, const std::string &requestedName,
348 const ProcessCredentials &peerCredentials) {
349 CStringPtr uidStr(CynaraHelperCredentials::dbusGetUser(std::move(conn),
350 requestedName.c_str(), method, CYNARA_API_SUCCESS));
351 uid_t uid = std::stoul(uidStr.get());
352 RUNNER_ASSERT_MSG(peerCredentials.uid() == uid, "UIDs don't match ret = " << uid
353 << "; expected = "<< peerCredentials.uid());
357 void testDbusUserGid(cynara_user_creds method = USER_METHOD_GID) {
358 // Acquiring gid from dbus connection is not yet implemented for cynara helpers
359 dbusTestTemplate([method] (DBusConnectionPtr conn, pid_t, const std::string &requestedName,
360 const ProcessCredentials &) {
361 CStringPtr gidStr(CynaraHelperCredentials::dbusGetUser(std::move(conn),
362 requestedName.c_str(), method, CYNARA_API_METHOD_NOT_SUPPORTED));
366 RUNNER_MULTIPROCESS_TEST(tccd04_dbus_credentials_user_uid)
371 RUNNER_MULTIPROCESS_TEST(tccd05_dbus_credentials_user_gid)
376 RUNNER_MULTIPROCESS_TEST(tccd06_dbus_credentials_user_default) {
377 auto method = getUserDefaultMethod();
379 case USER_METHOD_UID:
380 testDbusUserUid(USER_METHOD_DEFAULT);
382 case USER_METHOD_GID:
383 testDbusUserGid(USER_METHOD_DEFAULT);
386 RUNNER_FAIL_MSG("cynara_creds_get_default_user_method returned unexpected value "
391 RUNNER_TEST_SMACK(tccd06_dbus_credentials_pid) {
392 dbusTestTemplate([] (DBusConnectionPtr conn, pid_t expectedPid,
393 const std::string &requestedName, const ProcessCredentials &) {
394 auto helperPid = CynaraHelperCredentials::dbusGetPid(std::move(conn),
395 requestedName.c_str(), CYNARA_API_SUCCESS);
396 RUNNER_ASSERT_MSG(helperPid == expectedPid, "PIDs don't match ret = " << helperPid
397 << "; expected = " << expectedPid);
401 GDBusConnectionPtr createGDBusConnection() {
402 GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
404 return GDBusConnectionPtr(conn, [] (GDBusConnection *conn) {
405 g_object_unref(G_OBJECT(conn));
410 typedef std::function<void(GDBusConnectionPtr conn, pid_t pid,
411 const std::string &requestedName,
412 const ProcessCredentials &peerCredentials)> GDBusAssertionFn;
414 void gdbusTestTemplate(GDBusAssertionFn assertion, const std::string &/*scope*/) {
415 std::string requestedName = "tests.dbus.cynara";
416 const ProcessCredentials peerCredentials;
418 SynchronizationPipe pipe;
419 pid_t pid = runInChild(std::bind(dbusServer, std::ref(pipe), std::cref(requestedName),
420 std::cref(peerCredentials)));
422 pipe.claimParentEp();
425 auto conn = createGDBusConnection();
426 assertion(std::move(conn), pid, requestedName, peerCredentials);
431 RUNNER_TEST_GROUP_INIT(cynara_creds_gdbus)
433 RUNNER_TEST_SMACK(tccgd01_gdbus_credentials_client_pid) {
434 gdbusTestTemplate([] (GDBusConnectionPtr conn, pid_t pid, const std::string &requestedName,
435 const ProcessCredentials &) {
436 GStringPtr clientPidStr(CynaraHelperCredentials::gdbusGetClient(std::move(conn),
437 requestedName.c_str(), CLIENT_METHOD_PID));
438 pid_t clientPid = std::stoi(clientPidStr.get());
439 RUNNER_ASSERT_MSG(pid == clientPid, "PIDs don't match ret = " << clientPid
440 << "; expected = " << pid);
444 RUNNER_TEST_SMACK(tccgd02_gdbus_credentials_client_smack) {
445 gdbusTestTemplate([] (GDBusConnectionPtr conn, pid_t, const std::string &requestedName,
446 const ProcessCredentials &peerCredentials) {
447 GStringPtr label(CynaraHelperCredentials::gdbusGetClient(std::move(conn),
448 requestedName.c_str(), CLIENT_METHOD_SMACK));
449 RUNNER_ASSERT_MSG(peerCredentials.label() == label.get(),
450 "Labels don't match ret = " << label.get()
451 << "; expected = " << peerCredentials.label());
455 RUNNER_TEST_SMACK(tccgd03_gdbus_credentials_user_uid) {
456 gdbusTestTemplate([] (GDBusConnectionPtr conn, pid_t, const std::string &requestedName,
457 const ProcessCredentials &peerCredentials) {
458 GStringPtr uidStr(CynaraHelperCredentials::gdbusGetUser(std::move(conn),
459 requestedName.c_str(), USER_METHOD_UID));
460 uid_t uid = std::stoul(uidStr.get());
461 RUNNER_ASSERT_MSG(peerCredentials.uid() == uid, "UIDs don't match ret = " << uid
462 << "; expected = "<< peerCredentials.uid());
466 RUNNER_TEST_SMACK(tccgd04_gdbus_credentials_pid) {
467 gdbusTestTemplate([] (GDBusConnectionPtr conn, pid_t expectedPid,
468 const std::string &requestedName, const ProcessCredentials &) {
469 auto helperPid = CynaraHelperCredentials::gdbusGetPid(std::move(conn),
470 requestedName.c_str());
471 RUNNER_ASSERT_MSG(helperPid == expectedPid, "PIDs don't match ret = " << helperPid
472 << "; expected = " << expectedPid);
476 RUNNER_TEST_GROUP_INIT(cynara_creds_self)
478 void testCredsClientSelf(cynara_client_creds method, const std::string &expected) {
480 int ret = cynara_creds_self_get_client(method, &client);
481 CStringPtr clientPtr(client);
482 RUNNER_ASSERT_MSG(ret == CYNARA_API_SUCCESS, "cynara_creds_self_get_client failed with " << ret);
483 RUNNER_ASSERT_MSG(expected == client, "expected client doesn't match, expected: " << expected
484 << ", got : " << client);
487 void testCredsUserSelf(cynara_user_creds method, const std::string &expected) {
489 int ret = cynara_creds_self_get_user(method, &user);
490 CStringPtr clientPtr(user);
491 RUNNER_ASSERT_MSG(ret == CYNARA_API_SUCCESS, "cynara_creds_self_get_user failed with " << ret);
492 RUNNER_ASSERT_MSG(expected == user, "expected user doesn't match, expected: " << expected
493 << ", got : " << user);
496 void testSelfClientSmack(cynara_client_creds method = CLIENT_METHOD_SMACK) {
497 std::string label = "test-label";
498 change_label(label.c_str());
499 testCredsClientSelf(method, label);
502 void testSelfClientPid(cynara_client_creds method = CLIENT_METHOD_PID) {
503 pid_t pid = getpid();
504 testCredsClientSelf(method, std::to_string(pid));
507 void testSelfUserUid(cynara_user_creds method = USER_METHOD_UID) {
508 uid_t uid = getuid();
509 testCredsUserSelf(method, std::to_string(uid));
512 void testSelfUserGid(cynara_user_creds method = USER_METHOD_GID) {
513 gid_t gid = getgid();
514 testCredsUserSelf(method, std::to_string(gid));
517 RUNNER_CHILD_TEST_SMACK(tccsl01_self_credentials_client_smack) {
518 testSelfClientSmack();
521 RUNNER_CHILD_TEST_SMACK(tccsl02_self_credentials_client_pid) {
525 RUNNER_CHILD_TEST_SMACK(tccsl03_self_credentials_user_uid) {
529 RUNNER_CHILD_TEST_SMACK(tccsl04_self_credentials_user_gid) {
533 RUNNER_CHILD_TEST_SMACK(tccsl05_self_credentials_client_default) {
534 auto method = getClientDefaultMethod();
536 case CLIENT_METHOD_SMACK:
537 testSelfClientSmack(CLIENT_METHOD_DEFAULT);
539 case CLIENT_METHOD_PID:
540 testSelfClientPid(CLIENT_METHOD_DEFAULT);
543 RUNNER_FAIL_MSG("cynara_creds_get_default_client_method returned unexpected value " << method);
547 RUNNER_CHILD_TEST_SMACK(tccsl06_self_credentials_user_default) {
548 auto method = getUserDefaultMethod();
550 case USER_METHOD_UID:
551 testSelfUserUid(USER_METHOD_DEFAULT);
553 case USER_METHOD_GID:
554 testSelfUserGid(USER_METHOD_DEFAULT);
557 RUNNER_FAIL_MSG("cynara_creds_get_default_user_method returned unexpected value " << method);