1 #include <dpl/test/test_runner.h>
6 #include <unordered_set>
7 #include <sys/capability.h>
9 #include <sys/socket.h>
11 #include <attr/xattr.h>
12 #include <linux/xattr.h>
17 #include <libprivilege-control_test_common.h>
18 #include <tests_common.h>
20 #include <security-manager.h>
23 #include <sm_request.h>
24 #include <cynara_test_client.h>
25 #include <dbus_access.h>
27 using namespace SecurityManagerTest;
29 DEFINE_SMARTPTR(cap_free, _cap_struct, CapsSetsUniquePtr);
31 static const privileges_t SM_ALLOWED_PRIVILEGES = {
32 "security_manager_test_rules2_r",
33 "security_manager_test_rules2_no_r"
36 static const privileges_t SM_DENIED_PRIVILEGES = {
37 "security_manager_test_rules1",
38 "security_manager_test_rules2"
41 static const privileges_t SM_NO_PRIVILEGES = {
44 static const std::vector<std::string> SM_ALLOWED_GROUPS = {"db_browser", "db_alarm"};
46 static const char *const SM_PRIVATE_PATH = "/usr/apps/test_DIR/app_dir";
47 static const char *const SM_PUBLIC_RO_PATH = "/usr/apps/test_DIR/app_dir_public_ro";
48 static const char *const SM_DENIED_PATH = "/usr/apps/test_DIR/non_app_dir";
49 static const char *const SM_PRIVATE_PATH_FOR_USER = "/home/" APP_USER "/test_DIR";
50 static const char *const ANY_USER_REPRESENTATION = "anyuser";/*this may be actually any string*/
52 static void generateAppLabel(const std::string &pkgId, std::string &label)
58 static int nftw_check_sm_labels_app_dir(const char *fpath, const struct stat *sb,
59 const char* correctLabel, bool transmute_test, bool exec_test)
63 char* label = nullptr;
66 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
67 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
68 labelPtr.reset(label);
69 RUNNER_ASSERT_MSG(label != nullptr, "ACCESS label on " << fpath << " is not set");
70 result = strcmp(correctLabel, label);
71 RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect"
72 " (should be '" << correctLabel << "' and is '" << label << "')");
76 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
77 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
78 labelPtr.reset(label);
80 if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR) && exec_test) {
81 RUNNER_ASSERT_MSG(label != nullptr, "EXEC label on " << fpath << " is not set");
82 result = strcmp(correctLabel, label);
83 RUNNER_ASSERT_MSG(result == 0, "Incorrect EXEC label on executable file " << fpath);
85 RUNNER_ASSERT_MSG(label == nullptr, "EXEC label on " << fpath << " is set");
89 result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
90 RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
91 labelPtr.reset(label);
93 if (S_ISDIR(sb->st_mode) && transmute_test == true) {
94 RUNNER_ASSERT_MSG(label != nullptr, "TRANSMUTE label on " << fpath << " is not set at all");
95 RUNNER_ASSERT_MSG(strcmp(label,"TRUE") == 0,
96 "TRANSMUTE label on " << fpath << " is not set properly: '"<<label<<"'");
98 RUNNER_ASSERT_MSG(label == nullptr, "TRANSMUTE label on " << fpath << " is set");
105 static int nftw_check_sm_labels_app_private_dir(const char *fpath, const struct stat *sb,
106 int /*typeflag*/, struct FTW* /*ftwbuf*/)
108 return nftw_check_sm_labels_app_dir(fpath, sb, USER_APP_ID, false, true);
111 static int nftw_check_sm_labels_app_floor_dir(const char *fpath, const struct stat *sb,
112 int /*typeflag*/, struct FTW* /*ftwbuf*/)
115 return nftw_check_sm_labels_app_dir(fpath, sb, "_", false, false);
118 static void prepare_app_path()
122 result = nftw(SM_PRIVATE_PATH, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
123 RUNNER_ASSERT_MSG(result == 0, "Unable to clean Smack labels in " << SM_PRIVATE_PATH);
125 result = nftw(SM_PUBLIC_RO_PATH, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
126 RUNNER_ASSERT_MSG(result == 0, "Unable to clean Smack labels in " << SM_PUBLIC_RO_PATH);
128 result = nftw(SM_DENIED_PATH, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
129 RUNNER_ASSERT_MSG(result == 0, "Unable to set Smack labels in " << SM_DENIED_PATH);
132 static void prepare_app_env()
137 /* TODO: add parameters to this function */
138 static void check_app_path_after_install()
142 result = nftw(SM_PRIVATE_PATH, &nftw_check_sm_labels_app_private_dir, FTW_MAX_FDS, FTW_PHYS);
143 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << SM_PRIVATE_PATH);
145 result = nftw(SM_PUBLIC_RO_PATH, &nftw_check_sm_labels_app_floor_dir, FTW_MAX_FDS, FTW_PHYS);
146 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << SM_PUBLIC_RO_PATH);
148 result = nftw(SM_DENIED_PATH, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
149 RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << SM_DENIED_PATH);
153 static void check_app_permissions(const char *const app_id, const char *const pkg_id, const char *const user,
154 const privileges_t &allowed_privs, const privileges_t &denied_privs)
157 std::string smackLabel;
158 generateAppLabel(pkg_id, smackLabel);
160 CynaraTestClient ctc;
162 for (auto &priv : allowed_privs) {
163 ctc.check(smackLabel.c_str(), "", user, priv.c_str(), CYNARA_API_ACCESS_ALLOWED);
166 for (auto &priv : denied_privs) {
167 ctc.check(smackLabel.c_str(), "", user, priv.c_str(), CYNARA_API_ACCESS_DENIED);
171 static void check_app_gids(const char *const app_id, const std::vector<gid_t> &allowed_gids)
174 gid_t main_gid = getgid();
175 std::unordered_set<gid_t> reference_gids(allowed_gids.begin(), allowed_gids.end());
177 // Reset supplementary groups
178 ret = setgroups(0, NULL);
179 RUNNER_ASSERT_MSG(ret != -1, "Unable to set supplementary groups");
181 Api::setProcessGroups(app_id);
183 ret = getgroups(0, nullptr);
184 RUNNER_ASSERT_MSG(ret != -1, "Unable to get supplementary groups");
186 std::vector<gid_t> actual_gids(ret);
187 ret = getgroups(ret, actual_gids.data());
188 RUNNER_ASSERT_MSG(ret != -1, "Unable to get supplementary groups");
190 for (const auto &gid : actual_gids) {
191 RUNNER_ASSERT_MSG(gid == main_gid || reference_gids.count(gid) > 0,
192 "Application shouldn't get access to group " << gid);
193 reference_gids.erase(gid);
196 RUNNER_ASSERT_MSG(reference_gids.empty(), "Application didn't get access to some groups");
199 static void check_app_after_install(const char *const app_id, const char *const pkg_id,
200 const privileges_t &allowed_privs,
201 const privileges_t &denied_privs,
202 const std::vector<std::string> &allowed_groups)
204 TestSecurityManagerDatabase dbtest;
205 dbtest.test_db_after__app_install(app_id, pkg_id, allowed_privs);
206 dbtest.check_privileges_removed(app_id, pkg_id, denied_privs);
208 /*Privileges should be granted to all users if root installs app*/
209 check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, allowed_privs, denied_privs);
211 /* Setup mapping of gids to privileges */
212 /* Do this for each privilege for extra check */
213 for (const auto &privilege : allowed_privs) {
214 dbtest.setup_privilege_groups(privilege, allowed_groups);
217 std::vector<gid_t> allowed_gids;
219 for (const auto &groupName : allowed_groups) {
221 struct group* grp = getgrnam(groupName.c_str());
222 RUNNER_ASSERT_ERRNO_MSG(grp, "Group: " << groupName << " not found");
223 allowed_gids.push_back(grp->gr_gid);
226 check_app_gids(app_id, allowed_gids);
229 static void check_app_after_install(const char *const app_id, const char *const pkg_id)
231 TestSecurityManagerDatabase dbtest;
232 dbtest.test_db_after__app_install(app_id, pkg_id);
235 static void check_app_after_uninstall(const char *const app_id, const char *const pkg_id,
236 const privileges_t &privileges, const bool is_pkg_removed)
238 TestSecurityManagerDatabase dbtest;
239 dbtest.test_db_after__app_uninstall(app_id, pkg_id, privileges, is_pkg_removed);
242 /*Privileges should not be granted anymore to any user*/
243 check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, SM_NO_PRIVILEGES, privileges);
246 static void check_app_after_uninstall(const char *const app_id, const char *const pkg_id,
247 const bool is_pkg_removed)
249 TestSecurityManagerDatabase dbtest;
250 dbtest.test_db_after__app_uninstall(app_id, pkg_id, is_pkg_removed);
253 static void install_app(const char *app_id, const char *pkg_id)
255 InstallRequest request;
256 request.setAppId(app_id);
257 request.setPkgId(pkg_id);
259 Api::install(request);
261 check_app_after_install(app_id, pkg_id);
265 static void uninstall_app(const char *app_id, const char *pkg_id, bool expect_pkg_removed)
267 InstallRequest request;
268 request.setAppId(app_id);
270 Api::uninstall(request);
272 check_app_after_uninstall(app_id, pkg_id, expect_pkg_removed);
276 RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER)
279 RUNNER_TEST(security_manager_01_app_double_install_double_uninstall)
281 const char *const sm_app_id = "sm_test_01_app_id_double";
282 const char *const sm_pkg_id = "sm_test_01_pkg_id_double";
284 InstallRequest requestInst;
285 requestInst.setAppId(sm_app_id);
286 requestInst.setPkgId(sm_pkg_id);
288 Api::install(requestInst);
289 Api::install(requestInst);
291 /* Check records in the security-manager database */
292 check_app_after_install(sm_app_id, sm_pkg_id);
294 InstallRequest requestUninst;
295 requestUninst.setAppId(sm_app_id);
297 Api::uninstall(requestUninst);
298 Api::uninstall(requestUninst);
300 /* Check records in the security-manager database */
301 check_app_after_uninstall(sm_app_id, sm_pkg_id, TestSecurityManagerDatabase::REMOVED);
304 RUNNER_TEST(security_manager_02_app_install_uninstall_full)
306 const char *const sm_app_id = "sm_test_02_app_id_full";
307 const char *const sm_pkg_id = "sm_test_02_pkg_id_full";
311 InstallRequest requestInst;
312 requestInst.setAppId(sm_app_id);
313 requestInst.setPkgId(sm_pkg_id);
314 requestInst.addPrivilege(SM_ALLOWED_PRIVILEGES[0].c_str());
315 requestInst.addPrivilege(SM_ALLOWED_PRIVILEGES[1].c_str());
316 requestInst.addPath(SM_PRIVATE_PATH, SECURITY_MANAGER_PATH_PRIVATE);
317 requestInst.addPath(SM_PUBLIC_RO_PATH, SECURITY_MANAGER_PATH_PUBLIC_RO);
319 Api::install(requestInst);
321 /* Check records in the security-manager database */
322 check_app_after_install(sm_app_id, sm_pkg_id,
323 SM_ALLOWED_PRIVILEGES, SM_DENIED_PRIVILEGES, SM_ALLOWED_GROUPS);
325 /* TODO: add parameters to this function */
326 check_app_path_after_install();
328 InstallRequest requestUninst;
329 requestUninst.setAppId(sm_app_id);
331 Api::uninstall(requestUninst);
333 /* Check records in the security-manager database,
334 * all previously allowed privileges should be removed */
335 check_app_after_uninstall(sm_app_id, sm_pkg_id,
336 SM_ALLOWED_PRIVILEGES, TestSecurityManagerDatabase::REMOVED);
339 RUNNER_CHILD_TEST_SMACK(security_manager_03_set_label_from_appid)
341 const char *const app_id = "sm_test_03_app_id_set_label_from_appid_smack";
342 const char *const pkg_id = "sm_test_03_pkg_id_set_label_from_appid_smack";
343 const char *const expected_label = USER_APP_ID;
344 const char *const socketLabel = "not_expected_label";
345 char *label = nullptr;
349 uninstall_app(app_id, pkg_id, true);
350 install_app(app_id, pkg_id);
352 struct sockaddr_un sockaddr = {AF_UNIX, SOCK_PATH};
353 //Clean up before creating socket
355 int sock = socket(AF_UNIX, SOCK_STREAM, 0);
356 RUNNER_ASSERT_ERRNO_MSG(sock >= 0, "socket failed");
357 SockUniquePtr sockPtr(&sock);
358 //Bind socket to address
359 result = bind(sock, (struct sockaddr*) &sockaddr, sizeof(struct sockaddr_un));
360 RUNNER_ASSERT_ERRNO_MSG(result == 0, "bind failed");
361 //Set socket label to something different than expecedLabel
362 result = fsetxattr(sock, XATTR_NAME_SMACKIPIN, socketLabel,
363 strlen(socketLabel), 0);
364 RUNNER_ASSERT_ERRNO_MSG(result == 0,
365 "Can't set socket label. Result: " << result);
366 result = fsetxattr(sock, XATTR_NAME_SMACKIPOUT, socketLabel,
367 strlen(socketLabel), 0);
368 RUNNER_ASSERT_ERRNO_MSG(result == 0,
369 "Can't set socket label. Result: " << result);
371 Api::setProcessLabel(app_id);
373 char value[SMACK_LABEL_LEN + 1];
375 size = fgetxattr(sock, XATTR_NAME_SMACKIPIN, value, sizeof(value));
376 RUNNER_ASSERT_ERRNO_MSG(size != -1, "fgetxattr failed: " << value);
377 result = strcmp(expected_label, value);
378 RUNNER_ASSERT_MSG(result == 0, "Socket label is incorrect. Expected: " <<
379 expected_label << " Actual: " << value);
381 size = fgetxattr(sock, XATTR_NAME_SMACKIPOUT, value, sizeof(value));
382 RUNNER_ASSERT_ERRNO_MSG(size != -1, "fgetxattr failed: " << value);
383 result = strcmp(expected_label, value);
384 RUNNER_ASSERT_MSG(result == 0, "Socket label is incorrect. Expected: " <<
385 expected_label << " Actual: " << value);
387 result = smack_new_label_from_self(&label);
388 RUNNER_ASSERT_MSG(result >= 0,
389 " Error getting current process label");
390 RUNNER_ASSERT_MSG(label != nullptr,
391 " Process label is not set");
392 labelPtr.reset(label);
394 result = strcmp(expected_label, label);
395 RUNNER_ASSERT_MSG(result == 0,
396 " Process label is incorrect. Expected: \"" << expected_label <<
397 "\" Actual: \"" << label << "\"");
399 uninstall_app(app_id, pkg_id, true);
402 RUNNER_CHILD_TEST_NOSMACK(security_manager_03_set_label_from_appid_nosmack)
404 const char *const app_id = "sm_test_03_app_id_set_label_from_appid_nosmack";
405 const char *const pkg_id = "sm_test_03_pkg_id_set_label_from_appid_nosmack";
407 uninstall_app(app_id, pkg_id, true);
408 install_app(app_id, pkg_id);
410 Api::setProcessLabel(app_id);
412 uninstall_app(app_id, pkg_id, true);
417 static void prepare_request(InstallRequest &request,
418 const char *const app_id,
419 const char *const pkg_id,
420 app_install_path_type pathType,
421 const char *const path,
424 request.setAppId(app_id);
425 request.setPkgId(pkg_id);
426 request.addPath(path, pathType);
433 static struct passwd* get_app_pw()
435 struct passwd *pw = nullptr;
437 while(!(pw = getpwnam(APP_USER))) {
438 RUNNER_ASSERT_ERRNO_MSG(errno == EINTR, "getpwnam() failed");
444 static void install_and_check(const char *const sm_app_id,
445 const char *const sm_pkg_id,
446 const std::string &user, uid_t uid)
448 InstallRequest requestPublic;
450 //install app for non-root user and try to register public path (should fail)
451 prepare_request(requestPublic, sm_app_id, sm_pkg_id, SECURITY_MANAGER_PATH_PUBLIC, SM_PRIVATE_PATH_FOR_USER, uid);
453 Api::install(requestPublic, SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED);
455 InstallRequest requestPrivate;
457 //install app for non-root user
458 //should fail (users may only register folders inside their home)
459 prepare_request(requestPrivate, sm_app_id, sm_pkg_id, SECURITY_MANAGER_PATH_PRIVATE, SM_PRIVATE_PATH, uid);
461 Api::install(requestPrivate, SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED);
463 InstallRequest requestPrivateUser;
465 //install app for non-root user
466 //should succeed - this time i register folder inside user's home dir
467 prepare_request(requestPrivateUser, sm_app_id, sm_pkg_id, SECURITY_MANAGER_PATH_PRIVATE, SM_PRIVATE_PATH_FOR_USER, uid);
469 for (auto &privilege : SM_ALLOWED_PRIVILEGES)
470 requestPrivateUser.addPrivilege(privilege.c_str());
472 Api::install(requestPrivateUser);
474 check_app_permissions(sm_app_id, sm_pkg_id, user.c_str(), SM_ALLOWED_PRIVILEGES, SM_DENIED_PRIVILEGES);
477 RUNNER_CHILD_TEST(security_manager_04a_app_install_uninstall_by_app_user_for_self)
480 const char *const sm_app_id = "sm_test_04a_app_id_uid";
481 const char *const sm_pkg_id = "sm_test_04a_pkg_id_uid";
483 struct passwd *pw = get_app_pw();
484 const std::string user = std::to_string(static_cast<unsigned int>(pw->pw_uid));
486 //switch user to non-root
487 result = drop_root_privileges(pw->pw_uid, pw->pw_gid);
488 RUNNER_ASSERT_MSG(result == 0, "drop_root_privileges failed");
490 install_and_check(sm_app_id, sm_pkg_id, user, 0);
492 //uninstall app as non-root user
493 InstallRequest request;
494 request.setAppId(sm_app_id);
496 Api::uninstall(request);
498 check_app_permissions(sm_app_id, sm_pkg_id, user.c_str(), SM_NO_PRIVILEGES, SM_ALLOWED_PRIVILEGES);
501 RUNNER_CHILD_TEST(security_manager_04b_app_install_by_root_for_app_user)
504 const char *const sm_app_id = "sm_test_04b_app_id_uid";
505 const char *const sm_pkg_id = "sm_test_04b_pkg_id_uid";
507 struct passwd *pw = get_app_pw();
508 const std::string user = std::to_string(static_cast<unsigned int>(pw->pw_uid));
510 install_and_check(sm_app_id, sm_pkg_id, user, pw->pw_uid);
512 //switch user to non-root - root may not uninstall apps for specified users
513 result = drop_root_privileges(pw->pw_uid, pw->pw_gid);
514 RUNNER_ASSERT_MSG(result == 0, "drop_root_privileges failed");
516 //uninstall app as non-root user
517 InstallRequest request;
518 request.setAppId(sm_app_id);
520 Api::uninstall(request);
522 check_app_permissions(sm_app_id, sm_pkg_id, user.c_str(), SM_NO_PRIVILEGES, SM_ALLOWED_PRIVILEGES);
526 RUNNER_CHILD_TEST(security_manager_05_drop_process_capabilities)
529 CapsSetsUniquePtr caps, caps_empty(cap_init());
531 caps.reset(cap_from_text("all=eip"));
532 RUNNER_ASSERT_MSG(caps, "can't convert capabilities from text");
533 result = cap_set_proc(caps.get());
534 RUNNER_ASSERT_MSG(result == 0,
535 "can't set capabilities. Result: " << result);
537 Api::dropProcessPrivileges();
539 caps.reset(cap_get_proc());
540 RUNNER_ASSERT_MSG(caps, "can't get proc capabilities");
542 result = cap_compare(caps.get(), caps_empty.get());
543 RUNNER_ASSERT_MSG(result == 0,
544 "capabilities not dropped. Current: " << cap_to_text(caps.get(), NULL));
547 RUNNER_CHILD_TEST(security_manager_06_install_app_offline)
549 const char *const app_id = "sm_test_06_app_id_install_app_offline";
550 const char *const pkg_id = "sm_test_06_pkg_id_install_app_offline";
551 DBusAccess dbusAccess("security-manager.service");
553 uninstall_app(app_id, pkg_id, true);
554 dbusAccess.maskService();
555 dbusAccess.stopService();
557 install_app(app_id, pkg_id);
559 dbusAccess.unmaskService();
560 dbusAccess.startService();
562 uninstall_app(app_id, pkg_id, true);
565 int main(int argc, char *argv[])
567 return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);