Add security-server tests for NOSMACK environment.
authorLukasz Kostyra <l.kostyra@partner.samsung.com>
Tue, 13 Aug 2013 06:06:07 +0000 (08:06 +0200)
committerMarcin Niesluchowski <m.niesluchow@samsung.com>
Thu, 23 Jan 2014 14:07:38 +0000 (15:07 +0100)
[Issue#]        SSDWSSP-417
[Feature]       Add new security-server tests that test security-server behaviour on NOSMACK
                environment.
[Cause]         When previous tests were launched on NOSMACK environment they returned false errors
                because the system behaved differently with SMACK turned off.
[Solution]      Creating new tests that would expect different behaviour from security-server.
[Verification]  After successful compilation launch security-server tests on NOSMACK environment.
                Tests that previously failed and were turned off in one of my previous commits
                should appear with "_nosmack" ending in name.

Change-Id: I8c03ed8d97ff970f684466f6927a6e01f0c43d46

tests/security-server-tests/security_server_tests_client_smack.cpp
tests/security-server-tests/security_server_tests_dbus.cpp
tests/security-server-tests/security_server_tests_label.cpp
tests/security-server-tests/security_server_tests_server.cpp
tests/security-server-tests/security_server_tests_weird_arguments.cpp

index 940d1f7..b383ec0 100644 (file)
 #include <sys/smack.h>
 #include <sys/wait.h>
 #include <sys/un.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <memory>
+#include <functional>
 
 #include <dpl/log/log.h>
 #include <dpl/test/test_runner.h>
             "Cannot prepare environment for test");                       \
     } while (0)
 
