std::vector<std::string> accessesBasic = { "r", "w", "x", "wx", "rx", "rw", "rwx", "rwxat" };
+typedef std::unique_ptr<smack_accesses, std::function<void(smack_accesses*)> > AccessesUniquePtr;
+
waitpid(pid, NULL, 0);
}
}
+
+/////////////////////////////////////////
+//////NOSMACK ENVIRONMENT TESTS//////////
+/////////////////////////////////////////
+
+/**
+ * NOSMACK version of smack02 test. Functions, that should return error instead of success:
+ * - smack_accesses_apply
+ * - smack_have_access
+ * - smack_revoke_subject
+ * - smack_acceesses_clear
+ *
+ * Tests smack03, smack04, smack10, smack_accesses_clear, smack_revoke_subject all use functions
+ * tested in smack02 test. Results from those functions (smack_have_access, smack_accesses_apply,
+ * smack_accesses_clear, smack_revoke_subject) would be the same as in this test. Tests mentioned
+ * above doesn't make much sense on NOSMACK environment when test smack02 exists and passes
+ * correctly, thus those tests are are not implemented.
+ */
+RUNNER_TEST_NOSMACK(smack02_aplying_rules_into_kernel_nosmack)
+{
+
+ smack_accesses *tmp = NULL;
+ int result;
+
+ //init rules
+ result = smack_accesses_new(&tmp);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to create smack_accesses instance");
+
+ //pass rules to unique_ptr
+ AccessesUniquePtr rules(tmp, smack_accesses_free);
+
+ //adding test rules to struct (same as SMACK version of smack02 test)
+ result = smack_accesses_add(rules.get(), "writer", "book", "rwx");
+ RUNNER_ASSERT_MSG(result == 0, "Unable to add smack rules");
+ result = smack_accesses_add(rules.get(), "reader", "book", "r");
+ RUNNER_ASSERT_MSG(result == 0, "Unable to add smack rules");
+ result = smack_accesses_add(rules.get(), "spy", "book", "rwx");
+ RUNNER_ASSERT_MSG(result == 0, "Unable to add smack rules");
+
+ //applying rules to kernel (should fail)
+ result = smack_accesses_apply(rules.get());
+ RUNNER_ASSERT_MSG(result == -1, "Unable to apply rules into kernel");
+
+ //calls from SMACK version of this test - all should fail because of SMACK being turned off
+ result = smack_have_access("spy", "book", "rwx");
+ RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off)");
+ result = smack_have_access("reader", "book", "rwx");
+ RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off)");
+ result = smack_have_access("mars", "book", "rwx");
+ RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off)");
+
+ //testing subject revoking - should return error (no accesses applied = no subjects to revoke)
+ result = smack_revoke_subject("snickers");
+ RUNNER_ASSERT_MSG(result == -1, "smack_revoke_subject error - subject doesn't exist.");
+ result = smack_revoke_subject("spy");
+ RUNNER_ASSERT_MSG(result == -1, "smack_revoke_subject error - subject doesn't exist.");
+
+ //after revoking smack_have_access still should return error
+ result = smack_have_access("spy", "book", "rwx");
+ RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off).");
+
+ result = smack_accesses_add(rules.get(), "twix", "book", "rwx");
+ RUNNER_ASSERT_MSG(result == 0, "Unable to add smack rules");
+
+ //smack_accesses_clear should return error aswell
+ result = smack_accesses_clear(rules.get());
+ RUNNER_ASSERT_MSG(result == -1, "Clearing rules should return error - no SMACK on system.");
+
+ result = smack_have_access("writer", "book", "rwx");
+ RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off).");
+}
+
+/**
+ * NOSMACK version of smack11 test. Tests functions:
+ * - smack_accesses_add_from_file
+ *
+ * Since other SMACK functions were tested in smack02 test, the only function needed to be checked
+ * is applying rules loaded from file.
+ */
+RUNNER_TEST_NOSMACK(smack03_saving_loading_rules_nosmack)
+{
+ int result;
+ int fd;
+
+ smack_accesses* tmp = NULL;
+
+ result = smack_accesses_new(&tmp);
+ RUNNER_ASSERT_MSG(result == 0, "Error during rules creation.");
+
+ AccessesUniquePtr rules(tmp, smack_accesses_free);
+
+ //open file with rules
+ fd = open("/etc/smack/test_smack_rules_full", O_RDONLY, 0644);
+ RUNNER_ASSERT_MSG(fd >= 0,
+ "Unable to open /etc/smack/test_smack_rules_full. Errno: " << strerror(errno));
+
+ //load accesses from file
+ result = smack_accesses_add_from_file(rules.get(), fd);
+ close(fd);
+ RUNNER_ASSERT_MSG(result == 0, "Error while importing accesses from file. Result: " << result);
+}
+
+/**
+ * NOSMACK version of smack05 test. Tests if functions getting, or
+ * setting self label work correctly (that is, return error).
+ */
+RUNNER_TEST_NOSMACK(smack04_self_label_nosmack)
+{
+ char* label = NULL;
+ int result;
+ int fd;
+
+ const int B_SIZE = 8;
+ char buff[B_SIZE];
+
+ //smack_new_label_from_self should fail
+ result = smack_new_label_from_self(&label);
+ RUNNER_ASSERT_MSG(result == -1, "new_label_from_self should return error (SMACK is off).");
+ RUNNER_ASSERT_MSG(label == NULL, "new_label_from_self shouldn't allocate memory to label.");
+
+ //We don't need to remember about freeing label - smack_new_label_from_self must return NULL
+ //label if it's working properly.
+
+ // /proc/self/attr/current shouldn't keep any rules inside
+ fd = open("/proc/self/attr/current", O_RDONLY, 0644); //file exists, so it should open
+ RUNNER_ASSERT_MSG(fd >= 0, "/proc/self/attr/current failed to open.");
+
+ result = read(fd, buff, B_SIZE); //however reading it should return error
+ if(result >= 0) {
+ close(fd);
+ RUNNER_ASSERT_MSG(false, "Reading /proc/self/attr/current should return error.");
+ }
+
+ //setting label for self should fail
+ result = smack_set_label_for_self("fanta");
+ if(result != -1) {
+ close(fd);
+ RUNNER_ASSERT_MSG(false, "set_label_for_self should return error (SMACK is off).");
+ }
+
+ //getting previously set label should also fail
+ result = smack_new_label_from_self(&label);
+ if(result != -1) {
+ close(fd);
+ RUNNER_ASSERT_MSG(false, "new_label_from_self should return error (SMACK is off).");
+ }
+ if(label != NULL) {
+ close(fd);
+ RUNNER_ASSERT_MSG(false, "new_label_from_self shouldn't allocate memory to label.");
+ }
+
+ // /proc/self/attr/current still shouldn't keep any rules inside
+ result = lseek(fd, 0, SEEK_SET); //going to the file beginning
+ if(result != 0) {
+ close(fd);
+ RUNNER_ASSERT_MSG(false, "lseek() error.");
+ }
+
+ result = read(fd, buff, B_SIZE); //however it should return error
+ if(result >= 0) {
+ close(fd);
+ RUNNER_ASSERT_MSG(false, "Reading /proc/self/attr/current should return error.");
+ }
+
+ close(fd);
+}
+
+/**
+ * NOSMACK version of smack_accesses_add_modify_x tests.
+ *
+ * Because all smack_accesses_add_modify tests are basically the same (all use smack_accesses_apply
+ * and smack_have_access, which return -1 when SMACK is turned off), it makes much more sense to
+ * write one test which will create rules using smack_accesses_add_modify and then check if
+ * smack_accesses_apply and smack_have_access indeed return -1 when SMACK is turned off.
+ */
+RUNNER_TEST_NOSMACK(smack05_accesses_add_modify_nosmack)
+{
+ int result;
+ smack_accesses* tmp = NULL;
+
+ result = smack_accesses_new(&tmp);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to allocate memory for rules. Result: " << result);
+
+ AccessesUniquePtr rules(tmp, smack_accesses_free);
+
+ //Not doing clean_up() every RUNNER_ASSERT_MSG - what clean_up does is just a creation of new
+ //rule struct and removal of currenctly added and applied rules. clean_up() must be done only
+ //after smack_accesses_apply().
+ result = smack_accesses_add_modify(rules.get(), TEST_SUBJECT, TEST_OBJECT, "rwx", "");
+ RUNNER_ASSERT_MSG(result == 0, "Unable to modify rule. Result: " << result);
+
+ result = smack_accesses_add_modify(rules.get(), TEST_SUBJECT, TEST_OBJECT, "rwx", "");
+ RUNNER_ASSERT_MSG(result == 0, "Unable to modify rule. Result: " << result);
+
+ result = smack_accesses_apply(rules.get());
+ RUNNER_ASSERT_MSG(result == -1,
+ "smack_accesses_apply should return error (SMACK is off). Result: " << result);
+
+ result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, "rwx");
+ if(result != -1) {
+ clean_up();
+ RUNNER_ASSERT_MSG(false,
+ "smack_have_access should return error (SMACK is off). Result: " << result);
+ }
+
+ clean_up();
+}
+
+/**
+ * NOSMACK version of smack09 test.
+ *
+ * This test checks if smack_new_label_from_socket reacts correctly. Since label should be
+ * acquired from getsockopt, and it should fail, we must only set up socket and call
+ * smack_new_label_from_socket. It should return error.
+ */
+RUNNER_TEST_NOSMACK(smack09_new_label_from_socket_nosmack)
+{
+ int pid;
+ struct sockaddr_un sockaddr = {AF_UNIX, SOCK_PATH};
+ unlink(SOCK_PATH);
+ char* smack_label;
+
+ pid = fork();
+ RUNNER_ASSERT_MSG(pid >= 0, "Fork failed");
+ if (!pid) { //child (server)
+ int sock, result;
+ int fd;
+
+ //Create new socket
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ RUNNER_ASSERT_MSG(sock >= 0, "socket failed: " << strerror(errno));
+
+ //Bind it to sockaddr
+ result = bind(sock, (struct sockaddr*) &sockaddr, sizeof(struct sockaddr_un));
+ if (result != 0) {
+ close(sock);
+ RUNNER_ASSERT_MSG(false, "bind failed: " << strerror(errno));
+ }
+
+ //Prepare for listening
+ result = listen(sock, 1);
+ if (result != 0) {
+ close(sock);
+ RUNNER_ASSERT_MSG(false, "listen failed: " << strerror(errno));
+ }
+
+ //Accept client
+ alarm(2);
+ fd = accept(sock, NULL, NULL);
+ alarm(0);
+ if (fd < 0) {
+ close(sock);
+ RUNNER_ASSERT_MSG(false, "Failed when accepting connection from client.");
+ }
+
+ //wait for smack_new_label_from_socket execution
+ usleep(200);
+
+ //Close socket and server
+ close(sock);
+ exit(0);
+ }
+ else { //parent (client)
+ //Wait a little bit until server is set up
+ sleep(1);
+ int sock, result;
+
+ //Create socket
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ RUNNER_ASSERT_MSG(sock >= 0, "socket failed: " << strerror(errno));
+
+ //Connect to sockaddr
+ result = connect(sock, (struct sockaddr*) &sockaddr,
+ sizeof(struct sockaddr_un));
+ if (result != 0) {
+ close(sock);
+ RUNNER_ASSERT_MSG(false, "connect failed: " << strerror(errno));
+ }
+
+ //Try getting label, should fail beacuse getsockopt won't get anything
+ result = smack_new_label_from_socket(sock, &smack_label);
+ if (result != -1) {
+ close(sock);
+ RUNNER_ASSERT_MSG(false, "smack_new_label_from_socket should fail.");
+ }
+
+ //Close socket, wait for server shutdown
+ close(sock);
+ waitpid(pid, NULL, 0);
+ }
+}