Modify, systematize and reorder tests related the following libprivilege-control...
[platform/core/test/security-tests.git] / tests / libprivilege-control-tests / test_cases.cpp
index a9a448e..996c369 100644 (file)
@@ -17,6 +17,7 @@
 /*
  * @file        test_cases.cpp
  * @author      Jan Olszak (j.olszak@samsung.com)
+ * @author      Rafal Krypa (r.krypa@samsung.com)
  * @version     1.0
  * @brief       libprivilege-control test runer
  */
 #include <stdio.h>
 #include <vector>
 #include <errno.h>
+#include <memory>
+#include <ftw.h>
 #include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_child.h>
 #include <dpl/log/log.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/xattr.h>
 #include <sys/smack.h>
 #include <privilege-control.h>
+#include <fstream>
 
 
 #define SMACK_RULES_DIR  "/etc/smack/accesses.d/"
-#define TEST_DIR_TREE "/etc/smack/test_privilege_control_DIR"
-#define APPID_ADD  "test_APP_ID_add"
-#define APPID_REVOKE  "test_APP_ID_revoke"
+#define SMACK_LOAD2 "/smack/load2"
+#define TEST_APP_DIR "/etc/smack/test_privilege_control_DIR/app_dir"
+#define TEST_NON_APP_DIR "/etc/smack/test_privilege_control_DIR/non_app_dir"
 #define APPID_DIR  "test_APP_ID_dir"
+#define APPID_SHARED_DIR  "test_APP_ID_shared_dir"
+#define CANARY_LABEL "tiny_yellow_canary"
 
-#define APP_SET_PRIV  "test_APP"
+#define APP_ID  "test_APP"
 #define APP_SET_PRIV_PATH "/etc/smack/test_privilege_control_DIR/test_set_app_privilege/test_APP"
+#define APP_SET_PRIV_PATH_REAL "/etc/smack/test_privilege_control_DIR/test_set_app_privilege/test_APP_REAL"
 
 const char *PRIVS[] = { "WRT", "test_privilege_control_rules", NULL };
 
+#define LIBPRIVILEGE_APP_GROUP_LIST "/usr/share/privilege-control/app_group_list"
+#define LIBPRIVILEGE_TEST_DAC_FILE "/usr/share/privilege-control/test_privilege_control_rules.dac"
+
+#define APP_TEST_APP_1 "test-application1"
+#define APP_TEST_APP_2 "test-application_2"
+#define APP_TEST_APP_3 "test-app-3"
+#define APP_TEST_AV_1 "test-antivirus1"
+#define APP_TEST_AV_2 "test-antivirus_2"
+#define APP_TEST_AV_3 "test-av-3"
+#define SMACK_APPS_LABELS_DATABASE "/opt/dbspace/.privilege_control_all_apps_id.db"
+#define SMACK_AVS_LABELS_DATABASE "/opt/dbspace/.privilege_control_all_avs_id.db"
+
 #define APP_GID 5000
 #define APP_UID 5000
 #define APP_USER_NAME "app"
 #define APP_HOME_DIR "/opt/home/app"
 
+// How many open file descriptors should ftw() function use?
+#define FTW_MAX_FDS 16
 
 // Rules from test_privilege_control_rules.smack
