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>
48 class ProcessCredentials {
50 ProcessCredentials() {}
52 const std::string &label(void) const {
56 uid_t uid(void) const {
57 return PasswdAccess::uid(APP_USER);
60 gid_t gid(void) const {
61 return PasswdAccess::gid("users");
65 std::string m_label = "cynara_helpers";
68 pid_t runInChild(const std::function<void(void)> &process) {
70 RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "fork failed");
80 void udsServer(SynchronizationPipe &pipe, const struct sockaddr_un &sockaddr,
81 const struct ProcessCredentials &peerCredentials) {
82 SecurityServer::AccessProvider ap(peerCredentials.label());
83 ap.applyAndSwithToUser(peerCredentials.uid(), peerCredentials.gid());
86 int sock = UDSHelpers::createServer(&sockaddr);
87 SockUniquePtr sockPtr(&sock);
89 int clientSock = UDSHelpers::acceptClient(sock);
91 UDSHelpers::waitForDisconnect(clientSock);
94 typedef std::function<void(int sock, pid_t pid,
95 const ProcessCredentials &peerCredentials)> SocketAssertionFn;
97 void socketTestTemplate(SocketAssertionFn assertion, const std::string &scope) {
98 const auto sockaddr = UDSHelpers::makeAbstractAddress("helper_" + scope + ".socket");
99 const ProcessCredentials peerCredentials;
101 SynchronizationPipe pipe;
103 pid_t pid = runInChild(std::bind(udsServer, std::ref(pipe), std::cref(sockaddr),
104 std::cref(peerCredentials)));
106 pipe.claimParentEp();
108 int sock = UDSHelpers::createClient(&sockaddr);
109 SockUniquePtr sockPtr(&sock);
111 assertion(sock, pid, peerCredentials);
114 RUNNER_TEST_GROUP_INIT(cynara_creds_socket)
116 RUNNER_CHILD_TEST_SMACK(tccs01_socket_credentials_client_smack)
118 socketTestTemplate([] (int sock, pid_t, const ProcessCredentials &peerCredentials) {
119 CStringPtr label(CynaraHelperCredentials::socketGetClient(sock, CLIENT_METHOD_SMACK));
120 RUNNER_ASSERT_MSG(peerCredentials.label() == label.get(),
121 "Labels don't match ret = " << label.get()
122 << "; expected = " << peerCredentials.label());
126 RUNNER_CHILD_TEST_SMACK(tccs02_socket_credentials_client_pid)
128 socketTestTemplate([] (int sock, pid_t pid, const ProcessCredentials &) {
129 CStringPtr clientPidStr(CynaraHelperCredentials::socketGetClient(sock, CLIENT_METHOD_PID));
130 pid_t clientPid = std::stoi(clientPidStr.get());
131 RUNNER_ASSERT_MSG(pid == clientPid, "PIDs don't match ret = " << clientPid
132 << "; expected = " << pid);
136 RUNNER_CHILD_TEST_SMACK(tccs03_socket_credentials_user_uid)
138 socketTestTemplate([] (int sock, pid_t, const ProcessCredentials &peerCredentials) {
139 CStringPtr uidStr(CynaraHelperCredentials::socketGetUser(sock, USER_METHOD_UID));
140 uid_t uid = std::stoul(uidStr.get());
141 RUNNER_ASSERT_MSG(peerCredentials.uid() == uid, "UIDs don't match ret = " << uid
142 << "; expected = "<< peerCredentials.uid());
146 RUNNER_CHILD_TEST_SMACK(tccs04_socket_credentials_user_gid)
148 socketTestTemplate([] (int sock, pid_t, const ProcessCredentials &peerCredentials) {
149 CStringPtr gidStr(CynaraHelperCredentials::socketGetUser(sock, USER_METHOD_GID));
150 gid_t gid = std::stoul(gidStr.get());
151 RUNNER_ASSERT_MSG(peerCredentials.gid() == gid, "GIDs don't match ret = " << gid
152 << "; expected = "<< peerCredentials.gid());
156 RUNNER_CHILD_TEST_SMACK(tccs05_cynara_creds_socket_pid)
158 const auto sockaddr = UDSHelpers::makeAbstractAddress("helper_tccs05.socket");
159 const ProcessCredentials peerCredentials;
161 SynchronizationPipe pipe;
162 pid_t expectedPid = runInChild(std::bind(udsServer, std::ref(pipe), std::cref(sockaddr),
163 std::cref(peerCredentials)));
165 pipe.claimParentEp();
167 int sock = UDSHelpers::createClient(&sockaddr);
168 SockUniquePtr sockPtr(&sock);
170 pid_t helperPid = CynaraHelperCredentials::socketGetPid(sock);
171 RUNNER_ASSERT_MSG(helperPid == expectedPid, "PIDs don't match ret = " << helperPid
172 << "; expected = " << expectedPid);
175 // TODO: Create utility namespace for DBus, maybe?
176 DBusConnectionPtr createDBusConnection(const std::string &name) {
179 dbus_error_init(&err);
180 DBusConnection *conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
181 RUNNER_ASSERT_MSG(dbus_error_is_set(&err) != 1, "Error in dbus_bus_get: " << err.message);
182 dbus_connection_set_exit_on_disconnect(conn, FALSE);
184 DBusConnectionPtr ret(conn, [] (DBusConnection *conn) {
185 dbus_connection_close(conn);
186 dbus_connection_unref(conn);
189 if (name.empty() == false) {
190 dbus_bus_request_name(conn, name.c_str(), DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
191 RUNNER_ASSERT_MSG(dbus_error_is_set(&err) != TRUE,
192 "Error in dbus_bus_request_name: " << err.message);
198 void dbusServer(SynchronizationPipe &pipe, const std::string &requestedName,
199 const ProcessCredentials &peerCredentials) {
200 // for DBus connection, System must have access to our peer creds as well.
201 SecurityServer::AccessProvider systemAp("System");
202 systemAp.addObjectRule(peerCredentials.label(), "rwx");
205 SecurityServer::AccessProvider ap(peerCredentials.label());
206 ap.addObjectRule("System", "w");
207 ap.addObjectRule("System::Run", "x");
208 ap.addObjectRule("System::Shared", "x"); // for GDB
209 ap.addObjectRule("User", "r"); // for /usr/lib/debug access
210 ap.applyAndSwithToUser(peerCredentials.uid(), peerCredentials.gid());
213 auto conn = createDBusConnection(requestedName);
218 typedef std::function<void(DBusConnectionPtr conn, pid_t pid,
219 const std::string &requestedName,
220 const ProcessCredentials &peerCredentials)> DBusAssertionFn;
222 void dbusTestTemplate(DBusAssertionFn assertion, const std::string &/*scope*/) {
223 std::string requestedName = "tests.dbus.cynara";
224 const ProcessCredentials peerCredentials;
226 SynchronizationPipe pipe;
227 pid_t pid = runInChild(std::bind(dbusServer, std::ref(pipe), std::cref(requestedName),
228 std::cref(peerCredentials)));
230 pipe.claimParentEp();
233 auto conn = createDBusConnection("");
234 assertion(std::move(conn), pid, requestedName, peerCredentials);
238 RUNNER_TEST_GROUP_INIT(cynara_creds_dbus)
240 RUNNER_TEST_SMACK(tccd01_dbus_credentials_client_pid) {
241 dbusTestTemplate([] (DBusConnectionPtr conn, pid_t pid, const std::string &requestedName,
242 const ProcessCredentials &) {
243 CStringPtr clientPidStr(CynaraHelperCredentials::dbusGetClient(std::move(conn),
244 requestedName.c_str(), CLIENT_METHOD_PID, CYNARA_API_SUCCESS));
245 pid_t clientPid = std::stoi(clientPidStr.get());
246 RUNNER_ASSERT_MSG(pid == clientPid, "PIDs don't match ret = " << clientPid
247 << "; expected = " << pid);
251 RUNNER_TEST_SMACK(tccd02_dbus_credentials_client_smack) {
252 dbusTestTemplate([] (DBusConnectionPtr conn, pid_t, const std::string &requestedName,
253 const ProcessCredentials &peerCredentials) {
254 CStringPtr label(CynaraHelperCredentials::dbusGetClient(std::move(conn),
255 requestedName.c_str(), CLIENT_METHOD_SMACK, CYNARA_API_SUCCESS));
256 RUNNER_ASSERT_MSG(peerCredentials.label() == label.get(),
257 "Labels don't match ret = " << label.get()
258 << "; expected = " << peerCredentials.label());
262 RUNNER_TEST_SMACK(tccd03_dbus_credentials_user_uid) {
263 dbusTestTemplate([] (DBusConnectionPtr conn, pid_t, const std::string &requestedName,
264 const ProcessCredentials &peerCredentials) {
265 CStringPtr uidStr(CynaraHelperCredentials::dbusGetUser(std::move(conn),
266 requestedName.c_str(), USER_METHOD_UID, CYNARA_API_SUCCESS));
267 uid_t uid = std::stoul(uidStr.get());
268 RUNNER_ASSERT_MSG(peerCredentials.uid() == uid, "UIDs don't match ret = " << uid
269 << "; expected = "<< peerCredentials.uid());
273 RUNNER_TEST_SMACK(tccd04_dbus_credentials_pid) {
274 dbusTestTemplate([] (DBusConnectionPtr conn, pid_t expectedPid,
275 const std::string &requestedName, const ProcessCredentials &) {
276 auto helperPid = CynaraHelperCredentials::dbusGetPid(std::move(conn),
277 requestedName.c_str(), CYNARA_API_SUCCESS);
278 RUNNER_ASSERT_MSG(helperPid == expectedPid, "PIDs don't match ret = " << helperPid
279 << "; expected = " << expectedPid);
283 GDBusConnectionPtr createGDBusConnection() {
284 GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
286 return GDBusConnectionPtr(conn, [] (GDBusConnection *conn) {
287 g_object_unref(G_OBJECT(conn));
292 typedef std::function<void(GDBusConnectionPtr conn, pid_t pid,
293 const std::string &requestedName,
294 const ProcessCredentials &peerCredentials)> GDBusAssertionFn;
296 void gdbusTestTemplate(GDBusAssertionFn assertion, const std::string &/*scope*/) {
297 std::string requestedName = "tests.dbus.cynara";
298 const ProcessCredentials peerCredentials;
300 SynchronizationPipe pipe;
301 pid_t pid = runInChild(std::bind(dbusServer, std::ref(pipe), std::cref(requestedName),
302 std::cref(peerCredentials)));
304 pipe.claimParentEp();
307 auto conn = createGDBusConnection();
308 assertion(std::move(conn), pid, requestedName, peerCredentials);
313 RUNNER_TEST_GROUP_INIT(cynara_creds_gdbus)
315 RUNNER_TEST_SMACK(tccgd01_gdbus_credentials_client_pid) {
316 gdbusTestTemplate([] (GDBusConnectionPtr conn, pid_t pid, const std::string &requestedName,
317 const ProcessCredentials &) {
318 GStringPtr clientPidStr(CynaraHelperCredentials::gdbusGetClient(std::move(conn),
319 requestedName.c_str(), CLIENT_METHOD_PID));
320 pid_t clientPid = std::stoi(clientPidStr.get());
321 RUNNER_ASSERT_MSG(pid == clientPid, "PIDs don't match ret = " << clientPid
322 << "; expected = " << pid);
326 RUNNER_TEST_SMACK(tccgd02_gdbus_credentials_client_smack) {
327 gdbusTestTemplate([] (GDBusConnectionPtr conn, pid_t, const std::string &requestedName,
328 const ProcessCredentials &peerCredentials) {
329 GStringPtr label(CynaraHelperCredentials::gdbusGetClient(std::move(conn),
330 requestedName.c_str(), CLIENT_METHOD_SMACK));
331 RUNNER_ASSERT_MSG(peerCredentials.label() == label.get(),
332 "Labels don't match ret = " << label.get()
333 << "; expected = " << peerCredentials.label());
337 RUNNER_TEST_SMACK(tccgd03_gdbus_credentials_user_uid) {
338 gdbusTestTemplate([] (GDBusConnectionPtr conn, pid_t, const std::string &requestedName,
339 const ProcessCredentials &peerCredentials) {
340 GStringPtr uidStr(CynaraHelperCredentials::gdbusGetUser(std::move(conn),
341 requestedName.c_str(), USER_METHOD_UID));
342 uid_t uid = std::stoul(uidStr.get());
343 RUNNER_ASSERT_MSG(peerCredentials.uid() == uid, "UIDs don't match ret = " << uid
344 << "; expected = "<< peerCredentials.uid());
348 RUNNER_TEST_SMACK(tccgd04_gdbus_credentials_pid) {
349 gdbusTestTemplate([] (GDBusConnectionPtr conn, pid_t expectedPid,
350 const std::string &requestedName, const ProcessCredentials &) {
351 auto helperPid = CynaraHelperCredentials::gdbusGetPid(std::move(conn),
352 requestedName.c_str());
353 RUNNER_ASSERT_MSG(helperPid == expectedPid, "PIDs don't match ret = " << helperPid
354 << "; expected = " << expectedPid);