+
+/**
+ * Environment preparation should only differ in setting label. On NOSMACK system
+ * smack_set_label_for_self returns error because of no access to /proc/self/attr/current.
+ */
+#define ENVIRONMENT_NOSMACK                                               \
+    do {                                                                  \
+        int fd = open("/opt/home/root/pid_cycle", O_CREAT|O_APPEND, 0444);\
+        RUNNER_ASSERT_MSG(fd >= 0,                                        \
+            "Couldn't create pid_cycle file. errno: " << strerror(errno));\
+        close(fd);                                                        \
+        RUNNER_ASSERT_MSG(-1 != setgid(1),                                \
+            "Cannot prepare environment for test.");                      \
+        RUNNER_ASSERT_MSG(-1 != setuid(1),                                \
+            "Cannot prepare environment for test");                       \
+    } while (0)
+
+/**
+ * Unique_ptr typedef for NOSMACK version of tc06 test
+ */
+void closesockfdptr(int* sockfd_ptr)
+{
+    close(*sockfd_ptr);
+}
+typedef std::unique_ptr<int, std::function<void(int*)> > SockFDUniquePtr;
+
 /**
  * Dropping root privileges
  * returns 0 on success, 1 on error
@@ -386,6 +418,266 @@ RUNNER_TEST_SMACK(tc07_check_privilege_by_sockfd)
     RUNNER_ASSERT_MSG(SECURITY_SERVER_API_ERROR_ACCESS_DENIED == result2, " result2 = " << result2);
 }
 
+///////////////////////////
+/////NOSMACK ENV TESTS/////
+///////////////////////////
+
+/**
+ * First four test cases are the same as their SMACK versions. The only difference is environment
+ * preparation (described near ENVIRONMENT_NOSMACK macro).
+ */
+RUNNER_CHILD_TEST_NOSMACK(tc01_security_server_get_cookie_size_nosmack)
+{
+    ENVIRONMENT_NOSMACK;
+
+    int ret = security_server_get_cookie_size();
+    RUNNER_ASSERT_MSG(ret == 20, "ret = " << ret);
+}
+
+RUNNER_CHILD_TEST_NOSMACK(tc02_security_server_request_cookie_normal_case_nosmack)
+{
+    ENVIRONMENT_NOSMACK;
+
+    char cookie[20];
+    int ret = security_server_request_cookie(cookie, 20);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS, "ret = " << ret);
+}
+
+RUNNER_CHILD_TEST_NOSMACK(tc03_security_server_request_cookie_too_small_buffer_size_nosmack)
+{
+    ENVIRONMENT_NOSMACK;
+
+    char cookie[20];
+    int ret = security_server_request_cookie(cookie, 10);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL, "ret = " << ret);
+}
+
+RUNNER_CHILD_TEST_NOSMACK(tc04_security_server_get_gid_nosmack)
+{
+    ENVIRONMENT_NOSMACK;
+
+    int ret = security_server_get_gid("definitely_not_existing_object");
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_SUCH_OBJECT, "ret = " << ret);
+    ret = security_server_get_gid("root");
+    RUNNER_ASSERT_MSG(ret == 0, "ret = " << ret);
+}
+
+/*
+ * NOSMACK version of tc05 test.
+ *
+ * Correct behaviour of smack_accesses_apply and smack_set_label_for_self was checked by libsmack
+ * tests. We assume, that those tests pass. Additionally security_server_check_privilege_by_cookie
+ * should return SUCCESS no matter what access_rights we give to this function.
+ */
+RUNNER_CHILD_TEST_NOSMACK(tc05_check_privilege_by_cookie_nosmack)
+{
+    char cookie[20];
+    const char* object_label = "tc05objectlabel";
+
+    RUNNER_ASSERT(security_server_request_cookie(cookie,20) == SECURITY_SERVER_API_SUCCESS);
+
+    RUNNER_ASSERT_MSG(drop_root_privileges() == 0, "uid = " << getuid());
+
+    RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS ==
+        security_server_check_privilege_by_cookie(cookie, object_label, "r"));
+
+    //On NOSMACK env security server should return success on any accesses, even those that are
+    //incorrect.
+    RUNNER_ASSERT(SECURITY_SERVER_API_SUCCESS ==
+        security_server_check_privilege_by_cookie(cookie, object_label, "rw"));
+}
+
+/**
+ * NOSMACK version of tc06 test.
+ *
+ * Differences between this and SMACK version (server):
+ * - Skipped setting access_rights
+ * - Skipped setting label for server
+ * - get_smacklabel_sockfd is called only once for server, almost right after fork and creation
+ *   of socket (because it should do nothing when SMACK is off)
+ * - After get_smacklabel_sockfd privileges are dropped and server is prepared to accept connections
+ *   from client
+ *
+ * For client the only difference are expected results from check_privilege_by_sockfd - both should
+ * return SUCCESS.
+ */
+RUNNER_TEST_NOSMACK(tc06_check_privilege_by_sockfd_nosmack)
+{
+    const char* object_label = "tc06objectlabel";
+
+    int result1 = -1;
+    int result2 = -1;
+
+    int pid = fork();
+    char* label;
+    RUNNER_ASSERT(pid >= 0);
+
+    if (pid == 0) { //child process - server
+        int ret;
+        //create new socket
+        int sockfd = create_new_socket();
+        if(sockfd < 0)
+            exit(1);        //failed to create server; return 1
+
+        SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
+
+        //check if get_smacklabel_sockfd works correctly
+        label = security_server_get_smacklabel_sockfd(sockfd);
+        if(label == NULL)
+            exit(2);        //label is NULL, get_smacklabel_sockfd failed; return 2
+
+        ret = strcmp(label, "");
+        free(label);
+        if(ret != 0)
+            exit(3);        //label is not an empty string; return 3
+
+        ret = drop_root_privileges();
+        if(ret != 0)
+            exit(4);        //failed to drop root privileges; return 4
+
+        if (listen(sockfd, 5) < 0)
+            exit(5);        //listen failed; return 5
+
+        struct sockaddr_un client_addr;
+        socklen_t client_len = sizeof(client_addr);
+
+        int csockfd;
+        if((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) <= 0)
+            exit(6);        //accept failed; return 6
+
+        //wait a little bit for parent to do it's job
+        usleep(200);
+
+        //if everything works, cleanup and return 0
+        close(csockfd);
+        exit(0);
+    } else {
+        //parent
+        int ret;
+        sleep(1);
+        int sockfd = connect_to_testserver();
+        RUNNER_ASSERT_MSG(sockfd >= 0, "Failed to connect to server.");
+
+        SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
+
+        label = security_server_get_smacklabel_sockfd(sockfd);
+        RUNNER_ASSERT_MSG(label != NULL, "get_smacklabel_sockfd failed.");
+
+        ret = strcmp(label, "");
+        free(label);
+        RUNNER_ASSERT_MSG(ret == 0, "label is \"" << label << "\", should be empty");
+
+        result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
+        result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
+
+        kill(pid, SIGKILL);
+    }
+
+    int status;
+    waitpid(pid, &status, 0);
+
+    //check how our child process returned
+    switch(WEXITSTATUS(status))
+    {
+    case 1: RUNNER_ASSERT_MSG(false, "Child failed to create server.");
+    case 2: RUNNER_ASSERT_MSG(false, "Child error - get_smacklabel_sockfd failed.");
+    case 3: RUNNER_ASSERT_MSG(false, "Child error - label is not an empty string.");
+    case 4: RUNNER_ASSERT_MSG(false, "Child failed to drop root privileges.");
+    case 5: RUNNER_ASSERT_MSG(false, "Child error - listen failed.");
+    case 6: RUNNER_ASSERT_MSG(false, "Child error - accept failed.");
+    default: ;
+    }
+
+    RUNNER_ASSERT_MSG(result1 == SECURITY_SERVER_API_SUCCESS, "result = " << result1);
+    RUNNER_ASSERT_MSG(result2 == SECURITY_SERVER_API_SUCCESS, "result = " << result2);
+}
+
+/**
+ * NOSMACK version of tc07 test.
+ */
+RUNNER_TEST_NOSMACK(tc07_check_privilege_by_sockfd_nosmack)
+{
+    const char* object_label = "tc07objectlabel";
+
+    int result1 = -1;
+    int result2 = -1;
+
+    int pid = fork();
+    RUNNER_ASSERT(-1 != pid);
+
+    if (pid == 0) { //child process
+        int ret;
+        //Create socket
+        int sockfd = create_new_socket();
+        if(sockfd < 0)
+            exit(1);        //failed to create server, return 1
+
+        SockFDUniquePtr sockfd_ptr(&sockfd, closesockfdptr);
+
+        //Drop privileges
+        ret = drop_root_privileges();
+        if(ret != 0)
+            exit(2);        //failed to drop root privileges; return 2
+
+        //Prepare for accepting
+        if (listen(sockfd, 5) < 0)
+            exit(3);        //listen failed; return 3
+
+        struct sockaddr_un client_addr;
+        socklen_t client_len = sizeof(client_addr);
+
+        //Accept connections
+        int csockfd;
+        if((csockfd = accept(sockfd,(struct sockaddr*)&client_addr, &client_len)) <= 0)
+            exit(4);        //accept failed; return 4
+
+        //wait a little bit for parent to do it's job
+        usleep(200);
+
+        //cleanup and kill child
+        close(csockfd);
+        exit(0);
+    } else {    //parent process
+        //Drop root privileges
+        int ret = drop_root_privileges();
+        RUNNER_ASSERT_MSG(ret == 0,
+                "Failed to drop root privileges. Result: " << ret << ", uid = " << getuid());
+
+        //Wait for server to set up
+        sleep(1);
+
+        //Connect and check privileges
+        int sockfd = connect_to_testserver();
+        RUNNER_ASSERT_MSG(sockfd >= 0, "Failed to create socket fd.");
+
+        result1 = security_server_check_privilege_by_sockfd(sockfd, object_label, "r");
+        result2 = security_server_check_privilege_by_sockfd(sockfd, object_label, "rw");
+
+        close(sockfd);
+        kill(pid, SIGKILL);
+    }
+
+    int status;
+    waitpid(pid, &status, 0);
+
+    switch(WEXITSTATUS(status))
+    {
+    case 1: RUNNER_ASSERT_MSG(false, "Child failed to create server.");
+    case 2: RUNNER_ASSERT_MSG(false, "Child failed to drop root privileges.");
+    case 3: RUNNER_ASSERT_MSG(false, "Child failed to listen to sockfd.");
+    case 4: RUNNER_ASSERT_MSG(false, "Child failed to accept connection from server.");
+    default: ;
+    }
+
+    //Both results (just like in the previous test case) should return success.
+    RUNNER_ASSERT_MSG(SECURITY_SERVER_API_SUCCESS == result1, "result1 = " << result1);
+    RUNNER_ASSERT_MSG(SECURITY_SERVER_API_SUCCESS == result2, "result2 = " << result2);
+}
+
+////////////////////
+/////MAIN///////////
+////////////////////
+
 int main(int argc, char *argv[])
 {
     return
index 7c13abb..9ff3b75 100644 (file)
@@ -209,6 +209,169 @@ RUNNER_TEST_SMACK(tc01_smack_context_from_DBus)
     }
 }
 