-const std::vector< std::vector<std::string> > rulesAdd = {
-        { APPID_ADD, "test_book_1", "r" },
-        { APPID_ADD, "test_book_2", "w" },
-        { APPID_ADD, "test_book_3", "x" },
-        { APPID_ADD, "test_book_4", "rw" },
-        { APPID_ADD, "test_book_5", "rx" },
-        { APPID_ADD, "test_book_6", "wx" },
-        { APPID_ADD, "test_book_7", "rwx" },
-        { "test_subject_1", APPID_ADD, "r" },
-        { "test_subject_2", APPID_ADD, "w" },
-        { "test_subject_3", APPID_ADD, "x" },
-        { "test_subject_4", APPID_ADD, "rw" },
-        { "test_subject_5", APPID_ADD, "rx" },
-        { "test_subject_6", APPID_ADD, "wx" },
-        { "test_subject_7", APPID_ADD, "rwx" }};
-
-
-// Rules from test_privilege_control_rules.smack
-const std::vector< std::vector<std::string> > rulesRevoke = {
-        { APPID_REVOKE, "test_book_1", "r" },
-        { APPID_REVOKE, "test_book_2", "w" },
-        { APPID_REVOKE, "test_book_3", "x" },
-        { APPID_REVOKE, "test_book_4", "rw" },
-        { APPID_REVOKE, "test_book_5", "rx" },
-        { APPID_REVOKE, "test_book_6", "wx" },
-        { APPID_REVOKE, "test_book_7", "rwx" },
-        { "test_subject_1", APPID_REVOKE, "r" },
-        { "test_subject_2", APPID_REVOKE, "w" },
-        { "test_subject_3", APPID_REVOKE, "x" },
-        { "test_subject_4", APPID_REVOKE, "rw" },
-        { "test_subject_5", APPID_REVOKE, "rx" },
-        { "test_subject_6", APPID_REVOKE, "wx" },
-        { "test_subject_7", APPID_REVOKE, "rwx" }};
-
-// Files added in spec file
-const std::vector<std::string> paths = {
-        "/etc/smack/test_privilege_control_DIR",
-        "/etc/smack/test_privilege_control_DIR/test_file",
-        "/etc/smack/test_privilege_control_DIR/A",
-        "/etc/smack/test_privilege_control_DIR/A/test_file",
-        "/etc/smack/test_privilege_control_DIR/A/.test_file",
-        "/etc/smack/test_privilege_control_DIR/A/B/test_file" };
+const std::vector< std::vector<std::string> > rules = {
+        { APP_ID, "test_book_1", "r" },
+        { APP_ID, "test_book_2", "w" },
+        { APP_ID, "test_book_3", "x" },
+        { APP_ID, "test_book_4", "rw" },
+        { APP_ID, "test_book_5", "rx" },
+        { APP_ID, "test_book_6", "wx" },
+        { APP_ID, "test_book_7", "rwx" },
+        { "test_subject_1", APP_ID, "r" },
+        { "test_subject_2", APP_ID, "w" },
+        { "test_subject_3", APP_ID, "x" },
+        { "test_subject_4", APP_ID, "rw" },
+        { "test_subject_5", APP_ID, "rx" },
+        { "test_subject_6", APP_ID, "wx" },
+        { "test_subject_7", APP_ID, "rwx" },
+        { APP_ID, APPID_SHARED_DIR, "rwxat"}};
+
+
+namespace {
+
+const char* OSP_BLAHBLAH = "/usr/share/privilege-control/OSP_blahblah.smack";
+const char* WRT_BLAHBLAH = "/usr/share/privilege-control/WGT_blahblah.smack";
+const char* OTHER_BLAHBLAH = "/usr/share/privilege-control/blahblah.smack";
+const char* BLAHBLAH_FEATURE = "http://feature/blah/blahblah";
 
 /**
  * Check if every rule is true.
@@ -127,27 +131,272 @@ int test_have_any_accesses(const std::vector< std::vector<std::string> >& rules)
 
 RUNNER_TEST_GROUP_INIT(libprivilegecontrol)
 
+int nftw_remove_labels(const char *fpath, const struct stat *sb,
+                               int typeflag, struct FTW *ftwbuf)
+{
+       smack_lsetlabel(fpath, NULL, SMACK_LABEL_ACCESS);
+       smack_lsetlabel(fpath, NULL, SMACK_LABEL_EXEC);
+       smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
+
+       return 0;
+}
+
+int nftw_set_labels_non_app_dir(const char *fpath, const struct stat *sb,
+                               int typeflag, struct FTW *ftwbuf)
+{
+       smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_ACCESS);
+       smack_lsetlabel(fpath, CANARY_LABEL, SMACK_LABEL_EXEC);
+       smack_lsetlabel(fpath, NULL, SMACK_LABEL_TRANSMUTE);
+
+       return 0;
+}
+
+int nftw_check_labels_non_app_dir(const char *fpath, const struct stat *sb,
+                               int typeflag, struct FTW *ftwbuf)
+{
+    int result;
+    char* label;
+
+    /* ACCESS */
+    result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
+    RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+    result = strcmp(CANARY_LABEL, label);
+    RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is overwritten");
+
+    /* EXEC */
+    result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
+    RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+    result = strcmp(CANARY_LABEL, label);
+    RUNNER_ASSERT_MSG(result == 0, "EXEC label on " << fpath << " is overwritten");
+
+    /* TRANSMUTE */
+    result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
+    RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+    RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
+
+    return 0;
+}
+
+int nftw_check_labels_app_dir(const char *fpath, const struct stat *sb,
+                               int typeflag, struct FTW *ftwbuf)
+{
+    int result;
+    char* label;
+
+    /* ACCESS */
+    result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
+    RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+    RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
+    result = strcmp(APPID_DIR, label);
+    RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
+
+    /* EXEC */
+    result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
+    RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+    if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR)) {
+        RUNNER_ASSERT_MSG(label != NULL, "EXEC label on " << fpath << " is not set");
+        result = strcmp(APPID_DIR, label);
+        RUNNER_ASSERT_MSG(result == 0, "EXEC label on executable file " << fpath << " is incorrect");
+    } else
+        RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
+
+    /* TRANSMUTE */
+    result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
+    RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+    RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
+
+    return 0;
+}
+
+int nftw_check_labels_app_shared_dir(const char *fpath, const struct stat *sb,
+                               int typeflag, struct FTW *ftwbuf)
+{
+    int result;
+    char* label;
+
+    /* ACCESS */
+    result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
+    RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+    RUNNER_ASSERT_MSG(label != NULL, "ACCESS label on " << fpath << " is not set");
+    result = strcmp(APPID_SHARED_DIR, label);
+    RUNNER_ASSERT_MSG(result == 0, "ACCESS label on " << fpath << " is incorrect");
+
+    /* EXEC */
+    result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
+    RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+    RUNNER_ASSERT_MSG(label == NULL, "EXEC label on " << fpath << " is set");
+
+    /* TRANSMUTE */
+    result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
+    RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+    if (S_ISDIR(sb->st_mode)) {
+        RUNNER_ASSERT_MSG(label != NULL, "TRANSMUTE label on " << fpath << " is not set");
+        result = strcmp("TRUE", label);
+        RUNNER_ASSERT_MSG(result == 0, "TRANSMUTE label on " << fpath << " is not set");
+    } else
+        RUNNER_ASSERT_MSG(label == NULL, "TRANSMUTE label on " << fpath << " is set");
+
+    return 0;
+}
+
+int file_exists(const char* path)
+{
+    FILE* file = fopen(path, "r");
+    if (file) {
+        fclose(file);
+        return 0;
+    }
+    return -1;
+}
+
+void osp_blahblah_check(int line_no, const std::vector<std::string>& rules)
+{
+    std::ifstream smack_file(OSP_BLAHBLAH);
+    RUNNER_ASSERT_MSG(smack_file, "Line: " << line_no << " Failed to create " << OSP_BLAHBLAH);
+
+    auto it = rules.begin();
+    std::string line;
+    while(std::getline(smack_file,line)) {
+        RUNNER_ASSERT_MSG(it != rules.end(), "Line: " << line_no << "Additional line in file: " << line);
+        RUNNER_ASSERT_MSG(*it == line, "Line: " << line_no << " " << *it << "!=" << line);
+        it++;
+    }
+
+    RUNNER_ASSERT_MSG(it == rules.end(), "Line: " << line_no << " Missing line in file: " << *it);
+
+    smack_file.close();
+}
+
+void remove_smack_files()
+{
+    unlink(OSP_BLAHBLAH);
+    unlink(WRT_BLAHBLAH);
+    unlink(OTHER_BLAHBLAH);
+}
+
+int smack_file_name(const char* app_id, char** path)
+{
+    if (asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) {
+        RUNNER_ASSERT_MSG(false, "asprint failed");
+        *path = NULL;
+    }
+
+    return 0;
+}
+
+int cleaning_smack_app_files (void)
+{
+    char *path = NULL;
+    int fd = -1;
+
+    smack_file_name(APP_TEST_APP_1, &path);
+    unlink(path);
+    free(path);
+
+    smack_file_name(APP_TEST_APP_2, &path);
+    unlink(path);
+    free(path);
+
+    smack_file_name(APP_TEST_APP_3, &path);
+    unlink(path);
+    free(path);
+
+    smack_file_name(APP_TEST_AV_1, &path);
+    unlink(path);
+    free(path);
+
+    smack_file_name(APP_TEST_AV_2, &path);
+    unlink(path);
+    free(path);
+
+    smack_file_name(APP_TEST_AV_3, &path);
+    unlink(path);
+    free(path);
+
+    return 0;
+}
+
+int cleaning_smack_database_files (void)
+{
+    int fd = -1;
+
+    //clean app database
+    unlink(SMACK_APPS_LABELS_DATABASE);
+    fd = open(SMACK_APPS_LABELS_DATABASE, O_RDWR | O_EXCL | O_CREAT, 0644);
+    if (fd == -1) {
+        return -1;
+    }
+
+    //clean av database
+    unlink(SMACK_AVS_LABELS_DATABASE);
+    fd = open(SMACK_AVS_LABELS_DATABASE, O_RDWR | O_EXCL | O_CREAT, 0644);
+    if (fd == -1) {
+        return -1;
+    }
+
+    return 0;
+}
+} // namespace
+
 /**
- * Add permisions from  test_privilege_control_rules template
+ * Test setting labels for all files and folders in given path.
  */
