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_01a_app_double_install_double_uninstall)
281 const char *const sm_app_id = "sm_test_01a_app_id_double";
282 const char *const sm_pkg_id = "sm_test_01a_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);
305 RUNNER_TEST(security_manager_01b_app_double_install_wrong_pkg_id)
307 const char *const sm_app_id = "sm_test_01b_app";
308 const char *const sm_pkg_id = "sm_test_01b_pkg";
309 const char *const sm_pkg_id_wrong = "sm_test_01b_pkg_BAD";
311 InstallRequest requestInst;
312 requestInst.setAppId(sm_app_id);
313 requestInst.setPkgId(sm_pkg_id);
315 Api::install(requestInst);
317 InstallRequest requestInst2;
318 requestInst2.setAppId(sm_app_id);
319 requestInst2.setPkgId(sm_pkg_id_wrong);
321 Api::install(requestInst2, SECURITY_MANAGER_ERROR_INPUT_PARAM);
324 /* Check records in the security-manager database */
325 check_app_after_install(sm_app_id, sm_pkg_id);
327 InstallRequest requestUninst;
328 requestUninst.setAppId(sm_app_id);
330 Api::uninstall(requestUninst);
333 /* Check records in the security-manager database */
334 check_app_after_uninstall(sm_app_id, sm_pkg_id, TestSecurityManagerDatabase::REMOVED);
338 RUNNER_TEST(security_manager_01c_app_uninstall_pkg_id_ignored)
340 const char * const sm_app_id = "SM_TEST_01c_APPID";
341 const char * const sm_pkg_id = "SM_TEST_01c_PKGID";
342 const char * const sm_pkg_id_wrong = "SM_TEST_01c_PKGID_wrong";
344 InstallRequest requestInst;
345 requestInst.setAppId(sm_app_id);
346 requestInst.setPkgId(sm_pkg_id);
348 Api::install(requestInst);
350 /* Check records in the security-manager database */
351 check_app_after_install(sm_app_id, sm_pkg_id);
353 InstallRequest requestUninst;
354 requestUninst.setAppId(sm_app_id);
355 requestUninst.setPkgId(sm_pkg_id_wrong);
357 Api::uninstall(requestUninst);
359 check_app_after_uninstall(sm_app_id, sm_pkg_id, TestSecurityManagerDatabase::REMOVED);
363 RUNNER_TEST(security_manager_02_app_install_uninstall_full)
365 const char *const sm_app_id = "sm_test_02_app_id_full";
366 const char *const sm_pkg_id = "sm_test_02_pkg_id_full";
370 InstallRequest requestInst;
371 requestInst.setAppId(sm_app_id);
372 requestInst.setPkgId(sm_pkg_id);
373 requestInst.addPrivilege(SM_ALLOWED_PRIVILEGES[0].c_str());
374 requestInst.addPrivilege(SM_ALLOWED_PRIVILEGES[1].c_str());
375 requestInst.addPath(SM_PRIVATE_PATH, SECURITY_MANAGER_PATH_PRIVATE);
376 requestInst.addPath(SM_PUBLIC_RO_PATH, SECURITY_MANAGER_PATH_PUBLIC_RO);
378 Api::install(requestInst);
380 /* Check records in the security-manager database */
381 check_app_after_install(sm_app_id, sm_pkg_id,
382 SM_ALLOWED_PRIVILEGES, SM_DENIED_PRIVILEGES, SM_ALLOWED_GROUPS);
384 /* TODO: add parameters to this function */
385 check_app_path_after_install();
387 InstallRequest requestUninst;
388 requestUninst.setAppId(sm_app_id);
390 Api::uninstall(requestUninst);
392 /* Check records in the security-manager database,
393 * all previously allowed privileges should be removed */
394 check_app_after_uninstall(sm_app_id, sm_pkg_id,
395 SM_ALLOWED_PRIVILEGES, TestSecurityManagerDatabase::REMOVED);
398 RUNNER_CHILD_TEST_SMACK(security_manager_03_set_label_from_appid)
400 const char *const app_id = "sm_test_03_app_id_set_label_from_appid_smack";
401 const char *const pkg_id = "sm_test_03_pkg_id_set_label_from_appid_smack";
402 const char *const expected_label = USER_APP_ID;
403 const char *const socketLabel = "not_expected_label";
404 char *label = nullptr;
408 uninstall_app(app_id, pkg_id, true);
409 install_app(app_id, pkg_id);
411 struct sockaddr_un sockaddr = {AF_UNIX, SOCK_PATH};
412 //Clean up before creating socket
414 int sock = socket(AF_UNIX, SOCK_STREAM, 0);
415 RUNNER_ASSERT_ERRNO_MSG(sock >= 0, "socket failed");
416 SockUniquePtr sockPtr(&sock);
417 //Bind socket to address
418 result = bind(sock, (struct sockaddr*) &sockaddr, sizeof(struct sockaddr_un));
419 RUNNER_ASSERT_ERRNO_MSG(result == 0, "bind failed");
420 //Set socket label to something different than expecedLabel
421 result = fsetxattr(sock, XATTR_NAME_SMACKIPIN, socketLabel,
422 strlen(socketLabel), 0);
423 RUNNER_ASSERT_ERRNO_MSG(result == 0,
424 "Can't set socket label. Result: " << result);
425 result = fsetxattr(sock, XATTR_NAME_SMACKIPOUT, socketLabel,
426 strlen(socketLabel), 0);
427 RUNNER_ASSERT_ERRNO_MSG(result == 0,
428 "Can't set socket label. Result: " << result);
430 Api::setProcessLabel(app_id);
432 char value[SMACK_LABEL_LEN + 1];
434 size = fgetxattr(sock, XATTR_NAME_SMACKIPIN, value, sizeof(value));
435 RUNNER_ASSERT_ERRNO_MSG(size != -1, "fgetxattr failed: " << value);
436 result = strcmp(expected_label, value);
437 RUNNER_ASSERT_MSG(result == 0, "Socket label is incorrect. Expected: " <<
438 expected_label << " Actual: " << value);
440 size = fgetxattr(sock, XATTR_NAME_SMACKIPOUT, value, sizeof(value));
441 RUNNER_ASSERT_ERRNO_MSG(size != -1, "fgetxattr failed: " << value);
442 result = strcmp(expected_label, value);
443 RUNNER_ASSERT_MSG(result == 0, "Socket label is incorrect. Expected: " <<
444 expected_label << " Actual: " << value);
446 result = smack_new_label_from_self(&label);
447 RUNNER_ASSERT_MSG(result >= 0,
448 " Error getting current process label");
449 RUNNER_ASSERT_MSG(label != nullptr,
450 " Process label is not set");
451 labelPtr.reset(label);
453 result = strcmp(expected_label, label);
454 RUNNER_ASSERT_MSG(result == 0,
455 " Process label is incorrect. Expected: \"" << expected_label <<
456 "\" Actual: \"" << label << "\"");
458 uninstall_app(app_id, pkg_id, true);
461 RUNNER_CHILD_TEST_NOSMACK(security_manager_03_set_label_from_appid_nosmack)
463 const char *const app_id = "sm_test_03_app_id_set_label_from_appid_nosmack";
464 const char *const pkg_id = "sm_test_03_pkg_id_set_label_from_appid_nosmack";
466 uninstall_app(app_id, pkg_id, true);
467 install_app(app_id, pkg_id);
469 Api::setProcessLabel(app_id);
471 uninstall_app(app_id, pkg_id, true);
476 static void prepare_request(InstallRequest &request,
477 const char *const app_id,
478 const char *const pkg_id,
479 app_install_path_type pathType,
480 const char *const path,
483 request.setAppId(app_id);
484 request.setPkgId(pkg_id);
485 request.addPath(path, pathType);
492 static struct passwd* get_app_pw()
494 struct passwd *pw = nullptr;
496 while(!(pw = getpwnam(APP_USER))) {
497 RUNNER_ASSERT_ERRNO_MSG(errno == EINTR, "getpwnam() failed");
503 static void install_and_check(const char *const sm_app_id,
504 const char *const sm_pkg_id,
505 const std::string &user, uid_t uid)
507 InstallRequest requestPublic;
509 //install app for non-root user and try to register public path (should fail)
510 prepare_request(requestPublic, sm_app_id, sm_pkg_id, SECURITY_MANAGER_PATH_PUBLIC, SM_PRIVATE_PATH_FOR_USER, uid);
512 Api::install(requestPublic, SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED);
514 InstallRequest requestPrivate;
516 //install app for non-root user
517 //should fail (users may only register folders inside their home)
518 prepare_request(requestPrivate, sm_app_id, sm_pkg_id, SECURITY_MANAGER_PATH_PRIVATE, SM_PRIVATE_PATH, uid);
520 Api::install(requestPrivate, SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED);
522 InstallRequest requestPrivateUser;
524 //install app for non-root user
525 //should succeed - this time i register folder inside user's home dir
526 prepare_request(requestPrivateUser, sm_app_id, sm_pkg_id, SECURITY_MANAGER_PATH_PRIVATE, SM_PRIVATE_PATH_FOR_USER, uid);
528 for (auto &privilege : SM_ALLOWED_PRIVILEGES)
529 requestPrivateUser.addPrivilege(privilege.c_str());
531 Api::install(requestPrivateUser);
533 check_app_permissions(sm_app_id, sm_pkg_id, user.c_str(), SM_ALLOWED_PRIVILEGES, SM_DENIED_PRIVILEGES);
536 RUNNER_CHILD_TEST(security_manager_04a_app_install_uninstall_by_app_user_for_self)
539 const char *const sm_app_id = "sm_test_04a_app_id_uid";
540 const char *const sm_pkg_id = "sm_test_04a_pkg_id_uid";
542 struct passwd *pw = get_app_pw();
543 const std::string user = std::to_string(static_cast<unsigned int>(pw->pw_uid));
545 //switch user to non-root
546 result = drop_root_privileges(pw->pw_uid, pw->pw_gid);
547 RUNNER_ASSERT_MSG(result == 0, "drop_root_privileges failed");
549 install_and_check(sm_app_id, sm_pkg_id, user, 0);
551 //uninstall app as non-root user
552 InstallRequest request;
553 request.setAppId(sm_app_id);
555 Api::uninstall(request);
557 check_app_permissions(sm_app_id, sm_pkg_id, user.c_str(), SM_NO_PRIVILEGES, SM_ALLOWED_PRIVILEGES);
560 RUNNER_CHILD_TEST(security_manager_04b_app_install_by_root_for_app_user)
563 const char *const sm_app_id = "sm_test_04b_app_id_uid";
564 const char *const sm_pkg_id = "sm_test_04b_pkg_id_uid";
566 struct passwd *pw = get_app_pw();
567 const std::string user = std::to_string(static_cast<unsigned int>(pw->pw_uid));
569 install_and_check(sm_app_id, sm_pkg_id, user, pw->pw_uid);
571 //switch user to non-root - root may not uninstall apps for specified users
572 result = drop_root_privileges(pw->pw_uid, pw->pw_gid);
573 RUNNER_ASSERT_MSG(result == 0, "drop_root_privileges failed");
575 //uninstall app as non-root user
576 InstallRequest request;
577 request.setAppId(sm_app_id);
579 Api::uninstall(request);
581 check_app_permissions(sm_app_id, sm_pkg_id, user.c_str(), SM_NO_PRIVILEGES, SM_ALLOWED_PRIVILEGES);
585 RUNNER_CHILD_TEST(security_manager_05_drop_process_capabilities)
588 CapsSetsUniquePtr caps, caps_empty(cap_init());
590 caps.reset(cap_from_text("all=eip"));
591 RUNNER_ASSERT_MSG(caps, "can't convert capabilities from text");
592 result = cap_set_proc(caps.get());
593 RUNNER_ASSERT_MSG(result == 0,
594 "can't set capabilities. Result: " << result);
596 Api::dropProcessPrivileges();
598 caps.reset(cap_get_proc());
599 RUNNER_ASSERT_MSG(caps, "can't get proc capabilities");
601 result = cap_compare(caps.get(), caps_empty.get());
602 RUNNER_ASSERT_MSG(result == 0,
603 "capabilities not dropped. Current: " << cap_to_text(caps.get(), NULL));
606 RUNNER_CHILD_TEST(security_manager_06_install_app_offline)
608 const char *const app_id = "sm_test_06_app_id_install_app_offline";
609 const char *const pkg_id = "sm_test_06_pkg_id_install_app_offline";
610 DBusAccess dbusAccess("security-manager.service");
612 uninstall_app(app_id, pkg_id, true);
613 dbusAccess.maskService();
614 dbusAccess.stopService();
616 install_app(app_id, pkg_id);
618 dbusAccess.unmaskService();
619 dbusAccess.startService();
621 uninstall_app(app_id, pkg_id, true);
624 int main(int argc, char *argv[])
626 return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);