+///////////////////////////////////////
+//////NOSMACK ENV TESTS////////////////
+///////////////////////////////////////
+
+/**
+ * NOSMACK version of tc01 test.
+ *
+ * This is almost an exact copy of the original SMACK DBus test. As in previous security-server
+ * tests, parts where SMACK is used are skipped, because most important functions will return error.
+ */
+RUNNER_TEST_NOSMACK(tc01_smack_context_from_DBus_nosmack)
+{
+    int ret = -1;
+    const char* subject_parent = "subject_parent";
+
+    DBusMessage* msg = NULL;
+    DBusMessageIter args, iter, var, var_iter, var_value;
+    DBusConnection* conn = NULL;
+    DBusError err;
+    DBusPendingCall *pending = NULL;
+    const char *dbus_server_name = DBUS_SERVER_NAME;
+    char *smack_context = NULL;
+    int status;
+
+    pid_t pid = fork();
+    RUNNER_ASSERT_MSG(-1 != pid, "fork() failed");
+
+    if (pid == 0) {
+        // child
+
+        // initialize the errors
+        dbus_error_init(&err);
+
+        // connect to the system bus and check for errors; failure = exit with result 1
+        conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+        ret = dbus_error_is_set(&err);
+        if (1 == ret) {
+            dbus_error_free(&err);
+            exit(1);
+        }
+
+        // request our name on the bus; failure = exit with result 2
+        ret = dbus_bus_request_name(conn, DBUS_CALLER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
+        if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
+            dbus_error_free(&err);
+            exit(2);
+        }
+
+        // crate a new method call for checking SMACK context from DBus interface
+        msg = dbus_message_new_method_call(DBUS_SMACK_NAME,
+                                           DBUS_SMACK_OBJECT,
+                                           DBUS_SMACK_INTERFACE,
+                                           DBUS_SMACK_METHOD);
+
+        if(msg == NULL)
+            exit(3);    //dbus_message_new_method_call failed; return 3
+
+        // append arguments, we need SMACK context for our parent process "test.method.server"
+        dbus_message_iter_init_append(msg, &args);
+        ret = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &dbus_server_name);
+        if(ret != 1)
+            exit(4);       //out of memory; return 4
+
+        // wait for parent to connect to DBus
+        sleep(3);
+
+        // send message and get a handle for a reply
+        // -1 is default timeout
+        ret = dbus_connection_send_with_reply (conn, msg, &pending, -1);
+        if(ret != 1)
+            exit(4);           //out of memory; return 4
+        if(pending == NULL)
+            exit(5);    //pending call is null; return 5
+
+        dbus_connection_flush(conn);
+
+        // free message
+        dbus_message_unref(msg);
+
+        // block until reply
+        dbus_pending_call_block(pending);
+
+        // get the reply
+        msg = dbus_pending_call_steal_reply(pending);
+        if(msg == NULL)
+            exit(6);    //reply is null; return 6
+
+        // free message handle
+        dbus_pending_call_unref(pending);
+
+        ret = dbus_message_iter_init(msg, &iter);
+        if (ret == 0)
+            exit(7);      //DBus message has no arguments; return 7
+
+        dbus_message_iter_recurse(&iter, &var);
+        while (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_INVALID) {
+            dbus_message_iter_recurse(&var, &var_iter);
+            while(dbus_message_iter_get_arg_type(&var_iter) != DBUS_TYPE_INVALID) {
+                dbus_message_iter_recurse(&var_iter, &var_value);
+                switch(dbus_message_iter_get_arg_type(&var_value)) {
+                    case DBUS_TYPE_STRING:
+                        dbus_message_iter_get_basic(&var_value, &smack_context);
+                        break;
+                    default:
+                        ;
+                }
+                dbus_message_iter_next(&var_iter);
+            }
+            dbus_message_iter_next(&var);
+        }
+
+        // free reply and close connection
+        dbus_message_unref(msg);
+        dbus_connection_unref(conn);
+
+        ret = strcmp(smack_context, subject_parent);
+        if(ret != 0)
+            exit(8);       //context mismatch; return 8
+
+        exit(0);
+
+    } else {
+        // parent
+
+        // initialise the error
+        dbus_error_init(&err);
+
+        // connect to the bus and check for errors
+        conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+        ret = dbus_error_is_set(&err);
+        if (1 == ret) {
+            dbus_error_free(&err);
+            RUNNER_ASSERT_MSG(0 == ret, "dbus_bus_get() failed, ret: " << ret);
+        }
+
+        // request our name on the bus and check for errors
+        ret = dbus_bus_request_name(conn, DBUS_SERVER_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
+        if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
+            dbus_error_free(&err);
+            RUNNER_ASSERT_MSG(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret,
+                "dbus_bus_request_name() failed, ret: " << ret);
+        }
+
+        // close the connection
+        dbus_connection_unref(conn);
+    }
+
+    waitpid(pid, &status, 0);
+
+    switch(WEXITSTATUS(status))
+    {
+    case 1: RUNNER_ASSERT_MSG(false, "Child failed to connect to system bus.");
+    case 2: RUNNER_ASSERT_MSG(false, "Child failed to request name on the bus.");
+    case 3: RUNNER_ASSERT_MSG(false, "Child error - dbus_message_new_method_call() failed.");
+    case 4: RUNNER_ASSERT_MSG(false, "Child error - out of memory.");
+    case 5: RUNNER_ASSERT_MSG(false, "Child error - Pending call is NULL.");
+    case 6: RUNNER_ASSERT_MSG(false, "Child failed to get the reply from bus.");
+    case 7: RUNNER_ASSERT_MSG(false, "Child error - DBus message has no arguments.");
+    case 8: RUNNER_ASSERT_MSG(false, "Child error - context mismatch.");
+    default: ;
+    }
+}
+
 int main(int argc, char *argv[])
 {
     int status = DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
index 64a810e..df983f6 100644 (file)
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/smack.h>
+
+#include <memory>
+#include <functional>
+
 #include <security-server.h>
 #include <dpl/test/test_runner.h>
 #include <dlog.h>
@@ -105,6 +109,55 @@ RUNNER_TEST_SMACK(tc_security_server_get_smacklabel_cookie) {
     //is changed using security-server API function based on the same cookie
 }
 
+/**
+ * NOSMACK version of tc_security_server_get_smacklabel_cookie test.
+ *
+ * Most of this test goes exactly as the original one. The only difference are the labels:
+ * - We assume that libsmack tests passed and smack_new_label_from_self will return -1 and NULL
+ *   label - there is no need to re-check it.
+ * - Label acquired from security_server_get_smacklabel_cookie should be an empty string.
+ */
+RUNNER_TEST_NOSMACK(tc_security_server_get_smacklabel_cookie_nosmack) {
+    int res;
+
+    pid_t mypid;
+
+    char* label_ss = NULL;
+    char* cookie = NULL;
+
+    int COOKIESIZE = security_server_get_cookie_size();
+    RUNNER_ASSERT_MSG(20 == COOKIESIZE,
+            "Wrong cookie size from security-server. Size: " << COOKIESIZE);
+
+    cookie = (char*) calloc(COOKIESIZE, sizeof(char));
+    RUNNER_ASSERT_MSG(NULL != cookie, "Memory allocation error");
+
+    //wrap cookie in smart ptr for garbage collection
+    std::unique_ptr<char, std::function<void(char*)> > cookie_ptr(cookie, free);
+
+    mypid = getpid();
+
+    //Request cookie from SS
+    res = security_server_request_cookie(cookie, COOKIESIZE);
+    RUNNER_ASSERT_MSG(res == SECURITY_SERVER_API_SUCCESS,
+            "Error in requesting cookie from security-server. Result: " << res);
+
+    printhex((unsigned char*) cookie, COOKIESIZE);
+
+    //Get label; since we only use label_ss to check if it indeed is an empty string there is no
+    //need to wrap it into unique_ptr (we have only one assert before the end of the test)
+    label_ss = security_server_get_smacklabel_cookie(cookie);
+    RUNNER_ASSERT_MSG(label_ss != NULL, "Error in getting label by cookie");
+
+    //Check if label_ss is correct, that is only one NULL character.
+    if (label_ss[0] != '\0') {
+        free(label_ss);
+        RUNNER_ASSERT_MSG(false, "label_ss was not an empty string.");
+    }
+
+    free(label_ss);
+}
+
 int main(int argc, char *argv[])
 {
     int status =
index 030fae6..4ef5f87 100644 (file)
@@ -841,6 +841,231 @@ RUNNER_CHILD_TEST(tc10_check_API_app_disable_permissions)
     RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS, "ret: " << ret);
 }
 