-RUNNER_TEST(privilege_control_add_permissions)
+RUNNER_TEST(privilege_control02_app_label_dir)
+{
+    int result;
+
+    result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
+    RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
+
+    result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
+    RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
+
+    result = app_label_dir(APPID_DIR, TEST_APP_DIR);
+    RUNNER_ASSERT_MSG(result == 0, "app_label_dir() failed");
+
+    result = nftw(TEST_APP_DIR, &nftw_check_labels_app_dir, FTW_MAX_FDS, FTW_PHYS);
+    RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for app dir");
+
+    result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
+    RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
+}
+
+RUNNER_TEST(privilege_control03_app_label_shared_dir)
 {
-    char* path;
+    int result;
+
+    result = nftw(TEST_APP_DIR, &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS);
+    RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_APP_DIR);
+
+    result = nftw(TEST_NON_APP_DIR, &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
+    RUNNER_ASSERT_MSG(result == 0, "Unable to clean up Smack labels in " << TEST_NON_APP_DIR);
+
+    result = app_label_shared_dir(APP_ID, APPID_SHARED_DIR, TEST_APP_DIR);
+    RUNNER_ASSERT_MSG(result == 0, "app_label_shared_dir() failed");
+
+    result = nftw(TEST_APP_DIR, &nftw_check_labels_app_shared_dir, FTW_MAX_FDS, FTW_PHYS);
+    RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for shared app dir");
 
-    int result = app_add_permissions(APPID_ADD, PRIVS);
+    result = nftw(TEST_NON_APP_DIR, &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS);
+    RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for non-app dir");
+}
+
+
+/**
+ * Add permisions from  test_privilege_control_rules template
+ */
+RUNNER_TEST(privilege_control04_add_permissions)
+{
+    int result = app_add_permissions(APP_ID, PRIVS);
     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
             " Error adding app permissions. Errno: " << result);
 
     // Check if the accesses are realy applied..
-    result = test_have_all_accesses(rulesAdd);
+    result = test_have_all_accesses(rules);
     RUNNER_ASSERT_MSG(result==1, "Permissions not added.");
 
-    ///Investigate created SMACK rules files..
-    RUNNER_ASSERT_MSG(asprintf(&path, SMACK_RULES_DIR "%s", APPID_ADD) != -1,
-            "Error in asprintf");
-
     //// File exists?
-    FILE *pFile = fopen(path, "rb");
+    FILE *pFile = fopen(SMACK_RULES_DIR APP_ID, "rb");
     RUNNER_ASSERT_MSG(pFile != NULL,
             "SMACK file NOT created!. Errno: " << errno);
 
@@ -157,95 +406,69 @@ RUNNER_TEST(privilege_control_add_permissions)
     RUNNER_ASSERT_MSG(smack_file_length>0,
             "SMACK file empty, but privileges list was not empty.. Errno: " << errno);
 
-    // Clean up
-    result = app_revoke_permissions(APPID_ADD);
-    RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
-            "Error revoking app permissions. Errno: " << result);
-
     if (pFile != NULL)
         fclose(pFile);
 
 }
 
 /**
- * Test setting labels for all files and folders in given path.
- */
-RUNNER_TEST(privilege_control_dir_add)
-{
-    int result = app_label_dir(APPID_DIR, TEST_DIR_TREE);
-    RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
-            "Setting privileges for /etc/smack/test_privilege_control_DIR. Errno: " << result);
-
-    // Check if labels are realy set.
-    for(int i=0; i<paths.size(); ++i){
-        char* label;
-        result = smack_getlabel(paths[i].c_str(), &label, SMACK_LABEL_ACCESS);
-        RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
-        result = strcmp(APPID_DIR, label);
-        RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Label NOT set");
-        free(label);
-    }
-}
-
-/**
  * Revoke permissions from the list. Should be executed as privileged user.
  */