+//////////////////////////////////////////
+/////////NOSMACK ENV TESTS////////////////
+//////////////////////////////////////////
+
+/**
+ * NOSMACK version of tc01a and tc01c tests.
+ *
+ * SMACK is turned off - that means for us, that we don't need any accesses added to our process
+ * in SMACK before dropping root privileges. This test drops root privileges, calls
+ * security_server_app_give_access and then checks if smack_have_access returns error (because
+ * SMACK is off).
+ *
+ * security_server_app_give_access shouldn't return anything else than success when SMACK is off,
+ * hence there is only one test that replaces tests tc01a and tc01c.
+ */
+RUNNER_CHILD_TEST_NOSMACK(tc01_security_server_app_give_access_nosmack)
+{
+    const char* subject = "abc345v34sfa";
+    const char* object = "efg678x2lkjz";
+    int result = 0;
+
+    result = drop_root_privileges();
+    RUNNER_ASSERT_MSG(result == 0,
+            "Failed to drop root privileges. Result: " << result << "uid = " << getuid());
+
+    result = security_server_app_give_access(subject, getpid());
+    RUNNER_ASSERT_MSG(result == SECURITY_SERVER_API_SUCCESS,
+            "Error in security_server_app_give_access. Result: " << result);
+
+    result = smack_have_access(subject, object, "rwxat");
+    RUNNER_ASSERT_MSG(result == -1,
+            "smack_have_access should return error when SMACK is off. Result: " << result);
+}
+
+/**
+ * NOSMACK version of tc02 test.
+ *
+ * check_privilege_by_pid should always return success when SMACK is off, no matter if label is
+ * real or not.
+ */
+RUNNER_TEST_NOSMACK(tc02_check_privilege_by_pid_nosmack)
+{
+    int ret;
+    int pid;
+
+    pid = getpid();
+
+    //we checking existing rule, it should return positive
+    ret = security_server_check_privilege_by_pid(pid, "_", "rx");
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "check_privilege_by_pid for existing label failed. Result: " << ret);
+
+    //we checking rule with label that not exist
+    ret = security_server_check_privilege_by_pid(pid, "thislabelisnotreal", "rwxat");
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "check_privilege_by_pid for nonexisting label failed. Result: " << ret);
+}
+
+/**
+ * NOSMACK version of clear_password function.
+ *
+ * Compared to SMACK version of this function, this one skips adding rules and setting label.
+ */
+int clear_password_nosmack()
+{
+    int ret = -1;
+    unsigned int attempt, max_attempt, expire_sec;
+    const char* path = "/opt/data/security-server/";
+
+    attempt = max_attempt = expire_sec = 0;
+
+    if (getuid() == 0) {
+        if (access(path, F_OK) == 0) {
+            if (nftw(path, &nftw_rmdir_contents, 20, FTW_DEPTH) == -1) {
+                return 1;
+            }
+            sync();
+        }
+
+        ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
+
+        RUNNER_ASSERT_MSG(expire_sec == 0, "expire_sec = " << expire_sec << ", should be 0.");
+        RUNNER_ASSERT_MSG(max_attempt == 0, "max_attempt = " << max_attempt << ", should be 0.");
+        RUNNER_ASSERT_MSG(attempt == 0, "attempt = " << attempt << ", should be 0.");
+        RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD,
+                "is_pwd_faild should return no password error. Result: " << ret);
+
+        sleep(1);
+
+        return 0;
+    }
+    return -1;
+}
+
+/**
+ * NOSMACK version of tc03 test.
+ *
+ * Just as tc01a/tc01c NOSMACK replacement, we don't need to do anything with SMACK because most
+ * important functions will return errors (that is smack_accesses_apply/smack_have_access etc.).
+ * First clear password, then drop privileges and proceed to regular testing.
+ */
+
+RUNNER_CHILD_TEST_NOSMACK(tc03_check_API_passwd_allow_nosmack)
+{
+    int ret = -1;
+    unsigned int attempt, max_attempt, expire_sec;
+
+    attempt = max_attempt = expire_sec = 0;
+
+    clear_password_nosmack();
+
+    // drop root privileges
+    ret = drop_root_privileges();
+    RUNNER_ASSERT_MSG(ret == 0,
+            "Failed to drop root privileges. Result: " << ret << "uid = " << getuid());
+
+    ret = security_server_set_pwd_validity(10);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD,
+            "set_pwd_validity should return no password error. Result: " << ret);
+
+    ret = security_server_set_pwd_max_challenge(5);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD,
+            "set_pwd_max_challenge should return no password error. Result: " << ret);
+
+    ret = security_server_is_pwd_valid(&attempt, &max_attempt, &expire_sec);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_ERROR_NO_PASSWORD,
+            "is_pwd_valid should return no password error. Result: " << ret);
+
+    sleep(1);
+    ret = security_server_set_pwd(NULL, "12345", 0, 0);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "set_pwd failed. Result: " << ret);
+
+    sleep(1);
+    ret = security_server_reset_pwd("12345",0, 0);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "reset_pwd failed. Result: " << ret);
+
+    sleep(1);
+    ret = security_server_chk_pwd("12345", &attempt, &max_attempt, &expire_sec);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "chk_pwd failed. Result: " << ret);
+
+    sleep(1);
+    ret = security_server_set_pwd_history(10);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "set_pwd_history failed. Result: " << ret);
+}
+
+/**
+ * NOSMACK version of tc05 test.
+ *
+ * This test assumes similar information as previous NOSMACK tests. SMACK off = no need to
+ * set accesses and apply them in SMACK before dropping privileges.
+ */
+
+RUNNER_CHILD_TEST_NOSMACK(tc05_check_API_middleware_allow_nosmack)
+{
+    int ret = -1;
+    size_t cookie_size = security_server_get_cookie_size();
+    gid_t gid = 5000;
+    char cookie[20];
+    char* ss_label = NULL;
+    char object[SECURITY_SERVER_MAX_OBJ_NAME];
+
+    // drop root privileges
+    ret = drop_root_privileges();
+    RUNNER_ASSERT_MSG(ret == 0,
+            "Failed to drop root privileges. Result: " << ret << "uid = " << getuid());
+
+    ret = security_server_request_cookie(cookie, cookie_size);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "request_cookie failed. Result: " << ret);
+
+    ret = security_server_get_gid("audio");
+    RUNNER_ASSERT_MSG(ret > -1, "Failed to get \"audio\" gid. Result: " << ret);
+
+    ret = security_server_check_privilege(cookie, ret);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "check_privilege failed. Result: " << ret);
+
+    ret = security_server_get_object_name(gid, object, sizeof(object));
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "get_object_name failed. Result: " << ret);
+
+    ret = security_server_get_gid("root");
+    RUNNER_ASSERT_MSG(ret > -1,
+            "Failed to get \"root\" gid. Result: " << ret);
+
+    ret = security_server_get_cookie_pid(cookie);
+    RUNNER_ASSERT_MSG(ret == getpid(),
+            "get_cookie_pid returned different pid than it should. Result: " << ret);
+
+    ss_label = security_server_get_smacklabel_cookie(cookie);
+    RUNNER_ASSERT_MSG(ss_label != NULL, "get_smacklabel_cookie failed.");
+
+    ret = security_server_check_privilege_by_pid(getpid(), "_", "rx");
+    if(ret != SECURITY_SERVER_API_SUCCESS) {
+        free(ss_label);
+        RUNNER_ASSERT_MSG(false, "check_privilege_by_pid failed. Result: " << ret);
+    }
+}
+
+/**
+ * NOSMACK version of tc07 test.
+ *
+ * Similarily to previous tests - no need to set self label because SMACK is off. Just as
+ * tc01a/tc01c replacement, security_server_app_give_access should return only success. Hence the
+ * NOSMACK version of tc08 test is skipped.
+ */
+RUNNER_CHILD_TEST_NOSMACK(tc07_check_API_data_share_allow_nosmack)
+{
+    int ret = -1;
+    const char* subject_allow = TEST07_SUBJECT;
+
+    // drop root privileges
+    ret = drop_root_privileges();
+    RUNNER_ASSERT_MSG(ret == 0,
+            "Failed to drop root privileges. Result: " << ret << "uid = " << getuid());
+
+    ret = security_server_app_give_access(subject_allow, getpid());
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "app_give_access failed. Result: " << ret);
+}
+
 int main(int argc, char *argv[])
 {
     server_sockfd = -1;
index 92e0842..888a25a 100644 (file)
@@ -194,3 +194,41 @@ RUNNER_TEST(tc07_security_server_get_cookie_pid_weird_input_case)
     ret = security_server_get_cookie_pid(cookie);
     RUNNER_ASSERT(ret == SECURITY_SERVER_API_ERROR_INPUT_PARAM);
 }