-RUNNER_TEST(privilege_control_revoke_permissions)
+RUNNER_CHILD_TEST(privilege_control06_revoke_permissions)
 {
     int result;
-
-    // Prepare permissions that we want to revoke
-    result = app_add_permissions(APPID_REVOKE, PRIVS);
-    RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
-            " Error adding app permissions. Errno: " << result);
+    char* path = NULL;
+    int fd;
 
     // Revoke permissions
-    result = app_revoke_permissions(APPID_REVOKE);
+    result = app_revoke_permissions(APP_ID);
     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS,
             "Error revoking app permissions. Errno: " << result);
 
     // Are all the permissions revoked?
-    result = test_have_all_accesses(rulesRevoke);
+    result = test_have_all_accesses(rules);
     RUNNER_ASSERT_MSG(result!=1, "Not all permisions revoked.");
 
-    // Investigate SMACK rules file
-    char* path;
-    RUNNER_ASSERT_MSG(asprintf(&path, SMACK_RULES_DIR "%s", APPID_REVOKE) != -1,
-            "Error in asprintf");
-
-    //// Is the smack file deleted?
-    FILE *pFile = fopen(path, "rb");
-    RUNNER_ASSERT_MSG(pFile == NULL,
-            "SMACK file NOT deleted after revoking ALL privileges. Errno: " << errno);
-
-    RUNNER_ASSERT_MSG(errno == ENOENT,
-            "SMACK file NOT deleted after revoking ALL privileges. Errno: " << errno);
+    smack_file_name(APP_ID, &path);
+    fd = open(path, O_RDONLY);
+    RUNNER_ASSERT_MSG(fd >= 0, "SMACK file deleted after app_revoke_permissions");
+    RUNNER_ASSERT_MSG(lseek(fd, 0, SEEK_END) == 0, "SMACK file not empty after app_revoke_permissions");
+    free(path);
+    close(fd);
+}
 
-    if (pFile != NULL)
-        fclose(pFile);
+static void read_gids(std::set<unsigned> &set, const char* file_path)
+{
+       FILE *f = fopen(file_path, "r");
+       RUNNER_ASSERT_MSG(f != NULL, "Unable to open file " << file_path);
+       unsigned gid;
+       while (fscanf(f, "%u\n", &gid) == 1) {
+               set.insert(gid);
+       }
 }
 
 /**
  * Set APP privileges.
  */
-RUNNER_TEST(privilege_control_set_app_privilege)
+RUNNER_CHILD_TEST(privilege_control05_set_app_privilege)
 {
     int result;
-    char* labelApp = "test_pc_label";
 
     // Preset exec label
-    smack_setlabel(APP_SET_PRIV_PATH,labelApp, SMACK_LABEL_EXEC);
+    smack_lsetlabel(APP_SET_PRIV_PATH_REAL, APP_ID, SMACK_LABEL_EXEC);
+    smack_lsetlabel(APP_SET_PRIV_PATH, APP_ID "_symlink", SMACK_LABEL_EXEC);
 
     // Set APP privileges
-    result = set_app_privilege(APP_SET_PRIV, NULL, APP_SET_PRIV_PATH);
+    result = set_app_privilege(APP_ID, NULL, APP_SET_PRIV_PATH);
     RUNNER_ASSERT_MSG(result == PC_OPERATION_SUCCESS, "Error in set_app_privilege. Error: " << result);
 
     // Check if SMACK label really set
     char * label;
     result = smack_new_label_from_self(&label);
-    RUNNER_ASSERT_MSG(result == 0, "Error setting label for exec" << result);
-    result = strcmp(labelApp, label);
-    RUNNER_ASSERT_MSG(result == 0, "Label NOT set");
+    RUNNER_ASSERT_MSG(result == 0, "Error getting current process label");
+    RUNNER_ASSERT_MSG(label != NULL, "Process label is not set");
+    result = strcmp(APP_ID, label);
+    RUNNER_ASSERT_MSG(result == 0, "Process label " << label << " is incorrect");
 
     // Check if DAC privileges really set
     RUNNER_ASSERT_MSG(getuid() == APP_UID, "Wrong UID");
@@ -256,5 +479,330 @@ RUNNER_TEST(privilege_control_set_app_privilege)
 
     result = strcmp(getenv("USER"), APP_USER_NAME);
     RUNNER_ASSERT_MSG(result == 0, "Wrong user USER NAME");
+
+    std::set<unsigned> groups_check;
+    read_gids(groups_check, LIBPRIVILEGE_APP_GROUP_LIST);
+    read_gids(groups_check, LIBPRIVILEGE_TEST_DAC_FILE);
+
+    int groups_cnt = getgroups(0, NULL);
+    RUNNER_ASSERT_MSG(groups_cnt > 0, "Wrong number of supplementary groupsCnt");
+    gid_t *groups_list = (gid_t *) calloc(groups_cnt, sizeof(gid_t));
+    RUNNER_ASSERT_MSG(groups_list != NULL, "Memory allocation failed");
+    getgroups(groups_cnt, groups_list);
+
+    for (int i = 0; i < groups_cnt; ++i) {
+        if (groups_check.erase(groups_list[i]) == 0) {
+            // getgroups() may also return process' main group
+            if (groups_list[i] == getgid())
+                RUNNER_ASSERT_MSG(false, "Application belongs to unknown group (GID=" << groups_list[i] << ")");
+        }
+    }
+    std::string groups_left;
+    for (std::set<unsigned>::iterator it = groups_check.begin(); it != groups_check.end(); it++) {
+        groups_left.append(std::to_string(*it)).append(" ");
+    }
+    RUNNER_ASSERT_MSG(groups_check.empty(), "Application doesn't belong to some required groups: " << groups_left);
+}
+
+RUNNER_TEST(privilege_control08_app_give_access)
+{
+    const char *subject = "lkjq345v34sfa";
+    const char *object = "lk9290f92lkjz";
+    smack_accesses *tmp = NULL;
+
+    RUNNER_ASSERT(0 == smack_accesses_new(&tmp));
+
+    std::unique_ptr<smack_accesses,std::function<void(smack_accesses*)>>
+        smack(tmp, smack_accesses_free);
+
+    RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "r--a-"));
+    RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
+
+    app_give_access(subject, object, "wt");
+
+    RUNNER_ASSERT(1 == smack_have_access(subject, object, "rwat"));
+    RUNNER_ASSERT(0 == smack_have_access(subject, object, "x"));
+
+    app_revoke_access(subject, object);
+
+    RUNNER_ASSERT(1 == smack_have_access(subject, object, "ra"));
+    RUNNER_ASSERT(0 == smack_have_access(subject, object, "w"));
+    RUNNER_ASSERT(0 == smack_have_access(subject, object, "x"));
+    RUNNER_ASSERT(0 == smack_have_access(subject, object, "t"));
+
+    RUNNER_ASSERT(0 == smack_accesses_add(smack.get(), subject, object, "-"));
+    RUNNER_ASSERT(0 == smack_accesses_apply(smack.get()));
+}
+
+/**
+ * Add new API feature
+ */
+RUNNER_TEST(privilege_control09_add_api_feature)
+{
+    int result;
+
+    remove_smack_files();
+
+
+    // argument validation
+    result = add_api_feature(APP_TYPE_OSP, NULL, NULL, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+
+    result = add_api_feature(APP_TYPE_OSP,"" , NULL, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+
+
+    // already existing features
+    result = add_api_feature(APP_TYPE_OSP,"messaging" , NULL, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+
+    result = add_api_feature(APP_TYPE_OSP,"blahblah/messaging" , NULL, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+
+    result = add_api_feature(APP_TYPE_WGT,"blahblahblah/messaging" , NULL, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+
+    result = add_api_feature(APP_TYPE_OTHER,"blah/messaging" , NULL, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+
+
+    // empty features
+    result = add_api_feature(APP_TYPE_OSP,"blahblah" , NULL, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+
+    result = add_api_feature(APP_TYPE_WGT,"blahblah" , NULL, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+
+    result = add_api_feature(APP_TYPE_OTHER,"blahblah" , NULL, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+
+
+    // smack files existence
+    result = file_exists(OSP_BLAHBLAH);
+    RUNNER_ASSERT(result == -1);
+
+    result = file_exists(WRT_BLAHBLAH);
+    RUNNER_ASSERT(result == -1);
+
+    result = file_exists(OTHER_BLAHBLAH);
+    RUNNER_ASSERT(result == -1);
+
+
+    // empty rules
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , { NULL }, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+    result = file_exists(OSP_BLAHBLAH);
+    RUNNER_ASSERT(result == -1);
+
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "", NULL }, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+    result = file_exists(OSP_BLAHBLAH);
+    RUNNER_ASSERT(result == 0);
+    remove_smack_files();
+
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ " \t\n", "\t \n", "\n\t  ", NULL }, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+    result = file_exists(OSP_BLAHBLAH);
+    RUNNER_ASSERT(result == 0);
+    remove_smack_files();
+
+
+    // malformed rules
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "malformed", NULL }, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+    result = file_exists(OSP_BLAHBLAH);
+    RUNNER_ASSERT(result == -1);
+
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "malformed malformed", NULL }, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+    result = file_exists(OSP_BLAHBLAH);
+    RUNNER_ASSERT(result == -1);
+
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "-malformed malformed rwxat", NULL }, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+    result = file_exists(OSP_BLAHBLAH);
+    RUNNER_ASSERT(result == -1);
+
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "~/\"\\\ malformed rwxat", NULL }, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+    result = file_exists(OSP_BLAHBLAH);
+    RUNNER_ASSERT(result == -1);
+
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "subject object rwxat something else", NULL }, NULL);
+    RUNNER_ASSERT(result == PC_ERR_INVALID_PARAM);
+    result = file_exists(OSP_BLAHBLAH);
+    RUNNER_ASSERT(result == -1);
+
+
+    // correct rules
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "malformed malformed maaaaaalformed", NULL }, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+    osp_blahblah_check(__LINE__, { "malformed malformed r--a-" });
+    remove_smack_files();
+
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){ "subject object foo", NULL }, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+    osp_blahblah_check(__LINE__, { "subject object -----" });
+    remove_smack_files();
+
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
+        "subject    object\t rwxat",
+        " \t \n",
+        "subject2\tobject2 txarw",
+        "",
+        NULL }, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+    osp_blahblah_check(__LINE__, { "subject object rwxat", "subject2 object2 rwxat"});
+    remove_smack_files();
+
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
+        "Sub::jE,ct object a-RwX",
+        NULL }, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+    osp_blahblah_check(__LINE__, { "Sub::jE,ct object rwxa-"});
+    remove_smack_files();
+
+    // TODO For now identical/complementary rules are not merged.
+    result = add_api_feature(APP_TYPE_OSP, BLAHBLAH_FEATURE , (const char*[]){
+        "subject object rwxat",
+        " \t \n",
+        "subject object txarw",
+        "",
+        NULL }, NULL);
+    RUNNER_ASSERT(result == PC_OPERATION_SUCCESS);
+    osp_blahblah_check(__LINE__, { "subject object rwxat", "subject object rwxat"});
+    remove_smack_files();
+
+
+    // TODO database group ids
+}
+
+/*
+ * Check app_install function
+ */
+RUNNER_TEST(privilege_control01_app_install)
+{
+    int result;
+    char *path = NULL;
+    int fd = -1;
+
+    smack_file_name(APP_ID, &path);
+    unlink(path);
+
+    result = app_install(APP_ID);
+    RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
+
+    // checking if file really exists
+    fd = open(path, O_RDONLY);
+    RUNNER_ASSERT_MSG(fd >= 0, "File open failed: " << path << " : " << result << ". Errno: " << strerror(errno));
+    close(fd);
+    free(path);
+
+    // try install second time app with the same ID - it should failed with -1 (Errno: File exists).
+    result = app_install(APP_ID);
+    RUNNER_ASSERT_MSG(result == -1, "app_install returned " << result <<". Errno: " << strerror(errno));
+}
+
+/*
+ * Check app_install function
+ */
+RUNNER_TEST(privilege_control07_app_uninstall)
+{
+    int result;
+    char *path = NULL;
+    int fd = -1;
+
+    smack_file_name(APP_ID, &path);
+    result = app_uninstall(APP_ID);
+    RUNNER_ASSERT_MSG(result == 0, "app_uninstall returned " << result <<". Errno: " << strerror(errno));
+
+    // checking if file really exists
+    smack_file_name(APP_ID, &path);
+    fd = open(path, O_RDONLY);
+    RUNNER_ASSERT_MSG(fd == -1, "SMACK file NOT deleted after app_uninstall");
+    close(fd);
+    free(path);
 }
 