+
+///////////////////////////
+/////NOSMACK ENV TESTS/////
+///////////////////////////
+
+/**
+ * NOSMACK version of tc06 test.
+ *
+ * security_server_check_privilege_by_sockfd at first checks if SMACK exists and then checks if
+ * params are correct. Even with incorrect params we should expect SUCCESS instead of
+ * ERROR_INPUT_PARAM.
+ */
+
+RUNNER_TEST_NOSMACK(tc06_security_server_check_privilege_by_sockfd_weird_input_case_nosmack)
+{
+    int ret = 0;
+    int sockfd = -1;
+    const char* object = "telephony_makecall";
+    const char* access_rights = "r";
+
+    //invalid sockfd case
+    ret = security_server_check_privilege_by_sockfd(sockfd, object, access_rights);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "check_privilege_by_sockfd failed. Result: " << ret);
+    sockfd = 0;
+
+    //null object case
+    char *object2 = NULL;
+    ret = security_server_check_privilege_by_sockfd(sockfd, object2, access_rights);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "check_privilege_by_sockfd failed. Result: " << ret);
+
+    //null access rights case
+    access_rights = NULL;
+    ret = security_server_check_privilege_by_sockfd(sockfd, object, access_rights);
+    RUNNER_ASSERT_MSG(ret == SECURITY_SERVER_API_SUCCESS,
+            "check_privilege_by_sockfd failed. Result: " << ret);
+}