+/*
+ * Check app_register_av function
+ * Notice that this test case may have no sense if previous would fail (privilege_control06_app_install)
+ */
+RUNNER_TEST(privilege_control10_app_register_av)
+{
+    int result;
+    //FILE* file_av = NULL;
+    //FILE* file_app = NULL;
+    //int fd_app = -1;
+    int fd  = -1;
+    char *path = NULL;
+    char *buff;
+    int len;
+    int i;
+    //char label1[SMACK_LABEL_LEN +1];
+    //char label2[SMACK_LABEL_LEN +1];
+    //char acces_rights[6 +1];
+    //char row[2 * SMACK_LABEL_LEN + 20] //
+    const char* correct_antivirus1_rules = "test-antivirus1 test-application1 rwx--\n"
+                                            "test-antivirus1 test-application_2 rwx--\n"
+                                            "test-antivirus1 test-app-3 rwx--";
+    const char* correct_antivirus2_rules = "test-antivirus_2 test-application1 rwx--\n"
+                                           "test-antivirus_2 test-application_2 rwx--\n"
+                                           "test-antivirus_2 test-app-3 rwx--";
+
+    // cleaning
+    cleaning_smack_app_files();
+    cleaning_smack_database_files();
+
+    result = app_install(APP_TEST_APP_1);
+    RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
+
+    result = app_install(APP_TEST_APP_2);
+    RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
+
+    result = app_register_av(APP_TEST_AV_1);
+    RUNNER_ASSERT_MSG(result == 0, "app_register_av returned " << result <<". Errno: " << strerror(errno));
+
+    result = app_install(APP_TEST_APP_3);
+    RUNNER_ASSERT_MSG(result == 0, "app_install returned " << result <<". Errno: " << strerror(errno));
+
+    result = app_register_av(APP_TEST_AV_2);
+    RUNNER_ASSERT_MSG(result == 0, "app_register_av returned " << result <<". Errno: " << strerror(errno));
+
+    // checking rules for anti virus 1
+    // compare between file in /etc/smack/access.d/ and correct value (correct_antivirus1_rules).
+    len = strlen(correct_antivirus1_rules);
+    buff = (char *) malloc((len+1) * sizeof(char));
+    smack_file_name(APP_TEST_AV_1, &path);
+    fd = open(path, O_RDONLY);
+    free(path);
+    RUNNER_ASSERT_MSG(fd > -1, "file open failed " << result <<". Errno: " << strerror(errno));
+    result = read(fd, buff, len);
+    close(fd);
+    fd = -1;
+    buff[len] = '\0';
+    RUNNER_ASSERT_MSG(result > -1, "read from file descriptor failed. Errno: " << strerror(errno));
+    result = strncmp(buff, correct_antivirus1_rules, len);
+    RUNNER_ASSERT_MSG(result == 0, "Rules do not match: " << result << "\n\"" << buff << "\"\n\"" << correct_antivirus1_rules << "\"\n" << len);
+    free(buff);
+
+    // checking rules for anti virus 2
+    len = strlen(correct_antivirus2_rules);
+    buff = (char *) malloc((len+1) * sizeof(char));
+    smack_file_name(APP_TEST_AV_2, &path);
+    fd = open(path, O_RDONLY);
+    free (path);
+    RUNNER_ASSERT_MSG(fd > -1, "file open failed " << result <<". Errno: " << strerror(errno));
+    result = read(fd, buff, len);
+    close (fd);
+    fd = -1;
+    buff[len] = '\0';
+    RUNNER_ASSERT_MSG(result > -1, "read from file descriptor failed. Errno: " << strerror(errno));
+    result = strncmp(buff, correct_antivirus2_rules, len);
+    RUNNER_ASSERT_MSG(result == 0, "Rules do not match: " << result << "\n\"" << buff << "\"\n\"" << correct_antivirus1_rules << "\"\n" << len);
+    free(buff);
+
+    // cleaning
+    cleaning_smack_app_files();
+    cleaning_smack_database_files();
+}