Revert "rollback because of rule database"
authorJan Olszak <j.olszak@samsung.com>
Tue, 17 Sep 2013 08:33:20 +0000 (10:33 +0200)
committerJan Olszak <j.olszak@samsung.com>
Fri, 18 Oct 2013 12:26:52 +0000 (14:26 +0200)
Conflicts:

packaging/libprivilege-control.changes
packaging/libprivilege-control.spec
rule_loader/smack-early-rules.service
rule_loader/smack-late-rules.service

Change-Id: I80d42cdb1ed442db40646b4d5eb8ec0bac1ec0a0

25 files changed:
CMakeLists.txt
api_feature_loader/CMakeLists.txt [moved from rule_loader/CMakeLists.txt with 61% similarity]
api_feature_loader/api_feature_loader.c [new file with mode: 0644]
db/load-rules-db.sql [new file with mode: 0644]
db/rules-db-data.sql [new file with mode: 0644]
db/rules-db-sql-udf.c [new file with mode: 0644]
db/rules-db.sql [new file with mode: 0644]
db/rules-db.xml [new file with mode: 0644]
include/access-db.h
include/common.h
include/privilege-control.h
include/rules-db-internals.h [new file with mode: 0644]
include/rules-db.h [new file with mode: 0644]
packaging/libprivilege-control-conf.manifest
packaging/libprivilege-control.changes
packaging/libprivilege-control.spec
rule_loader/rule_loader.c [deleted file]
rule_loader/smack-early-rules.service [deleted file]
rule_loader/smack-late-rules.service [deleted file]
smack-rules.service [new file with mode: 0644]
src/access-db.c
src/common.c
src/privilege-control.c
src/rules-db-internals.c [new file with mode: 0644]
src/rules-db.c [new file with mode: 0644]

index aa7f2c8..b77c5cc 100644 (file)
@@ -1,6 +1,7 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 PROJECT(libprivilege-control C)
 
+SET(TARGET_PRIVILEGE_CONTROL "privilege-control")
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(EXEC_PREFIX "\${prefix}")
 SET(SHAREDIR "${PREFIX}/share/privilege-control")
@@ -13,7 +14,7 @@ SET(VERSION "${VERSION_MAJOR}.0.2")
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
 
 INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED libsmack libiri dlog)
+pkg_check_modules(pkgs REQUIRED libsmack libiri dlog sqlite3)
 
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
@@ -30,13 +31,13 @@ SET(CMAKE_C_FLAGS_RELEASE "-O2 -g")
 SET(src_dir "./src")
 SET(include_dir "./include")
 
+
 ## Additional flag
 ADD_DEFINITIONS("-fvisibility=hidden")
 ADD_DEFINITIONS("-DSHAREDIR=${SHAREDIR}")
 ADD_DEFINITIONS("-DHOMEDIR=${HOMEDIR}")
-ADD_DEFINITIONS("-Wall -Werror")
+ADD_DEFINITIONS("-Wall -Werror -Wextra")
 
-#ADD_DEFINITIONS("-DDLOG_DEBUG_ENABLED")    #enables dlogutil logs
 ADD_DEFINITIONS("-DDLOG_WARN_ENABLED")
 ADD_DEFINITIONS("-DDLOG_ERROR_ENABLED")
 
@@ -47,17 +48,27 @@ SET(libprivilege-control_SOURCES
        ${src_dir}/privilege-control.c
        ${src_dir}/access-db.c
        ${src_dir}/common.c
+       ${src_dir}/rules-db.c
+       ${src_dir}/rules-db-internals.c
        )
 SET(libprivilege-control_LDFLAGS " -module -avoid-version ")
 SET(libprivilege-control_CFLAGS  " ${CFLAGS} -fPIC -I${include_dir}")
 SET(libprivilege-control_LIBADD  "${pkgs_LDFLAGS} -lcap -lcrypt")
 
-ADD_LIBRARY(privilege-control SHARED ${libprivilege-control_SOURCES})
-TARGET_LINK_LIBRARIES(privilege-control ${libprivilege-control_LIBADD} ${pkgs_LIBRARIES})
-SET_TARGET_PROPERTIES(privilege-control PROPERTIES COMPILE_FLAGS "${libprivilege-control_CFLAGS}")
-SET_TARGET_PROPERTIES(privilege-control PROPERTIES SOVERSION ${VERSION_MAJOR})
-SET_TARGET_PROPERTIES(privilege-control PROPERTIES VERSION ${VERSION})
+ADD_LIBRARY(${TARGET_PRIVILEGE_CONTROL} SHARED ${libprivilege-control_SOURCES})
+TARGET_LINK_LIBRARIES(${TARGET_PRIVILEGE_CONTROL} ${libprivilege-control_LIBADD} ${pkgs_LIBRARIES})
+SET_TARGET_PROPERTIES(${TARGET_PRIVILEGE_CONTROL} PROPERTIES COMPILE_FLAGS "${libprivilege-control_CFLAGS}")
+SET_TARGET_PROPERTIES(${TARGET_PRIVILEGE_CONTROL} PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(${TARGET_PRIVILEGE_CONTROL} PROPERTIES VERSION ${VERSION})
 ###################################################################################################
+## for rules-db-sql-udf.so (library)
+SET(rules-db-sql-udf_SOURCES ./db/rules-db-sql-udf.c)
+SET(rules-db-sql-udf_LDFLAGS " -avoid-version -module ")
+SET(rules-db-sql-udf_CFLAGS  " ${CFLAGS} -fPIC")
+
+ADD_LIBRARY(rules-db-sql-udf MODULE ${rules-db-sql-udf_SOURCES})
+SET_TARGET_PROPERTIES(rules-db-sql-udf PROPERTIES COMPILE_FLAGS "${rules-db-sql-udf_CFLAGS}")
+SET_TARGET_PROPERTIES(rules-db-sql-udf PROPERTIES LINK_FLAGS "${rules-db-sql-udf_LDFLAGS}")
 
 ###################################################################################################
 ## for slp-su (excutable)
@@ -66,27 +77,31 @@ SET(slp-su_LDFLAGS " -module -avoid-version ")
 SET(slp-su_CFLAGS  " ${CFLAGS} -fPIC -I${include_dir}")
 
 ADD_EXECUTABLE(slp-su ${slp-su_SOURCES})
-TARGET_LINK_LIBRARIES(slp-su ${pkgs_LDFLAGS} ${pkgs_LIBRARIES} privilege-control)
+TARGET_LINK_LIBRARIES(slp-su ${pkgs_LDFLAGS} ${pkgs_LIBRARIES} ${TARGET_PRIVILEGE_CONTROL})
 SET_TARGET_PROPERTIES(slp-su PROPERTIES COMPILE_FLAGS "${slp-su_CFLAGS}")
 ###################################################################################################
 
-#for rule_loader binary, which loads rules after home screen shows up
-ADD_SUBDIRECTORY(rule_loader)
 
 CONFIGURE_FILE(libprivilege-control.pc.in libprivilege-control.pc @ONLY)
 
-INSTALL(TARGETS privilege-control DESTINATION  ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
+INSTALL(TARGETS ${TARGET_PRIVILEGE_CONTROL} DESTINATION  ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
+INSTALL(TARGETS rules-db-sql-udf DESTINATION  ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libprivilege-control.pc DESTINATION  ${LIB_INSTALL_DIR}/pkgconfig)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/passwd DESTINATION /opt/etc/)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/group DESTINATION /opt/etc/)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/smack_default_labeling DESTINATION /etc/rc.d/init.d/)
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/smack_rules DESTINATION /etc/rc.d/init.d/)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/privilege-control.h DESTINATION ${INCLUDE_INSTALL_DIR})
-INSTALL(FILES .privilege_control_all_apps_id.db DESTINATION /opt/dbspace)
-INSTALL(FILES .privilege_control_all_avs_id.db DESTINATION /opt/dbspace)
 INSTALL(FILES .privilege_control_app_gids.db DESTINATION /opt/dbspace)
-INSTALL(FILES .privilege_control_public_dirs.db DESTINATION /opt/dbspace)
-INSTALL(FILES .privilege_control_app_setting.db DESTINATION /opt/dbspace)
-INSTALL(FILES .privilege_control_setting_dir.db DESTINATION /opt/dbspace)
 #INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/udev/ DESTINATION lib/udev)
 INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/slp-su DESTINATION bin)
+
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/rules-db.sql DESTINATION /opt/dbspace)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/rules-db-data.sql DESTINATION /opt/dbspace)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/db/load-rules-db.sql DESTINATION /opt/etc/smack/)
+
+INSTALL(FILES ${PROJECT_SOURCE_DIR}/smack-rules.service
+       DESTINATION /usr/lib/systemd/system
+        PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
+
+ADD_SUBDIRECTORY(api_feature_loader)
similarity index 61%
rename from rule_loader/CMakeLists.txt
rename to api_feature_loader/CMakeLists.txt
index 18e3867..ddcf19a 100644 (file)
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
+
 # @file        CMakeLists.txt
-# @author      Pawel Polawski (p.polawski@samsung.com)
+# @author      Jan Olszak (j.olszak@samsung.com)
 # @version     0.1
-# @brief
-#
-INCLUDE(FindPkgConfig)
-SET(TARGET "rule_loader")
+# @brief       CMake file for the api_feature_loader
+
+SET(TARGET_API_FEATURE_LOADER "api_feature_loader")
 
 #dependencies
 PKG_CHECK_MODULES(TARGET_DEP
@@ -28,10 +28,12 @@ PKG_CHECK_MODULES(TARGET_DEP
 
 #files to compile
 SET(TARGET_SOURCES
-    ${PROJECT_SOURCE_DIR}/rule_loader/rule_loader.c
+    ${PROJECT_SOURCE_DIR}/api_feature_loader/api_feature_loader.c
     ${PROJECT_SOURCE_DIR}/src/access-db.c
     ${PROJECT_SOURCE_DIR}/src/common.c
     ${PROJECT_SOURCE_DIR}/src/privilege-control.c
+    ${PROJECT_SOURCE_DIR}/src/rules-db.c
+    ${PROJECT_SOURCE_DIR}/src/rules-db-internals.c
     )
 
 #header directories
@@ -40,42 +42,20 @@ INCLUDE_DIRECTORIES(
     ${PROJECT_SOURCE_DIR}/include
     )
 
-#preprocessor definitions
-#ADD_DEFINITIONS("-DDPL_LOGS_ENABLED")
-
 #output format
-ADD_EXECUTABLE(${TARGET} ${TARGET_SOURCES})
+ADD_EXECUTABLE(${TARGET_API_FEATURE_LOADER} ${TARGET_SOURCES})
 
 #linker directories
-TARGET_LINK_LIBRARIES(${TARGET}
+TARGET_LINK_LIBRARIES(${TARGET_API_FEATURE_LOADER}
     ${TARGET_DEP_LIBRARIES}
-    privilege-control
+    ${TARGET_PRIVILEGE_CONTROL}
     )
 
 #place for output file
-INSTALL(TARGETS ${TARGET}
+INSTALL(TARGETS ${TARGET_API_FEATURE_LOADER}
     DESTINATION /usr/bin
     PERMISSIONS
     OWNER_READ
     OWNER_WRITE
     OWNER_EXECUTE
-    )
-
-#place for additional systemd service
-INSTALL(FILES
-    ${PROJECT_SOURCE_DIR}/rule_loader/smack-late-rules.service
-    DESTINATION /usr/lib/systemd/system
-    PERMISSIONS
-    OWNER_READ
-    OWNER_WRITE
-    OWNER_EXECUTE
-    )
-
-INSTALL(FILES
-    ${PROJECT_SOURCE_DIR}/rule_loader/smack-early-rules.service
-    DESTINATION /usr/lib/systemd/system
-    PERMISSIONS
-    OWNER_READ
-    OWNER_WRITE
-    OWNER_EXECUTE
-    )
+    )
\ No newline at end of file
diff --git a/api_feature_loader/api_feature_loader.c b/api_feature_loader/api_feature_loader.c
new file mode 100644 (file)
index 0000000..7d88044
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+* @file        api_feature_loader.c
+* @author      Jan Olszak (j.olszak@samsung.com)
+* @version     1.0
+* @brief       Binary file for loading predefined API features to the database.
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h>              // For file manipulation
+#include <stdlib.h>             // For malloc and free
+#include <dirent.h>             // For iterating directories
+#include <obstack.h>            // For obstack implementation
+#include <privilege-control.h>  // For app_type
+#include <sys/smack.h>          // For SMACK_LABEL_LEN
+#include <getopt.h>             // For getopt
+
+
+#define API_FEATURE_LOADER_VERSION "1.0"
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free  free
+
+#define vector_init(V)              obstack_init(&(V))
+#define vector_push_back_ptr(V, I)  obstack_ptr_grow(&(V), (I))
+#define vector_finish(V)            obstack_finish(&(V))
+#define vector_free(V)              obstack_free(&(V), NULL)
+
+#define ACC_LEN 6
+
+#define API_FEATURES_DIR "/usr/share/privilege-control/"
+
+#define API_FEATURE_LOADER_LOG(format, ...) if(i_verbose_flag__) printf(format, ##__VA_ARGS__)
+
+typedef struct obstack vector_t;
+static int i_verbose_flag__ = 0;
+static const size_t ui_smack_ext_len__ = 6; // = strlen(".smack");
+
+bool has_prefix(const char *const s_str, const char *const s_prefix)
+{
+       return !strncmp(s_str, s_prefix, strlen(s_prefix));
+}
+
+bool has_smack_ext(const char *const s_str)
+{
+       return strlen(s_str) > ui_smack_ext_len__ &&
+              !strncmp(&s_str[strlen(s_str) - ui_smack_ext_len__], ".smack", ui_smack_ext_len__);
+}
+
+int wrt_filter(const struct dirent *entry)
+{
+       return !strcmp(entry->d_name, "WRT.smack");
+}
+
+int wrt_partner_filter(const struct dirent *entry)
+{
+       return !strcmp(entry->d_name, "WRT_partner.smack");
+}
+
+int wrt_platform_filter(const struct dirent *entry)
+{
+       return !strcmp(entry->d_name, "WRT_platform.smack");
+}
+
+int wrt_family_filter(const struct dirent *entry)
+{
+       return has_prefix(entry->d_name, "WRT_") &&
+              !has_prefix(entry->d_name, "WRT_partner") &&
+              !has_prefix(entry->d_name, "WRT_platform") &&
+              has_smack_ext(entry->d_name);
+}
+
+int osp_filter(const struct dirent *entry)
+{
+       return !strcmp(entry->d_name, "OSP.smack");
+}
+
+int osp_partner_filter(const struct dirent *entry)
+{
+       return !strcmp(entry->d_name, "OSP_partner.smack");
+}
+
+int osp_platform_filter(const struct dirent *entry)
+{
+       return !strcmp(entry->d_name, "OSP_platform.smack");
+}
+
+int osp_family_filter(const struct dirent *entry)
+{
+       return has_prefix(entry->d_name, "OSP_") &&
+              !has_prefix(entry->d_name, "OSP_partner") &&
+              !has_prefix(entry->d_name, "OSP_platform") &&
+              has_smack_ext(entry->d_name);
+}
+
+int efl_filter(const struct dirent *entry)
+{
+       return !strcmp(entry->d_name, "EFL.smack");
+}
+
+int efl_family_filter(const struct dirent *entry)
+{
+       return has_prefix(entry->d_name, "EFL_") &&
+              has_smack_ext(entry->d_name);
+}
+
+void load_rules_from_file(const char *s_rules_file_path,
+                         const char *s_permission_name,
+                         const app_type_t app_type)
+{
+       FILE *p_file       = NULL;
+       char *s_rule       = NULL;
+       char **rules_array = NULL;
+       size_t i_num_rules = 0;
+       size_t i           = 0;
+       int ret;
+       vector_t rules_vector;
+
+       p_file = fopen(s_rules_file_path, "r");
+       if(!p_file) goto finish;
+
+       API_FEATURE_LOADER_LOG("Loading permission: %s  \n", s_permission_name);
+
+       vector_init(rules_vector);
+       while(getline(&s_rule, &i, p_file) > 0) {
+               vector_push_back_ptr(rules_vector, s_rule);
+               ++i_num_rules;
+               s_rule = NULL;
+       }
+       vector_push_back_ptr(rules_vector, NULL);
+
+       rules_array = vector_finish(rules_vector);
+
+       ret = perm_add_api_feature(app_type,
+                                  s_permission_name,
+                                  (const char **)rules_array,
+                                  NULL,
+                                  i_num_rules);
+       if(ret != PC_OPERATION_SUCCESS)
+               API_FEATURE_LOADER_LOG("Error %d\n", ret);
+
+finish:
+       if(p_file != NULL) fclose(p_file);
+       if(rules_array != NULL) {
+               for(i = 0; i < i_num_rules; ++i) {
+                       free(rules_array[i]);
+               }
+               vector_free(rules_vector);
+       }
+}
+
+void load_permission_family(int (*filter)(const struct dirent *),
+                           int i_prefix_len,
+                           const app_type_t app_type,
+                           const char const *s_dir)
+{
+       int i, num_files          = 0;
+       struct dirent **file_list = NULL;
+       char *s_path              = NULL;
+       char *s_permission_name   = NULL;
+       int i_perm_name_len;
+
+       num_files = scandir(s_dir, &file_list, filter, alphasort);
+       for(i = 0; i < num_files; ++i) {
+               if(asprintf(&s_path, "%s%s", s_dir, file_list[i]->d_name) <= 0) continue;
+
+               i_perm_name_len = strlen(file_list[i]->d_name);
+               s_permission_name = (char *) malloc(i_perm_name_len);
+               if(!s_permission_name) {
+                       API_FEATURE_LOADER_LOG("Error during allocating memory.\n");
+                       return;
+               }
+               strncpy(s_permission_name,
+                       &(file_list[i]->d_name[i_prefix_len]),
+                       i_perm_name_len - i_prefix_len - ui_smack_ext_len__);
+               s_permission_name[i_perm_name_len - i_prefix_len - ui_smack_ext_len__ ] = '\0';
+               load_rules_from_file(s_path, s_permission_name, app_type);
+
+               free(file_list[i]);
+               free(s_path);
+               free(s_permission_name);
+               s_path = NULL;
+               s_permission_name = NULL;
+       }
+       free(file_list);
+}
+
+void load_pemission_type_rules(int (*filter)(const struct dirent *),
+                              const char const *s_permission_name,
+                              const app_type_t app_type,
+                              const char const *s_dir)
+{
+       char *s_path              = NULL;
+       struct dirent **file_list = NULL;
+       int i, num_files;
+
+       num_files = scandir(s_dir, &file_list, filter, alphasort);
+       for(i = 0; i < num_files; ++i) {
+               if(asprintf(&s_path, "%s%s", API_FEATURES_DIR, file_list[i]->d_name) <= 0) continue;
+
+               load_rules_from_file(s_path, s_permission_name, app_type);
+
+               if(file_list[i]) free(file_list[i]);
+               if(s_path) free(s_path);
+               s_path = NULL;
+       }
+       free(file_list);
+}
+
+
+void load_from_dir(const char  *const s_dir)
+{
+
+       API_FEATURE_LOADER_LOG("Loading rules from directory...\n");
+       if(perm_modification_start()) return;
+
+       // Load rules specific to permission's types:
+       load_pemission_type_rules(wrt_filter, "WRT", APP_TYPE_WGT, s_dir);
+       load_pemission_type_rules(wrt_partner_filter, "WRT_partner", APP_TYPE_WGT_PARTNER, s_dir);
+       load_pemission_type_rules(wrt_platform_filter, "WRT_platform", APP_TYPE_WGT_PLATFORM, s_dir);
+       load_pemission_type_rules(osp_filter, "OSP", APP_TYPE_OSP, s_dir);
+       load_pemission_type_rules(osp_partner_filter, "OSP_partner" , APP_TYPE_OSP_PARTNER, s_dir);
+       load_pemission_type_rules(osp_platform_filter, "OSP_platform", APP_TYPE_OSP_PLATFORM, s_dir);
+       load_pemission_type_rules(efl_filter, "EFL", APP_TYPE_EFL, s_dir);
+
+       // Load rules for each permission type:
+       load_permission_family(wrt_family_filter, strlen("WRT_"), APP_TYPE_WGT, s_dir);
+       load_permission_family(osp_family_filter, strlen("OSP_"), APP_TYPE_OSP, s_dir);
+       load_permission_family(efl_family_filter, strlen("EFL_"), APP_TYPE_EFL, s_dir);
+
+       perm_modification_finish();
+       API_FEATURE_LOADER_LOG("Done.\n");
+
+}
+
+int main(int argc, char *argv[])
+{
+       int c;
+       int i_option_index = 0;
+
+       bool b_load_from_file = false;
+       const char *s_file;
+
+       bool b_load_from_dir = false;
+       const char *s_dir;
+
+       static struct option long_options[] = {
+               {"verbose", no_argument,       &i_verbose_flag__,  1},
+               {"file",    required_argument, 0, 'f'},
+               {"dir",     required_argument, 0, 'd'},
+               {"help",    no_argument,       0, 'h'},
+               {"version", no_argument,       0, 'v'},
+               {0, 0, 0, 0}
+       };
+
+       while((c = getopt_long(argc, argv,
+                              "f:d:hav",
+                              long_options,
+                              &i_option_index)) != -1) {
+               switch(c) {
+               case 0:
+                       // If this option set a flag, do nothing.
+                       break;
+               case '?':
+                       // No such command.
+                       // getopt_long already printed an error message.
+                       return 0;
+               case 'f':
+                       b_load_from_file = true;
+                       s_file = optarg;
+                       break;
+
+               case 'd':
+                       b_load_from_dir = false;
+                       s_dir = optarg;
+                       break;
+
+               case 'h':
+                       printf("Api feature loader v." API_FEATURE_LOADER_VERSION "\n\n");
+                       printf("    Options:\n");
+                       printf("        -d,--dir=path        load api-features from the directory\n");
+                       printf("        -f,--file=file_name  load api-feature from the file\n");
+                       printf("        -h,--help            print this help\n");
+                       printf("        --verbose            verbose output\n");
+                       printf("        -v,--version         show applcation version\n");
+
+                       return 0;
+
+               case 'v':
+                       printf("Api feature loader v." API_FEATURE_LOADER_VERSION "\n");
+                       return 0;
+
+               default:
+                       break;
+               }
+       }
+
+       // Print unknown remaining command line arguments
+       if(optind < argc) {
+               printf("Unknown options: ");
+               while(optind < argc)
+                       printf("%s ", argv[optind++]);
+               putchar('\n');
+               return 0;
+       }
+
+
+       if(b_load_from_dir) load_from_dir(s_dir);
+
+       if(b_load_from_file) {
+               // TODO: Call the function that loads the permission from a file.
+       }
+
+       // By default we load from API_FEATURES_DIR
+       load_from_dir(API_FEATURES_DIR);
+
+       return 0;
+
+}
+
+
diff --git a/db/load-rules-db.sql b/db/load-rules-db.sql
new file mode 100644 (file)
index 0000000..27724ba
--- /dev/null
@@ -0,0 +1,11 @@
+.load librules-db-sql-udf.so
+.separator " "
+
+PRAGMA journal_mode = DELETE;
+
+.output "/opt/etc/smack/boot-rules.smack"
+
+SELECT subject, object, access_to_str(access)
+FROM   all_smack_binary_rules
+WHERE  all_smack_binary_rules.is_volatile = 0;
+
diff --git a/db/rules-db-data.sql b/db/rules-db-data.sql
new file mode 100644 (file)
index 0000000..9b4285b
--- /dev/null
@@ -0,0 +1,118 @@
+-- !!! CAUTION !!!
+-- Beware of updating!
+-- Remember that you might insert things to a filled database.
+
+
+.load librules-db-sql-udf.so
+PRAGMA foreign_keys = ON;
+
+BEGIN TRANSACTION;
+
+-- PERMISSION TYPES --------------------------------------------------------------------------------
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("ALL_APPS"); -- Automatically added to all apps.
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("WRT");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("OSP");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("EFL");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("WRT_partner");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("WRT_platform");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("OSP_partner");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("OSP_platform");
+
+-- APP PATH TYPES ----------------------------------------------------------------------------------
+INSERT OR IGNORE INTO app_path_type(name) VALUES("PRIVATE");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("GROUP_RW");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("PUBLIC_RO");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("SETTINGS_RW");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("ANY_LABEL");
+
+INSERT OR IGNORE INTO permission_view(name, type_name) VALUES
+               ("ALL_APPS",    "ALL_APPS"),
+               ("WRT",         "WRT"),
+               ("WRT_partner", "WRT_partner"),
+               ("WRT_platform","WRT_platform"),
+               ("OSP",         "OSP"),
+               ("OSP_partner", "OSP_partner"),
+               ("OSP_platform","OSP_platform"),
+               ("EFL",         "EFL");
+
+-- PUBLIC FOLDERS ----------------------------------------------------------------------------------
+-- PUBLIC_RO
+INSERT OR IGNORE INTO permission_app_path_type_rule_view(permission_name,
+                                                        permission_type_name,
+                                                        app_path_type_name,
+                                                        access,
+                                                        is_reverse) VALUES
+       ("ALL_APPS",    "ALL_APPS",     "PUBLIC_RO", "rx", 0);
+
+
+-- SETTINGS ----------------------------------------------------------------------------------------
+-- Permission name == TIZEN_PRIVILEGE_APPSETTING
+-- SETTINGS_RW
+INSERT OR IGNORE INTO permission_view(name, type_name) VALUES
+               ("org.tizen.privilege.appsetting", "WRT"),
+               ("org.tizen.privilege.appsetting", "OSP"),
+               ("org.tizen.privilege.appsetting", "EFL");
+
+INSERT OR IGNORE INTO permission_app_path_type_rule_view(permission_name,
+                                                        permission_type_name,
+                                                        app_path_type_name,
+                                                        access,
+                                                        is_reverse) VALUES
+       ("org.tizen.privilege.appsetting","WRT", "SETTINGS_RW", "rwx", 0),
+       ("org.tizen.privilege.appsetting","OSP", "SETTINGS_RW", "rwx", 0),
+       ("org.tizen.privilege.appsetting","EFL", "SETTINGS_RW", "rwx", 0);
+
+INSERT OR IGNORE INTO permission_permission_rule_view(permission_name,
+                                                     permission_type_name,
+                                                     target_permission_name,
+                                                     target_permission_type_name,
+                                                     access,
+                                                     is_reverse) VALUES
+       ("org.tizen.privilege.appsetting","WRT", "ALL_APPS", "ALL_APPS", "rx", 0),
+       ("org.tizen.privilege.appsetting","OSP", "ALL_APPS", "ALL_APPS", "rx", 0),
+       ("org.tizen.privilege.appsetting","EFL", "ALL_APPS", "ALL_APPS", "rx", 0);
+
+
+-- ANTIVIRUS ---------------------------------------------------------------------------------------
+-- Permission name == TIZEN_PRIVILEGE_ANTIVIRUS
+INSERT OR IGNORE INTO permission_view(name, type_name) VALUES
+               ("org.tizen.privilege.antivirus", "WRT"),
+               ("org.tizen.privilege.antivirus", "OSP"),
+               ("org.tizen.privilege.antivirus", "EFL");
+
+INSERT OR IGNORE INTO permission_permission_rule_view(permission_name,
+                                                     permission_type_name,
+                                                     target_permission_name,
+                                                     target_permission_type_name,
+                                                     access,
+                                                     is_reverse) VALUES
+       ("org.tizen.privilege.antivirus","WRT", "ALL_APPS", "ALL_APPS", "rwx", 0),
+       ("org.tizen.privilege.antivirus","OSP", "ALL_APPS", "ALL_APPS", "rwx", 0),
+       ("org.tizen.privilege.antivirus","EFL", "ALL_APPS", "ALL_APPS", "rwx", 0);
+
+INSERT OR IGNORE INTO permission_app_path_type_rule_view(permission_name,
+                                                        permission_type_name,
+                                                        app_path_type_name,
+                                                        access,
+                                                        is_reverse) VALUES
+       ("org.tizen.privilege.antivirus","WRT", "GROUP_RW",    "rwx", 0),
+       ("org.tizen.privilege.antivirus","OSP", "GROUP_RW",    "rwx", 0),
+       ("org.tizen.privilege.antivirus","EFL", "GROUP_RW",    "rwx", 0),
+       ("org.tizen.privilege.antivirus","WRT", "SETTINGS_RW", "rwx", 0),
+       ("org.tizen.privilege.antivirus","OSP", "SETTINGS_RW", "rwx", 0),
+       ("org.tizen.privilege.antivirus","EFL", "SETTINGS_RW", "rwx", 0),
+       ("org.tizen.privilege.antivirus","WRT", "PUBLIC_RO",   "rwx", 0),
+       ("org.tizen.privilege.antivirus","OSP", "PUBLIC_RO",   "rwx", 0),
+       ("org.tizen.privilege.antivirus","EFL", "PUBLIC_RO",   "rwx", 0),
+       ("org.tizen.privilege.antivirus","WRT", "ANY_LABEL",   "rwx", 0),
+       ("org.tizen.privilege.antivirus","OSP", "ANY_LABEL",   "rwx", 0),
+       ("org.tizen.privilege.antivirus","EFL", "ANY_LABEL",   "rwx", 0);
+
+
+-- Initial fill of all_smack_binary_rules table
+DELETE FROM all_smack_binary_rules;
+INSERT INTO all_smack_binary_rules
+SELECT      subject, object, access, is_volatile
+FROM        all_smack_binary_rules_view;
+
+COMMIT TRANSACTION;
\ No newline at end of file
diff --git a/db/rules-db-sql-udf.c b/db/rules-db-sql-udf.c
new file mode 100644 (file)
index 0000000..8ca9e30
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+* @file        rules-db-sql-udf.c
+* @author      Jan Olszak (j.olszak@samsung.com)
+* @version     1.0
+* @brief       This file contains implementation of a SQLite module used in rules-db.
+*/
+
+#include <sqlite3ext.h>
+
+#define UNUSED __attribute__((unused))
+
+// Access rights:
+#define RDB_ACCESS_READ       1
+#define RDB_ACCESS_WRITE      2
+#define RDB_ACCESS_EXEC       4
+#define RDB_ACCESS_APPEND     8
+#define RDB_ACCESS_TRANSMUTE  16
+#define RDB_ACCESS_LOCK       32
+#define RDB_ACCESS_FULL (RDB_ACCESS_READ      |  \
+                        RDB_ACCESS_WRITE     |  \
+                        RDB_ACCESS_EXEC      |  \
+                        RDB_ACCESS_APPEND    |  \
+                        RDB_ACCESS_TRANSMUTE |  \
+                        RDB_ACCESS_LOCK)
+
+
+SQLITE_EXTENSION_INIT1
+
+/**
+* Convert access to a string representation.
+*
+* @ingroup SQLite User Defined Functions
+*
+*/
+static void access_to_str(sqlite3_context *context,
+                         int argc UNUSED,
+                         sqlite3_value **argv)
+{
+       int access = sqlite3_value_int(argv[0]);
+       int i = 0;
+       char string[7];
+       if (access & RDB_ACCESS_READ)
+               string[i++] = 'r';
+       if (access & RDB_ACCESS_WRITE)
+               string[i++] = 'w';
+       if (access & RDB_ACCESS_EXEC)
+               string[i++] = 'x';
+       if (access & RDB_ACCESS_APPEND)
+               string[i++] = 'a';
+       if (access & RDB_ACCESS_TRANSMUTE)
+               string[i++] = 't';
+       if (access & RDB_ACCESS_LOCK)
+               string[i++] = 'l';
+       string[i] = '\0';
+       sqlite3_result_text(context, string, -1, SQLITE_TRANSIENT);
+}
+
+
+/**
+* Convert a string to access representation.
+* Takes ONE input string like "rwxat" and converts it into access representation.
+* The order of rwxat letters does not matter.
+*
+* @ingroup SQLite User Defined Functions
+*
+*/
+static void str_to_access(sqlite3_context *context,
+                         int argc UNUSED,
+                         sqlite3_value **argv)
+{
+       const unsigned char *string = sqlite3_value_text(argv[0]);
+       int access = 0;
+       int i;
+
+       if (!string) {
+               sqlite3_result_null(context);
+               return;
+       }
+
+       for (i = 0; string[i] != '\0'; ++i) {
+               switch (string[i]) {
+               case 'R':
+               case 'r': access |= RDB_ACCESS_READ; break;
+
+               case 'W':
+               case 'w': access |= RDB_ACCESS_WRITE; break;
+
+               case 'X':
+               case 'x': access |= RDB_ACCESS_EXEC; break;
+
+               case 'A':
+               case 'a': access |= RDB_ACCESS_APPEND; break;
+
+               case 'T':
+               case 't': access |= RDB_ACCESS_TRANSMUTE; break;
+
+               case 'L':
+               case 'l': access |= RDB_ACCESS_LOCK; break;
+
+               case '-': break;
+
+               default: // He got an unknown permission
+                       sqlite3_result_null(context);
+                       return;
+               }
+       }
+       sqlite3_result_int(context, access);
+}
+
+
+/**
+* An bitwise or aggregating function. We assume, that all arguments are ints.
+*
+* @ingroup SQLite User Defined Functions
+*
+* @return bitwise or of all given values.
+*/
+static void bitwise_or_step(sqlite3_context *context,
+                           int argc UNUSED,
+                           sqlite3_value **argv)
+{
+       int *result_buffer = (int *)sqlite3_aggregate_context(context, sizeof(int));
+       *result_buffer |= sqlite3_value_int(argv[0]);
+}
+
+
+void bitwise_or_final(sqlite3_context *context)
+{
+       int *result_buffer = (int *)sqlite3_aggregate_context(context, sizeof(int));
+       sqlite3_result_int(context, *result_buffer );
+}
+
+/**
+* Entry point for SQLite.
+*/
+__attribute__((visibility("default")))
+int sqlite3_extension_init( sqlite3 *p_db,
+                           char **ps_err_msg UNUSED,
+                           const sqlite3_api_routines *p_api)
+{
+       SQLITE_EXTENSION_INIT2(p_api)
+       sqlite3_create_function(p_db, "access_to_str", 1, SQLITE_ANY, 0, access_to_str, 0, 0);
+       sqlite3_create_function(p_db, "str_to_access", 1, SQLITE_ANY, 0, str_to_access, 0, 0);
+       sqlite3_create_function(p_db, "bitwise_or", 1, SQLITE_ANY, 0, 0,
+                               bitwise_or_step, bitwise_or_final);
+
+       return 0;
+}
\ No newline at end of file
diff --git a/db/rules-db.sql b/db/rules-db.sql
new file mode 100644 (file)
index 0000000..71bb39c
--- /dev/null
@@ -0,0 +1,746 @@
+-- !!! CAUTION !!!
+-- 1. Beware of updating schema!
+--    We can drop views and triggers,
+--    but we should copy data from tables
+--    according to the schema version!
+-- 2. If you change definition of tables
+--    update the schema counter at the bottom!!
+
+-- TODO: Use "USING" in joins whenever possible
+
+.load librules-db-sql-udf.so
+PRAGMA foreign_keys = ON;
+
+BEGIN EXCLUSIVE TRANSACTION;
+
+-- PRAGMA cache_size = 2000;
+
+CREATE TABLE IF NOT EXISTS  app (
+    app_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+    label_id INTEGER NOT NULL,
+    UNIQUE(label_id),
+
+    FOREIGN KEY(label_id) REFERENCES label(label_id)
+);
+CREATE INDEX IF NOT EXISTS app_index ON app(app_id, label_id);
+
+
+CREATE TABLE IF NOT EXISTS app_permission (
+    app_id INTEGER NOT NULL,
+    permission_id INTEGER NOT NULL,
+    is_volatile INTEGER NOT NULL  DEFAULT 0,
+    is_enabled INTEGER NOT NULL  DEFAULT 1,
+
+    PRIMARY KEY(app_id, permission_id),
+
+    FOREIGN KEY(app_id) REFERENCES app(app_id),
+    FOREIGN KEY(permission_id) REFERENCES permission(permission_id)
+);
+
+CREATE TABLE IF NOT EXISTS app_path (
+    app_id INTEGER NOT NULL,
+    path TEXT NOT NULL,
+    label_id INTEGER NOT NULL,
+    access INTEGER NOT NULL,
+    app_path_type_id INTEGER NOT NULL ,
+
+    -- TODO:
+    -- Desired behavior should be:
+    -- allow one app to register a path only once (already implemented by the primary key)
+    -- prohibit two apps registering the same path with different labels (probably cannot be done by SQL constraints)
+    -- allow two apps to register the same path if label is also same
+
+    PRIMARY KEY (app_id, path),
+
+    FOREIGN KEY(app_id) REFERENCES app(app_id),
+    FOREIGN KEY(label_id) REFERENCES label(label_id),
+    FOREIGN KEY(app_path_type_id) REFERENCES app_path_type(app_path_type_id)
+);
+
+CREATE TABLE IF NOT EXISTS app_path_type (
+    app_path_type_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+    name TEXT NOT NULL ,
+
+    UNIQUE (name)
+);
+-- CREATE INDEX IF NOT EXISTS app_path_type_index ON app_path_type(app_path_type_id, name);
+
+
+CREATE TABLE IF NOT EXISTS permission_permission_rule (
+    permission_id INTEGER NOT NULL,
+    target_permission_id INTEGER NOT NULL,
+    access INTEGER NOT NULL DEFAULT 0,
+    is_reverse INTEGER NOT NULL  DEFAULT 0,
+
+    PRIMARY KEY (permission_id, target_permission_id, is_reverse),
+
+    FOREIGN KEY(permission_id) REFERENCES permission(permission_id),
+    FOREIGN KEY(target_permission_id) REFERENCES permission(permission_id)
+);
+
+CREATE TABLE IF NOT EXISTS permission_label_rule (
+    permission_id INTEGER NOT NULL,
+    label_id INTEGER NOT NULL,
+    access INTEGER NOT NULL DEFAULT 0,
+    is_reverse INTEGER NOT NULL  DEFAULT 0,
+
+    PRIMARY KEY (permission_id,label_id, is_reverse),
+
+    FOREIGN KEY(permission_id) REFERENCES permission(permission_id),
+    FOREIGN KEY(label_id) REFERENCES label(label_id)
+);
+
+CREATE TABLE IF NOT EXISTS permission_app_path_type_rule (
+    permission_id INTEGER NOT NULL,
+    app_path_type_id INTEGER NOT NULL,
+    access INTEGER NOT NULL DEFAULT 0,
+    is_reverse INTEGER NOT NULL  DEFAULT 0,
+
+    PRIMARY KEY (permission_id, app_path_type_id, is_reverse),
+
+    FOREIGN KEY(permission_id) REFERENCES permission(permission_id),
+    FOREIGN KEY(app_path_type_id) REFERENCES app_path_type(app_path_type_id)
+);
+
+
+CREATE TABLE IF NOT EXISTS label (
+    label_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+    name TEXT NOT NULL,
+
+    UNIQUE(name)
+);
+
+CREATE TABLE IF NOT EXISTS permission_type (
+    permission_type_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+    type_name TEXT NOT NULL,
+
+    UNIQUE(type_name)
+);
+
+CREATE TABLE IF NOT EXISTS permission (
+    permission_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT ,
+    permission_type_id INTEGER NOT NULL,
+    name TEXT NOT NULL,
+
+    UNIQUE (name, permission_type_id),
+
+    FOREIGN KEY(permission_type_id) REFERENCES permission_type(permission_type_id)
+);
+
+
+CREATE TABLE IF NOT EXISTS all_smack_binary_rules(
+    subject TEXT NOT NULL,
+    object  TEXT NOT NULL,
+    access  INTEGER NOT NULL,
+    is_volatile INTEGER NOT NULL
+);
+
+-- TEMPORARY TABLES ------------------------------------------------------------
+-- Definitions are repeated in code.
+
+CREATE TEMPORARY TABLE history_smack_rule(
+    subject TEXT NOT NULL,
+    object  TEXT NOT NULL,
+    access  INTEGER NOT NULL
+);
+
+
+CREATE TEMPORARY TABLE modified_label(
+   name TEXT NOT NULL,
+   UNIQUE (name)
+);
+
+
+CREATE TEMPORARY TABLE all_smack_binary_rules_modified(
+    subject TEXT NOT NULL,
+    object  TEXT NOT NULL,
+    access  INTEGER NOT NULL
+);
+
+
+CREATE TEMPORARY TABLE history_smack_rule_modified(
+    subject TEXT NOT NULL,
+    object  TEXT NOT NULL,
+    access  INTEGER NOT NULL
+);
+
+
+-- PERMISSION VIEW -------------------------------------------------------------
+DROP VIEW IF EXISTS permission_view;
+CREATE VIEW permission_view AS
+SELECT      permission.permission_id, permission.name, permission_type.type_name
+FROM        permission
+INNER JOIN  permission_type
+ON          permission.permission_type_id = permission_type.permission_type_id;
+
+DROP TRIGGER IF EXISTS permission_view_insert_trigger;
+CREATE TRIGGER permission_view_insert_trigger
+INSTEAD OF INSERT ON permission_view
+BEGIN
+    INSERT OR IGNORE INTO permission(name,permission_type_id)
+    SELECT                NEW.name, permission_type.permission_type_id
+    FROM                  permission_type
+    WHERE                 permission_type.type_name = NEW.type_name;
+
+    -- TODO:
+    -- Once the files provide other types of rules,
+    -- this trigger will have to delete also from permission_path_type_rule
+    -- and maybe permission_permission_rule
+    DELETE FROM permission_label_rule_view
+    WHERE       permission_label_rule_view.permission_name = NEW.name AND
+                permission_label_rule_view.permission_type_name = NEW.type_name;
+END;
+
+-- PERMISSION TO LABEL RULE VIEW -----------------------------------------------
+DROP VIEW IF EXISTS permission_label_rule_view;
+CREATE VIEW permission_label_rule_view AS
+SELECT
+        permission_view.permission_id       AS permission_id,
+        permission_view.name                AS permission_name,
+        permission_view.type_name           AS permission_type_name,
+        label.name                              AS label_name,
+        permission_label_rule.access            AS access,
+        permission_label_rule.is_reverse        AS is_reverse
+FROM    permission_label_rule
+LEFT JOIN permission_view
+ON permission_label_rule.permission_id = permission_view.permission_id
+
+LEFT JOIN label
+ON permission_label_rule.label_id = label.label_id;
+
+
+-- Preferred way of adding permission rules would be to use these ONE, multi-row
+-- insert statement, with one check of a condition
+-- that there is such permission id. It's impossible to make those inserts in C,
+-- so the programmer has to secure, that there is a permission with a given id.
+-- (Check it and insert in the same transaction)
+-- In runtime we accept ONLY inserts with label.
+-- All other kinds of permissions are filled during the database creation.
+DROP TRIGGER IF EXISTS permission_label_rule_view_insert_trigger;
+CREATE TRIGGER permission_label_rule_view_insert_trigger
+INSTEAD OF INSERT ON permission_label_rule_view
+BEGIN
+    -- Adding api features adds a label it it's not present.
+    INSERT OR IGNORE INTO label(name) VALUES (NEW.label_name);
+
+    INSERT INTO permission_label_rule(permission_id, label_id, access, is_reverse)
+    SELECT      NEW.permission_id,
+                label.label_id,
+                str_to_access(NEW.access),
+                NEW.is_reverse
+    FROM        label
+    WHERE       label.name = NEW.label_name;
+END;
+
+
+-- TODO: Potential problem - undeleted labels.
+DROP TRIGGER IF EXISTS permission_label_rule_view_delete_trigger;
+CREATE TRIGGER permission_label_rule_view_delete_trigger
+INSTEAD OF DELETE ON permission_label_rule_view
+BEGIN
+        DELETE FROM permission_label_rule
+        WHERE permission_label_rule.permission_id IN (SELECT    permission_view.permission_id
+                                                      FROM      permission_view
+                                                      WHERE     permission_view.name = OLD.permission_name AND
+                                                                permission_view.type_name = OLD.permission_type_name);
+END;
+
+
+-- PERMISSION TO APP PATH TYPE RULE VIEW ---------------------------------------
+DROP VIEW IF EXISTS permission_app_path_type_rule_view;
+CREATE VIEW permission_app_path_type_rule_view AS
+SELECT
+        permission_view.permission_id       AS permission_id,
+        permission_view.name                AS permission_name,
+        permission_view.type_name           AS permission_type_name,
+        app_path_type.name                      AS app_path_type_name,
+        permission_app_path_type_rule.access       AS access,
+        permission_app_path_type_rule.is_reverse   AS is_reverse
+FROM    permission_app_path_type_rule
+LEFT JOIN permission_view
+ON permission_app_path_type_rule.permission_id = permission_view.permission_id
+LEFT JOIN app_path_type
+ON permission_app_path_type_rule.app_path_type_id = app_path_type.app_path_type_id;
+
+DROP TRIGGER IF EXISTS permission_app_path_type_rule_view_insert_trigger;
+CREATE TRIGGER permission_app_path_type_rule_view_insert_trigger
+INSTEAD OF INSERT
+ON permission_app_path_type_rule_view
+BEGIN
+    INSERT INTO permission_app_path_type_rule(permission_id,
+                                              app_path_type_id,
+                                              access,
+                                              is_reverse)
+    SELECT      permission_view.permission_id,
+                app_path_type.app_path_type_id,
+                str_to_access(NEW.access),
+                NEW.is_reverse
+    FROM        permission_view, app_path_type
+    WHERE       permission_view.name = NEW.permission_name AND
+                permission_view.type_name = NEW.permission_type_name AND
+                app_path_type.name = NEW.app_path_type_name;
+END;
+
+
+-- PERMISSION TO PERMISSION RULE VIEW ------------------------------------------
+DROP VIEW IF EXISTS permission_permission_rule_view;
+CREATE VIEW permission_permission_rule_view AS
+SELECT
+        tmp_permission_view.permission_id       AS permission_id,
+        tmp_permission_view.name                AS permission_name,
+        tmp_permission_view.type_name           AS permission_type_name,
+        tmp_target_permission_view.name         AS target_permission_name,
+        tmp_target_permission_view.type_name    AS target_permission_type_name,
+        permission_permission_rule.access       AS access,
+        permission_permission_rule.is_reverse   AS is_reverse
+FROM    permission_permission_rule
+LEFT JOIN permission_view AS tmp_permission_view
+ON permission_permission_rule.permission_id = tmp_permission_view.permission_id
+LEFT JOIN permission_view AS tmp_target_permission_view
+ON permission_permission_rule.target_permission_id = tmp_target_permission_view.permission_id;
+
+
+-- Trigger for manual addition of rules.
+DROP TRIGGER IF EXISTS permission_permission_rule_view_insert_trigger;
+CREATE TRIGGER  permission_permission_rule_view_insert_trigger
+INSTEAD OF INSERT ON  permission_permission_rule_view
+BEGIN
+    INSERT INTO permission_permission_rule(permission_id,
+                                           target_permission_id,
+                                           access,
+                                           is_reverse)
+    SELECT  tmp_permission_view.permission_id,
+            tmp_target_permission_view.permission_id,
+            str_to_access(NEW.access),
+            NEW.is_reverse
+    FROM    permission_view AS tmp_permission_view,
+            permission_view AS tmp_target_permission_view
+    WHERE   tmp_permission_view.name = NEW.permission_name AND
+            tmp_permission_view.type_name = NEW.permission_type_name AND
+            tmp_target_permission_view.name = NEW.target_permission_name AND
+            tmp_target_permission_view.type_name = NEW.target_permission_type_name;
+END;
+
+
+
+-- LABEL VIEW ------------------------------------------------------------------
+-- There are no INSTEAD OF triggers on regular tables.
+-- We use a view to delete unreferenced labels:
+DROP VIEW IF EXISTS label_view;
+CREATE VIEW label_view AS SELECT * FROM label;
+
+DROP TRIGGER IF EXISTS label_view_delete_trigger;
+CREATE TRIGGER label_view_delete_trigger
+INSTEAD OF DELETE ON label_view
+WHEN    OLD.label_id NOT IN (SELECT app.label_id
+                             FROM app) AND
+        OLD.label_id NOT IN (SELECT permission_label_rule.label_id
+                             FROM permission_label_rule) AND
+        OLD.label_id NOT IN (SELECT app_path.label_id
+                             FROM app_path)
+BEGIN
+        DELETE FROM label WHERE label.name = OLD.name;
+END;
+
+
+-- APPLICATION VIEW ------------------------------------------------------------
+DROP VIEW IF EXISTS application_view;
+CREATE VIEW application_view AS
+SELECT      app.app_id, label.name
+FROM        label
+INNER JOIN  app
+ON          label.label_id = app.label_id ;
+
+DROP TRIGGER IF EXISTS application_view_insert_trigger;
+CREATE TRIGGER application_view_insert_trigger
+INSTEAD OF INSERT ON application_view
+BEGIN
+    INSERT OR IGNORE INTO label(name) VALUES (NEW.name);
+    INSERT INTO app(label_id) SELECT label_id FROM label WHERE label.name = NEW.name;
+    INSERT INTO app_permission_view(app_id,
+                                    name,
+                                    type_name,
+                                    is_volatile,
+                                    is_enabled)
+                VALUES(last_insert_rowid(),
+                        "ALL_APPS",
+                        "ALL_APPS",
+                        0,1);
+END;
+
+
+DROP TRIGGER IF EXISTS application_view_delete_trigger;
+CREATE TRIGGER application_view_delete_trigger
+INSTEAD OF DELETE ON application_view
+BEGIN
+        -- Delete rules that correspond to app's paths:
+        DELETE FROM permission_label_rule
+        WHERE       permission_label_rule.label_id IN
+                   (SELECT     app_path.label_id
+                    FROM       app_path
+                    INNER JOIN application_view
+                               ON app_path.app_id = application_view.app_id
+                    WHERE      application_view.name = OLD.name);
+
+        -- Delete path
+        DELETE FROM path_view
+        WHERE path_view.owner_app_label_name=OLD.name;
+
+        -- Delete apps permissions:
+        DELETE FROM app_permission
+        WHERE       app_permission.app_id
+                    IN (SELECT application_view.app_id
+                        FROM   application_view
+                        WHERE  application_view.name = OLD.name
+                        LIMIT  1);
+
+        -- Delete application
+        DELETE FROM app
+        WHERE app.app_id IN (SELECT application_view.app_id
+                             FROM   application_view
+                             WHERE  application_view.name = OLD.name
+                             LIMIT  1);
+
+        -- Delete label
+        DELETE FROM label_view
+        WHERE label_view.name = OLD.name;
+END;
+
+
+-- PATH VIEW -------------------------------------------------------------------
+DROP VIEW IF EXISTS path_view;
+CREATE VIEW path_view AS
+SELECT  application_view.name   AS owner_app_label_name,
+        app_path.path           AS path,
+        label.name              AS path_label_name,
+        app_path.access         AS access,
+        app_path_type.name      AS path_type_name
+
+FROM    app_path
+LEFT JOIN app_path_type     USING (app_path_type_id)
+LEFT JOIN application_view  USING (app_id)
+LEFT JOIN label             USING (label_id);
+
+
+-- For an existing application we add a path.
+DROP TRIGGER IF EXISTS path_view_insert_trigger;
+CREATE TRIGGER path_view_insert_trigger
+INSTEAD OF INSERT ON path_view
+WHEN NEW.owner_app_label_name IN (SELECT application_view.name
+                                  FROM application_view)
+BEGIN
+    INSERT OR IGNORE INTO label(name) VALUES (NEW.path_label_name);
+
+    INSERT INTO app_path(app_id, path, label_id, access, app_path_type_id)
+        SELECT  application_view.app_id,
+                NEW.path,
+                label.label_id,
+                str_to_access(NEW.access),
+                app_path_type.app_path_type_id
+
+        FROM    application_view, app_path_type, label
+        WHERE   application_view.name = NEW.owner_app_label_name AND
+                app_path_type.name = NEW.path_type_name AND
+                label.name = NEW.path_label_name;
+
+END;
+
+DROP TRIGGER IF EXISTS path_view_delete_trigger;
+CREATE TRIGGER path_view_delete_trigger
+INSTEAD OF DELETE ON path_view
+BEGIN
+        DELETE FROM app_path
+        WHERE app_path.app_id IN (SELECT  app.app_id
+                                  FROM    app, label
+                                  WHERE   label.name = OLD.owner_app_label_name AND
+                                          app.label_id = label.label_id);
+
+        DELETE FROM label_view WHERE label_view.name = OLD.path_label_name;
+END;
+
+-- APP PERMISSION LIST VIEW ----------------------------------------------------
+-- Used in check_app_permission_internal to check if permissions are present
+-- TODO: Check if SQLite optimizer doesn't change app_permission_view to the same code.
+DROP VIEW IF EXISTS app_permission_list_view;
+CREATE VIEW app_permission_list_view AS
+SELECT      app_permission.app_id AS app_id,
+            app_permission.permission_id AS permission_id,
+            permission_view.name AS permission_name,
+            permission_view.type_name AS permission_type_name,
+            app_permission.is_volatile AS is_volatile,
+            app_permission.is_enabled AS is_enabled
+FROM        app_permission
+INNER JOIN  permission_view
+ON permission_view.permission_id =  app_permission.permission_id;
+
+
+
+-- APP PERMISSION VIEW ---------------------------------------------------------
+DROP VIEW IF EXISTS app_permission_view;
+CREATE VIEW app_permission_view AS
+SELECT      application_view.app_id,
+            application_view.name  AS app_name,
+            permission_view.permission_id,
+            permission_view.name,
+            permission_view.type_name,
+            app_permission.is_volatile,
+            app_permission.is_enabled
+FROM        app_permission
+INNER JOIN  application_view
+ON application_view.app_id = app_permission.app_id
+INNER JOIN  permission_view
+ON permission_view.permission_id =  app_permission.permission_id;
+
+
+DROP TRIGGER IF EXISTS app_permission_view_insert_trigger;
+CREATE TRIGGER app_permission_view_insert_trigger
+INSTEAD OF INSERT ON app_permission_view
+BEGIN
+    INSERT INTO app_permission(app_id, permission_id, is_volatile, is_enabled)
+    SELECT      NEW.app_id,
+                permission_view.permission_id,
+                NEW.is_volatile,
+                NEW.is_enabled
+    FROM        permission_view
+    WHERE       permission_view.name = NEW.name AND
+                permission_view.type_name = NEW.type_name;
+END;
+
+
+
+
+-- It's forbidden do change permission from not volatile to volatile.
+-- We have to check it before inserting anything.
+-- Used in updating permissions
+DROP TRIGGER IF EXISTS app_permission_view_update_trigger;
+CREATE TRIGGER app_permission_view_update_trigger
+INSTEAD OF UPDATE ON app_permission_view
+BEGIN
+    UPDATE OR IGNORE app_permission
+    SET              is_enabled = NEW.is_enabled
+    WHERE            app_permission.app_id = OLD.app_id AND
+                     app_permission.permission_id
+                     IN (SELECT  permission_view.permission_id
+                         FROM    permission_view
+                         WHERE   permission_view.name = OLD.name AND
+                                 permission_view.type_name = OLD.type_name
+                         LIMIT 1);
+END;
+
+
+DROP TRIGGER IF EXISTS app_permission_view_delete_trigger;
+CREATE TRIGGER app_permission_view_delete_trigger
+INSTEAD OF DELETE ON app_permission_view
+BEGIN
+    DELETE FROM app_permission
+    WHERE       app_permission.app_id
+                IN (SELECT application_view.app_id
+                    FROM   application_view
+                    WHERE  application_view.name = OLD.app_name
+                    LIMIT  1)
+                AND
+                app_permission.permission_id NOT IN (SELECT permission_view.permission_id
+                                                     FROM   permission_view
+                                                     WHERE  permission_view.name = "ALL_APPS" AND
+                                                            permission_view.type_name = "ALL_APPS");
+END;
+
+-- APP PERMISSION VOLATILE VIEW ------------------------------------------------
+DROP VIEW IF EXISTS app_permission_volatile_view;
+CREATE VIEW app_permission_volatile_view AS
+SELECT      *
+FROM        app_permission_view
+WHERE       app_permission_view.is_volatile = 1;
+
+
+DROP TRIGGER IF EXISTS app_permission_volatile_view_delete_trigger;
+CREATE TRIGGER app_permission_volatile_view_delete_trigger
+INSTEAD OF DELETE ON app_permission_volatile_view
+BEGIN
+    DELETE FROM app_permission
+    WHERE       app_permission.is_volatile = 1 AND
+                app_permission.app_id
+                IN (SELECT application_view.app_id
+                    FROM   application_view
+                    WHERE  application_view.name = OLD.app_name
+                    LIMIT  1);
+END;
+
+
+-- APPLICATIONS PERMISSIONS ID -------------------------------------------------
+-- All applications and their permissions
+DROP VIEW IF EXISTS app_label_with_permission_view;
+CREATE VIEW app_label_with_permission_view AS
+SELECT      app_permission.permission_id,
+            application_view.name,
+            application_view.app_id,
+            app_permission.is_volatile
+FROM        app_permission
+INNER JOIN  application_view
+            ON  application_view.app_id = app_permission.app_id  AND
+                app_permission.is_enabled = 1;
+
+
+
+-- PERMISSION TO PERMISSION RULE VIEW ------------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_permission_permission_rule_view;
+CREATE VIEW ltl_permission_permission_rule_view AS
+SELECT          (CASE WHEN is_reverse = 0 THEN app1.name ELSE app2.name END) AS subject,
+                (CASE WHEN is_reverse = 1 THEN app1.name ELSE app2.name END) AS object,
+                p.access,
+                app1.is_volatile OR app2.is_volatile AS is_volatile
+FROM            permission_permission_rule AS p
+INNER JOIN      app_label_with_permission_view AS app1
+                ON app1.permission_id = p.permission_id
+INNER JOIN      app_label_with_permission_view AS app2
+                ON app2.permission_id = p.target_permission_id AND
+                app1.app_id != app2.app_id;
+
+-- PERMISSION TO LABEL RULE VIEW -----------------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_permission_label_rule_view;
+CREATE VIEW ltl_permission_label_rule_view AS
+SELECT          (CASE WHEN is_reverse = 0 THEN app.name ELSE label.name END) AS subject,
+                (CASE WHEN is_reverse = 1 THEN app.name ELSE label.name END) AS object,
+                p.access,
+                app.is_volatile
+FROM            permission_label_rule AS p
+INNER JOIN      app_label_with_permission_view AS app
+                ON app.permission_id = p.permission_id
+INNER JOIN      label
+                ON label.label_id = p.label_id AND
+                app.name != label.name;
+
+
+
+-- PERMISSION TO PATH TYPE RULE VIEW -------------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_permission_app_path_type_rule_view;
+CREATE VIEW ltl_permission_app_path_type_rule_view AS
+SELECT          (CASE WHEN is_reverse = 0 THEN app.name ELSE label.name END) AS subject,
+                (CASE WHEN is_reverse = 1 THEN app.name ELSE label.name END) AS object,
+                p.access,
+                app.is_volatile
+FROM            permission_app_path_type_rule AS p
+INNER JOIN      app_label_with_permission_view AS app
+                ON app.permission_id = p.permission_id
+INNER JOIN      app_path
+                ON app_path.app_path_type_id = p.app_path_type_id
+INNER JOIN      label
+                ON label.label_id = app_path.label_id AND
+                app.name != label.name;
+
+
+-- PERMISSION TO APPLICATION'S OWN PATHS ---------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_app_path_view;
+CREATE VIEW ltl_app_path_view AS
+SELECT      application_view.name   AS subject,
+            label.name              AS object,
+            app_path.access         AS access
+FROM        app_path
+INNER JOIN  application_view ON application_view.app_id = app_path.app_id
+INNER JOIN  label            ON label.label_id = app_path.label_id;
+
+
+-- SMACK RULES VIEWS -----------------------------------------------------------
+DROP VIEW IF EXISTS all_smack_binary_rules_view;
+CREATE VIEW all_smack_binary_rules_view AS
+SELECT  subject,
+       object,
+       bitwise_or(access) AS access,
+       MIN(is_volatile) AS is_volatile
+FROM   (SELECT subject, object, access, is_volatile
+        FROM   ltl_permission_permission_rule_view
+        UNION ALL
+        SELECT subject, object, access, is_volatile
+        FROM   ltl_permission_label_rule_view
+        UNION ALL
+        SELECT subject, object, access, is_volatile
+        FROM   ltl_permission_app_path_type_rule_view
+        UNION ALL
+        SELECT subject, object, access, 0
+        FROM   ltl_app_path_view
+       )
+GROUP BY subject, object
+ORDER BY subject, object ASC;
+
+-- ALL INSERTED DATA VIEW ------------------------------------------------------
+-- This view is used to clear the database from inserted rules.
+-- We loose all information about installed applications
+-- and folders.
+DROP VIEW IF EXISTS all_inserted_data;
+CREATE VIEW all_inserted_data AS
+SELECT      *
+FROM        label;
+
+DROP TRIGGER IF EXISTS all_inserted_data_delete_trigger;
+CREATE TRIGGER all_inserted_data_delete_trigger INSTEAD OF
+DELETE ON all_inserted_data
+BEGIN
+    DELETE FROM permission_label_rule;
+    DELETE FROM permission_permission_rule;
+    DELETE FROM permission_app_path_type_rule;
+
+    DELETE FROM app_permission;
+
+    DELETE FROM permission;
+    DELETE FROM permission_type;
+
+    DELETE FROM app_path;
+    DELETE FROM app_path_type;
+    DELETE FROM app;
+
+    DELETE FROM label;
+END;
+
+
+
+-- SMACK RULES MODIFICATIONS VIEW ----------------------------------------------
+-- This definition is repeated during opening a connection with the database.
+-- Used to get all smack rules, even volatile.
+-- Ensure it's the same!
+CREATE TEMPORARY VIEW modified_smack_rules AS
+SELECT  subject, object,
+        access_to_str(access_add) AS access_add,
+        access_to_str(access_del) AS access_del
+FROM    (
+        SELECT     subject, object,
+                   s1.access & ~s2.access AS access_add,
+                   s2.access & ~s1.access AS access_del
+        FROM       all_smack_binary_rules AS s1
+        INNER JOIN history_smack_rule AS s2
+                   USING (subject, object)
+        WHERE      s1.access != s2.access
+
+        UNION
+
+        SELECT     subject, object,
+                   s1.access AS access_add,
+                   0 AS access_del
+        FROM       all_smack_binary_rules AS s1
+        LEFT JOIN  history_smack_rule s2
+                   USING (subject, object)
+        WHERE      s2.subject IS NULL AND
+                   s2.object  IS NULL
+
+        UNION
+
+        SELECT     subject, object,
+                   0 AS access_add,
+                   s1.access AS access_del
+        FROM       history_smack_rule s1
+        LEFT JOIN  all_smack_binary_rules AS s2
+                   USING (subject, object)
+        WHERE      s2.subject IS NULL AND
+                   s2.object  IS NULL
+        )
+ORDER BY subject, object ASC;
+
+
+-- Update here!
+PRAGMA schema_version = 1;
+
+COMMIT TRANSACTION;
+
diff --git a/db/rules-db.xml b/db/rules-db.xml
new file mode 100644 (file)
index 0000000..f739e28
--- /dev/null
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- SQL XML created by WWW SQL Designer, http://code.google.com/p/wwwsqldesigner/ -->
+<!-- Active URL: https://mcdsrvbld02.digital.local/wwwsqldesigner/ -->
+<sql>
+<datatypes db="sqlite">
+    <group label="Numeric" color="rgb(238,238,170)">
+        <type label="TINYINT" length="0" sql="TINYINT" quote=""/>
+        <type label="SMALLINT" length="0" sql="SMALLINT" quote=""/>
+        <type label="MEDIUMINT" length="0" sql="MEDIUMINT" quote=""/>
+        <type label="INT" length="0" sql="INT" quote=""/>
+        <type label="Integer" length="0" sql="INTEGER" quote=""/>
+        <type label="BIGINT" length="0" sql="BIGINT" quote=""/>
+        <type label="Decimal" length="1" sql="DECIMAL" re="DEC" quote=""/>
+        <type label="Single precision" length="0" sql="FLOAT" quote=""/>
+        <type label="Double precision" length="0" sql="DOUBLE" re="DOUBLE" quote=""/>
+    </group>
+
+    <group label="Character" color="rgb(255,200,200)">
+        <type label="Char" length="1" sql="CHAR" quote="'"/>
+        <type label="Varchar" length="1" sql="VARCHAR" quote="'"/>
+        <type label="Text" length="0" sql="MEDIUMTEXT" re="TEXT" quote="'"/>
+        <type label="Binary" length="1" sql="BINARY" quote="'"/>
+        <type label="Varbinary" length="1" sql="VARBINARY" quote="'"/>
+        <type label="BLOB" length="0" sql="BLOB" re="BLOB" quote="'"/>
+    </group>
+
+    <group label="Date &amp; Time" color="rgb(200,255,200)">
+        <type label="Date" length="0" sql="DATE" quote="'"/>
+        <type label="Time" length="0" sql="TIME" quote="'"/>
+        <type label="Datetime" length="0" sql="DATETIME" quote="'"/>
+        <type label="Year" length="0" sql="YEAR" quote=""/>
+        <type label="Timestamp" length="0" sql="TIMESTAMP" quote="'"/>
+    </group>
+
+    <group label="Miscellaneous" color="rgb(200,200,255)">
+        <type label="ENUM" length="1" sql="ENUM" quote=""/>
+        <type label="SET" length="1" sql="SET" quote=""/>
+        <type label="Bit" length="0" sql="bit" quote=""/>
+    </group>
+</datatypes><table x="31" y="298" name="app">
+<row name="app_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="app_permission" row="app_id" />
+<relation table="app_path" row="app_id" />
+</row>
+<row name="label_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>app_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>label_id</part>
+</key>
+</table>
+<table x="241" y="43" name="app_permission">
+<row name="app_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="permission_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="is_volatile" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+<default>0</default></row>
+<row name="is_enabled" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+<default>1</default></row>
+<key type="PRIMARY" name="">
+<part>app_id</part>
+<part>permission_id</part>
+</key>
+</table>
+<table x="215" y="490" name="app_path">
+<row name="app_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="path" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<row name="label_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+</row>
+<row name="app_path_type_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>app_id</part>
+<part>path</part>
+</key>
+</table>
+<table x="450" y="577" name="app_path_type">
+<row name="app_path_type_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="app_path" row="app_path_type_id" />
+<relation table="permission_app_path_type_rule" row="app_path_type_id" />
+</row>
+<row name="name" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>app_path_type_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>name</part>
+</key>
+</table>
+<table x="472" y="457" name="label">
+<row name="label_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="app" row="label_id" />
+<relation table="app_path" row="label_id" />
+<relation table="permission_label_rule" row="label_id" />
+</row>
+<row name="name" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>label_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>name</part>
+</key>
+</table>
+<table x="510" y="182" name="permission_type">
+<row name="permission_type_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="permission" row="permission_type_id" />
+</row>
+<row name="type_name" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>permission_type_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>type_name</part>
+</key>
+</table>
+<table x="517" y="65" name="permission">
+<row name="permission_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="app_permission" row="permission_id" />
+<relation table="permission_permission_rule" row="permission_id" />
+<relation table="permission_permission_rule" row="target_permission_id" />
+<relation table="permission_label_rule" row="permission_id" />
+<relation table="permission_app_path_type_rule" row="permission_id" />
+</row>
+<row name="permission_type_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="name" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>permission_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>permission_type_id</part>
+<part>name</part>
+</key>
+</table>
+<table x="855" y="133" name="permission_permission_rule">
+<row name="permission_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+</row>
+<row name="target_permission_id" null="1" autoincrement="0">
+<datatype>TINYINT</datatype>
+<default>NULL</default></row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<row name="is_reverse" null="1" autoincrement="0">
+<datatype>INTEGER</datatype>
+<default>NULL</default></row>
+<key type="PRIMARY" name="">
+<part>permission_id</part>
+<part>target_permission_id</part>
+<part>is_reverse</part>
+</key>
+</table>
+<table x="852" y="300" name="permission_label_rule">
+<row name="permission_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="label_id" null="1" autoincrement="0">
+<datatype>TINYINT</datatype>
+<default>NULL</default></row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<row name="is_reverse" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<key type="PRIMARY" name="">
+<part>permission_id</part>
+<part>label_id</part>
+<part>is_reverse</part>
+</key>
+</table>
+<table x="849" y="477" name="permission_app_path_type_rule">
+<row name="permission_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="app_path_type_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<row name="is_reverse" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<key type="PRIMARY" name="">
+<part>permission_id</part>
+<part>app_path_type_id</part>
+<part>is_reverse</part>
+</key>
+</table>
+</sql>
index c4370f4..49835c0 100644 (file)
 #ifndef _ACCESS_DB_H_
 #define _ACCESS_DB_H_
 
-/**
- * This function adds app_id to database.
- * Needs to be called by privileged user.
- */
-int add_app_id_to_databse(const char * app_id);
-
-/**
- * This function adds anti_virus_id to database.
- * Needs to be called by privileged user.
- */
-int add_av_id_to_databse(const char * av_id);
-
-/**
- * This function adds appsetting_id to database.
- * Needs to be called by privileged user.
- */
-int add_appsetting_id_to_databse(const char *appsetting_id);
-
-/**
- * This function adds setting_dir_id to database.
- * Needs to be called by privileged user.
- */
-int add_setting_dir_id_to_databse(const char *setting_dir_id);
-
-
-/**
- * This function returns (in params) labels of all installed applications.
- * apps_ids should be freed by caller.
- */
-int get_all_apps_ids(char *** apps_ids, int * len);
-
-
-/**
- * This function returns (in params) labels of all registered settings dirs of
- * all installed applications.
- * apps_ids should be freed by caller.
- */
-int get_all_settings_dir_ids(char ***apps_ids, int *len);
-
-
-/**
- * This function returns (in params) labels of all registered apps with
- * appsettings privilege
- *
- * apps_ids should be freed by caller.
- */
-int get_all_appsetting_ids(char ***apps_ids, int *len);
-
-/**
- * This function returns (in params) labels of all installed anti viruses.
- * avs_ids should be freed by caller.
- */
-int get_all_avs_ids(char *** av_ids, int * len);
 
 /**
  * This function adds an app to a supplementary group identified by gid
  */
 int add_app_gid(const char *app_id, unsigned gid);
 
+
 /**
  * This function returns (in params) supplementary group ids that an app
  * has been assigned to.
@@ -88,26 +36,4 @@ int add_app_gid(const char *app_id, unsigned gid);
  */
 int get_app_gids(const char *app_id, unsigned **gids, int *len);
 
-/**
- * This functions add public RO path to the database.
- */
-int db_add_public_dir(const char *dir_label);
-
-/**
- * This function returns (in params) list of public RO paths
- * dir_labels should be freed by caller.
- */
-int db_get_public_dirs(char ***dir_labels, int *len);
-
-/**
- * This functions add group RW path to the database.
- */
-int db_add_groups_dir(const char *dir_label);
-
-/**
- * This function returns (in params) list of group RW paths
- * dir_labels should be freed by caller.
- */
-int db_get_groups_dirs(char ***dir_labels, int *len);
-
 #endif // _ACCESS_DB_H_
index f0b6c53..dafe93e 100644 (file)
@@ -104,9 +104,6 @@ int smack_label_is_valid(const char* smack_label);
 
 int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd, char** path);
 int load_smack_from_file_early(const char* app_id, struct smack_accesses** smack, int *fd, char** path);
-int check_if_rules_were_loaded(const char *app_id);
-int add_app_first_run_rules(const char *app_id);
-void mark_rules_as_loaded(const char *app_id);
 int smack_mark_file_name(const char *app_id, char **path);
 bool file_exists(const char* path);
 int smack_file_name(const char* app_id, char** path);
index 2abbe19..0a121e5 100644 (file)
@@ -38,6 +38,7 @@ extern "C" {
 #endif // API
 
 #define DEPRECATED __attribute__((deprecated));
+#define UNUSED __attribute__((unused))
 
 /* error codes */
 #define        PC_OPERATION_SUCCESS            ((int)0)
@@ -48,6 +49,53 @@ extern "C" {
 #define PC_ERR_INVALID_OPERATION       -5
 #define PC_ERR_DB_OPERATION                    -6
 
+/// Label is taken by another application
+#define PC_ERR_DB_LABEL_TAKEN           -7
+
+/// Label is forbidden
+#define PC_ERR_DB_LABEL_FORBIDDEN       -8
+
+/// Query fails during preparing a SQL statement
+#define PC_ERR_DB_QUERY_PREP            -9
+
+/// Query fails during binding to a SQL statement
+#define PC_ERR_DB_QUERY_BIND            -10
+
+/// Query fails during stepping a SQL statement
+#define PC_ERR_DB_QUERY_STEP            -11
+
+/// Query is too long
+#define PC_ERR_DB_QUERY_TOO_LONG        -12
+
+/// Returned value is unexpected,
+/// e.g an int that stores bool is not 0 or 1.
+#define PC_ERR_DB_UNEXPECTED_VALUE      -13
+
+/// Constraint violated
+#define PC_ERR_DB_CONSTRAINT            -14
+
+// Unable to establish a connection with the database
+#define PC_ERR_DB_CONNECTION            -15
+
+// Error when creating boot file with rules
+#define PC_ERR_BOOT_FILE                -16
+
+// There is no application with such app_id
+#define PC_ERR_DB_NO_SUCH_APP           -17
+
+// There already exists a permission with this name and type
+#define PC_ERR_DB_PERM_FORBIDDEN        -18
+
+// There is no permission with a this name
+#define PC_ERR_DB_UNKNOWN_PERMISSION    -19
+
+// There is no application with this label
+#define PC_ERR_DB_UNKNOWN_APPLICATION   -20
+
+// This permission already exists
+#define PC_PERMISSION_EXISTS            -21
+
+
 typedef enum {
        APP_TYPE_WGT,
        APP_TYPE_OSP,
@@ -67,6 +115,7 @@ typedef enum {
        APP_PATH_ANY_LABEL,
 } app_path_type_t;
 
+
 /* APIs - used by applications */
 int control_privilege(void) DEPRECATED;
 
@@ -365,6 +414,20 @@ int add_api_feature(app_type_t app_type,
                     const gid_t* list_of_db_gids,
                     size_t list_size) DEPRECATED;
 
+
+/**
+ * Run before any privilege modification.
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int perm_modification_start(void);
+
+/**
+ * Run after any privilege modification.
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int perm_modification_finish(void);
+
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
diff --git a/include/rules-db-internals.h b/include/rules-db-internals.h
new file mode 100644 (file)
index 0000000..fb5fcec
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * @file        rules-db-internals.h
+ * @author      Jan Olszak (j.olszak@samsung.com)
+ * @version     1.0
+ * @brief       This file contains definition of rules database API.
+ */
+
+#include <sqlite3.h>
+#include "rules-db.h"
+
+#ifndef _RULES_DB_INTERNALS_H_
+#define _RULES_DB_INTERNALS_H_
+
+#define ACC_LEN 6
+
+// Templates:
+#define SMACK_APP_LABEL_TEMPLATE "~APP~"
+
+// Open database flags:
+#define RDB_READWRITE_FLAG SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_PRIVATECACHE
+#define RDB_READONLY_FLAG SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_PRIVATECACHE
+
+// Bind function defines:
+#define RDB_FIRST_PARAM  1 /// Bind to the first parameter
+#define RDB_SECOND_PARAM 2 /// Bind to the second parameter
+
+#define RDB_AUTO_DETERM_SIZE -1 // Determine the size of the
+
+// Getting values
+#define RDB_FIRST_COLUMN  0
+#define RDB_SECOND_COLUMN 1
+#define RDB_THIRD_COLUMN  2
+#define RDB_FOURTH_COLUMN 3
+
+#define RDB_DISABLE 0
+#define RDB_ENABLE  1
+
+#define RDB_LOG_ENTRY_PARAM(format, ...) C_LOGD("RDB: Entering function %s. Args: " format, __func__, ##__VA_ARGS__)
+#define RDB_LOG_ENTRY C_LOGD("RDB: Entering function %s", __func__)
+
+
+/**
+ * Add the label to the temporary table with modified labels.
+ * We use this table to speed up generating modified smack rules.
+ *
+ * If label is not in this table, but rule changed
+ * Smack will not get the rule in runtime.
+ *
+ *
+ * @param  p_db         pointer to a SQLite3 database object
+ * @param  s_label_name label name
+ * @return              PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_modified_label_internal(sqlite3 *p_db, const char *const s_label_name);
+
+
+/**
+ * Adds label names of applications with the permission to modified labels.
+ * Used when permission is going to change and we're going to change some
+ * accesses granted by this permission.
+ *
+ *
+ * @param  p_db            pointer to a SQLite3 database object
+ * @param  i_permission_id id of the permission
+ * @return                 PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id);
+
+
+/**
+ * Open a connection with the database and perform an initialization.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db pointer to a SQLite3 database object
+ * @return      PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int open_rdb_connection(sqlite3 **pp_db);
+
+
+/**
+ * Write variables into the query and create a SQLite statement.
+ * One should use the SQLite3 format strings like '%Q'.
+ *
+ * For a lot of generic queries use binding.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db    pointer to a SQLite3 database object
+ * @param  pp_stmt buffer for a pointer to the constructed statement
+ * @return         PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int prepare_stmt(sqlite3 *p_db,
+                sqlite3_stmt **pp_stmt,
+                const char   *const s_sql,
+                ...);
+
+
+/**
+ * Check if the label is present in the database.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db         pointer to a SQLite3 database object
+ * @param  s_label_name label's name
+ * @return              PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int check_label_internal(sqlite3 *p_db,
+                        const char  *const s_label_name);
+
+
+/**
+ * Check if the label is available for an application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db         pointer to a SQLite3 database object
+ * @param  s_label_name application's label name
+ * @return              PC_OPERATION_SUCCESS when label free
+ *                      PC_ERR_DB_LABEL_TAKEN when label taken
+ *                      error code otherwise
+ */
+int check_app_label_internal(sqlite3 *p_db,
+                            const char  *const s_label_name);
+
+
+/**
+ * Check if permission with a given name and type is available
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db                   pointer to a SQLite3 database object
+ * @param  s_permission_name      permission name
+ * @param  s_permission_type_name permission type name
+ * @return                        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int check_permission_internal(sqlite3 *p_db,
+                             const char *const s_permission_name,
+                             const char *const s_permission_type_name);
+
+
+/**
+ * Adds the application to the database.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db         pointer to a SQLite3 database object
+ * @param  s_label_name application's label name
+ * @return              PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_app_internal(sqlite3 *p_db,
+                    const char  *const s_label_name);
+
+
+/**
+ * Removes the application from the database together with its permissions and paths.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db         pointer to a SQLite3 database object
+ * @param  s_label_name application's label name
+ * @return              PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int remove_app_internal(sqlite3 *p_db,
+                       const char   *const s_label_name);
+
+
+/**
+ * Add a path to the database
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db               pointer to a SQLite3 database object
+ * @param  s_owner_label_name label name of the paths owner
+ * @param  s_path_label_name  path's label name
+ * @param  s_path             the path
+ * @param  access             access rights
+ * @param  s_type             path's type name
+ * @return                    PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_path_internal(sqlite3 *p_db,
+                     const char *const s_owner_label_name,
+                     const char *const s_path_label_name,
+                     const char *const s_path,
+                     const char *const s_access,
+                     const char *const s_type);
+
+
+/**
+ * Add a permission with a given name and of a give type
+ * and return its internal permission id.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db                   pointer to a SQLite3 database object
+ * @param  s_permission_name      permission name
+ * @param  s_permission_type_name permission type name
+ * @return                        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_permission_internal(sqlite3 *p_db,
+                           const char *const s_permission_name,
+                           const char *const s_permission_type_name);
+
+/**
+ * Gets the id of the permission
+ * @param  p_db                   pointer to a SQLite3 database object
+ * @param  s_permission_name      permission name
+ * @param  s_permission_type_name permission type name
+ * @param  p_permission_id        buffer for the id of the new permission
+ * @return                        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int get_permission_id_internal(sqlite3 *p_db,
+                              const char *const s_permission_name,
+                              const char *const s_permission_type_name,
+                              sqlite3_int64 *p_permission_id);
+
+/**
+ * Adds a list of smack permissions to the database.
+ * s_permision_name has to appear either in the subject or the object of the rule.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db            pointer to a SQLite3 database object
+ * @param  i_permission_id permission id for which we ad permission rules
+ * @param  pp_smack_rules  a list of smack rules, that we want to apply. Not empty!
+ * @return                 PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_permission_rules_internal(sqlite3 *p_db,
+                                 sqlite3_int64 i_permission_id,
+                                 const char  *const *const pp_smack_rules);
+
+
+
+/**
+ * Gets the internal app id of an application with a given name.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db             pointer to a SQLite3 database object
+ * @param  pi_app_id        pointer to where the app is should be returned
+ * @param  s_app_label_name label name of the application
+ * @return                  PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int get_app_id_internal(sqlite3 *p_db,
+                       int *pi_app_id,
+                       const char *const s_app_label_name);
+
+
+/**
+ * Divides the rule into subject, object and access strings.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  s_rule    the string that we parse
+ * @param  s_subject buffer for the subject
+ * @param  s_object  buffer for the object
+ * @param  s_access  buffer for the access
+ * @return           PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int parse_rule(const char *const s_rule,
+              char s_subject[],
+              char s_object[],
+              char s_access[]);
+
+
+/**
+ * Add a new permission to an application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db                   pointer to a SQLite3 database object
+ * @param  i_app_id               application id
+ * @param  s_permission_name      permission name
+ * @param  s_permission_type_name permission type name
+ * @param  b_is_volatile_new      is the permission volatile
+ * @param  b_is_enabled_new       is the permission enabled
+ * @return                        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_app_permission_internal(sqlite3 *p_db,
+                               int i_app_id,
+                               const char *const s_permission_name,
+                               const char *const s_permission_type_name,
+                               const bool b_is_volatile_new,
+                               const bool b_is_enabled_new);
+
+
+/**
+ * Enable or disable a permission for a given application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db                   pointer to a SQLite3 database object
+ * @param  i_app_id               application id
+ * @param  s_permission_name      permission name
+ * @param  s_permission_type_name permission type name
+ * @param  b_is_enabled_new       is the permission enabled
+ * @return                        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int switch_app_permission_internal(sqlite3 *p_db,
+                                  const int i_app_id,
+                                  const char *const s_permission_name,
+                                  const char *const s_permission_type_name,
+                                  const bool b_is_enabled_new);
+
+
+/**
+ * Update an existing permission of an application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db              pointer to a SQLite3 database object
+ * @param  i_app_id          application id
+ * @param  i_permission_id   id of the permission
+ * @param  b_is_volatile_new is the permission volatile
+ * @param  b_is_enabled_new  is the permission enabled
+ * @return                   PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int update_app_permission_internal(sqlite3 *p_db,
+                                  const int i_app_id,
+                                  const int i_permission_id,
+                                  const bool b_is_volatile_new,
+                                  const bool b_is_enabled_new);
+
+
+/**
+ * Change a permission for an application.
+ * Function modifies or adds a permission.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db                   pointer to a SQLite3 database object
+ * @param  i_app_id               application id
+ * @param  s_permission_name      permission name
+ * @param  s_permission_type_name permission type name
+ * @param  i_is_volatile_new      is the permission volatile
+ * @param  i_is_enabled_new       is the permission enabled
+ * @return                        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int change_app_permission_internal(sqlite3 *p_db,
+                                  int i_app_id,
+                                  const char *const s_permission_name,
+                                  const char *const s_permission_type_name,
+                                  int i_is_volatile_new,
+                                  int i_is_enabled_new);
+
+
+/**
+ * Delete all permissions of the application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db             pointer to a SQLite3 database object
+ * @param  s_app_label_name applications label name
+ * @return                  PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int revoke_app_permissions_internal(sqlite3 *p_db,
+                                   const char *const s_app_label_name);
+
+
+/**
+ * Delete all volatile permissions of the application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db             pointer to a SQLite3 database object
+ * @param  s_app_label_name applications label name
+ * @return                  PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int reset_app_permissions_internal(sqlite3 *p_db,
+                                  const char *const s_app_label_name);
+
+
+/**
+ * Saves present smack rules in a temporary table: history_smack_rule
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db pointer to a SQLite3 database object
+ * @return      PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int save_smack_rules(sqlite3 *p_db);
+
+
+/**
+ * Updates smack rules. Only rules that change are refreshed.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db pointer to a SQLite3 database object
+ * @return      PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int update_smack_rules(sqlite3 *p_db);
+
+
+#endif // _RULES_DB_INTERNALS_H_
\ No newline at end of file
diff --git a/include/rules-db.h b/include/rules-db.h
new file mode 100644 (file)
index 0000000..6ae4f91
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+/*
+ * @file        rules-db.h
+ * @author      Jan Olszak (j.olszak@samsung.com)
+ * @version     1.0
+ * @brief       This file contains definition of rules database API.
+ */
+
+#ifndef _RULES_DB_H_
+#define _RULES_DB_H_
+
+#include "privilege-control.h" // For error codes
+#include "common.h"
+
+#define RDB_PATH "/opt/dbspace/.rules-db.db3"
+#define RDB_BOOT_FILE_PATH "/opt/etc/smack/boot-rules.smack"
+#define RDB_BOOT_FILE_PATH_NEW "/opt/etc/smack/boot-rules-new.smack"
+
+
+/**
+ * Starts a session with the database.
+ * Begins transaction.
+ *
+ * @ingroup RDB API functions
+ *
+ * @return  PC_OPERATION_SUCCESS on success,
+ *          error code otherwise
+ */
+int rdb_modification_start(void);
+
+
+/**
+ * Finishes the session with the database.
+ * Commits or rollbacks.
+ *
+ * @ingroup RDB API functions
+ *
+ */
+void rdb_modification_finish(void);
+
+
+/**
+ * Add application label to the database.
+ * If label present: do nothing.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_label_name s_label_name application label
+ * @return              PC_OPERATION_SUCCESS on success,
+ *                      error code otherwise
+ */
+int rdb_add_application(const char *const s_label_name);
+
+
+/**
+ * Remove application label from the table.
+ * Used during uninstalling application.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_label_name application's label name
+ * @return              PC_OPERATION_SUCCESS on success,
+ *                      error code otherwise
+ */
+int rdb_remove_application(const char *const s_label_name);
+
+
+/**
+ * Add a path to the database.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_owner_label_name owner application's label name
+ * @param  s_path_label_name  path's label name
+ * @param  s_path             the path
+ * @param  i_access           access rights
+ * @param  s_type             type of path
+ * @return                    PC_OPERATION_SUCCESS on success,
+ *                            error code otherwise
+ */
+int rdb_add_path(const char *const s_owner_label_name,
+                const char *const s_path_label_name,
+                const char *const s_path,
+                const char *const s_access,
+                const char *const s_type);
+
+
+/**
+ * Add permission with the given name and type and add smack rules.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_permission_name      new permission's name
+ * @param  s_permission_type_name new permission's type
+ * @param  pp_smack_rules         a table of smack accesses to apply
+ * @return                        PC_OPERATION_SUCCESS on success,
+ *                                error code otherwise
+ */
+int rdb_add_permission_rules(const char  *const s_permission_name,
+                            const char  *const s_permission_type_name,
+                            const char *const *const pp_smack_rules);
+
+
+/**
+ * Enable permissions from the list.
+ * If there were no such permissions, we adds them.
+ * One can't change permissions from non volatile to volatile,
+ * One can change permissions from volatile to non volatile,
+ * but it's suspicious...
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_app_label_name       application's label name
+ * @param  s_permission_type_name permission's type name
+ * @param  pp_permissions_list    array of permissions to parse
+ * @param  b_is_volatile          are the new permissions volatile
+ * @return                        PC_OPERATION_SUCCESS on success,
+ *                                error code otherwise
+ */
+int rdb_enable_app_permissions(const char  *const s_app_label_name,
+                              const char  *const s_permission_type_name,
+                              const char *const *const pp_permissions_list,
+                              const bool   b_is_volatile);
+
+
+/**
+ * Disable permissions from the list.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_app_label_name       application's label name
+ * @param  s_permission_type_name permission's type name
+ * @param  pp_permissions_list    array of permissions to parse
+ * @return                        PC_OPERATION_SUCCESS on success,
+ *                                error code otherwise
+ */
+int rdb_disable_app_permissions(const char  *const s_app_label_name,
+                               const char  *const s_permission_type_name,
+                               const char *const *const pp_permissions_list);
+
+
+/**
+ * Validate if all rules in the array can be parsed.
+ *
+ * @param  pp_permissions_list array of permissions to check
+ * @return                     PC_OPERATION_SUCCESS on success,
+ *                             error code otherwise
+ */
+int validate_all_rules(const char *const *const pp_permissions_list);
+
+
+/**
+ * Revokes all permissions from the application by.
+ * deleting all permissions from app_permission table.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_app_label_name application's label name
+ * @return                  PC_OPERATION_SUCCESS on success,
+ *                          error code otherwise
+ */
+int rdb_revoke_app_permissions(const char *const s_app_label_name);
+
+
+/**
+ * Revokes all volatile permissions from the application by.
+ * deleting all permissions from app_permission table.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_app_label_name application's label name
+ * @return                  PC_OPERATION_SUCCESS on success,
+ *                          error code otherwise
+ */
+int rdb_reset_app_permissions(const char *const s_app_label_name);
+
+#endif /*_RULES_DB_H_*/
\ No newline at end of file
index e178289..34c228c 100644 (file)
                <domain name="_"/>
        </request>
        <assign>
-               <filesystem path="/opt/dbspace/.privilege_control_all_apps_id.db" label="system::privilege_control::db"/>
-               <filesystem path="/opt/dbspace/.privilege_control_all_avs_id.db" label="system::privilege_control::db"/>
                <filesystem path="/opt/dbspace/.privilege_control_app_gids.db" label="system::privilege_control::db"/>
-               <filesystem path="/opt/dbspace/.privilege_control_public_dirs.db" label="system::privilege_control::db"/>
-               <filesystem path="/opt/dbspace/.privilege_control_setting_dir.db" label="system::privilege_control::db"/>
-               <filesystem path="/opt/dbspace/.privilege_control_app_setting.db" label="system::privilege_control::db"/>
+               <filesystem path="/opt/dbspace/.rules-db.db3" label="system::privilege_control::db"/>
        </assign>
 </manifest>
index 33769b9..6ed4c12 100644 (file)
@@ -1,5 +1,34 @@
-* Tue Aug 20 2013 Rafal Krypa <r.krypa@samsung.com> - 0.0.42.TIZEN
-- Changed dlog logging buffer.
+* Mon Sep 16 2013 Bartlomiej Grzelewski - 0.0.57.SLP
+[Jan Olszak]
+- Optimalization of the database operation time.
+
+* Fri Sep 13 2013 Krzysztof Jackiewicz - 0.0.56.SLP
+[Jan Olszak]
+- Corrected behavior when there is no Smack on the target.
+[Jan Olszak]
+- Correct antivirus access rights to public dirs.
+[Jan Olszak]
+- Rules kept in SQLite3 database. Initial commit.
+[Jan Olszak]
+- SQLite3 database for application permissions.
+[Krzysztof Jackiewicz]
+- Fix for ~APP~ label allowance issue
+[Krzysztof Jackiewicz]
+- Unused function smack_get_access_new removed
+[Krzysztof Jackiewicz]
+- Libprivilege API cleanup
+[Lukasz Kostyra]
+- Add missing information about APP_PATH_ANY_LABEL in header
+[Bartlomiej Grzelewski]
+- Takes compilation profile from command line.
+
+* Wed Aug 28 2013 Krzysztof Jackiewicz - 0.0.55.SLP
+[Janusz Kozerski]
+- Add for all anti viruses RWX access to all public-RO and group-RW shared folder
+[Marcin Lis]
+- Simple corrections in api-feature handling.
+
+* Tue Aug 13 2013 Rafal Krypa - 0.0.54.SLP
 - Adapt code for new libsmack API
 - Rewrite internal function app_uninstall_remove_early_rules()
 - Create format strings for scanf statically.
index df1853e..b5e2b7b 100644 (file)
@@ -14,7 +14,9 @@ BuildRequires: libcap-devel
 BuildRequires: pkgconfig(libsmack)
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(libiri)
-Requires: smack-privilege-config
+BuildRequires: pkgconfig(sqlite3)
+Requires:   smack-privilege-config
+Requires:   sqlite
 
 %description
 development package of library to control privilege of in-house application
@@ -46,7 +48,7 @@ export CFLAGS="${CFLAGS} -Wno-implicit-function-declaration"
 %cmake . -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:RELEASE} \
          -DCMAKE_VERBOSE_MAKEFILE=ON
 
-make %{?jobs:-j%jobs}
+VERBOSE=1 make %{?jobs:-j%jobs}
 
 %install
 rm -rf %{buildroot}
@@ -66,8 +68,7 @@ install -m 644 %{SOURCE2} %{buildroot}/usr/lib/systemd/system/
 ln -s ../smack-default-labeling.service %{buildroot}/usr/lib/systemd/system/basic.target.wants/
 
 mkdir -p %{buildroot}/usr/lib/systemd/system/multi-user.target.wants
-ln -sf /usr/lib/systemd/system/smack-late-rules.service %{buildroot}/usr/lib/systemd/system/multi-user.target.wants/smack-late-rules.service
-ln -sf /usr/lib/systemd/system/smack-early-rules.service %{buildroot}/usr/lib/systemd/system/multi-user.target.wants/smack-early-rules.service
+ln -sf /usr/lib/systemd/system/smack-rules.service %{buildroot}/usr/lib/systemd/system/multi-user.target.wants/smack-rules.service
 
 mkdir -p %{buildroot}/usr/lib/systemd/system/tizen-runtime.target.wants
 ln -s /usr/lib/systemd/system/smack-default-labeling.service %{buildroot}/usr/lib/systemd/system/multi-user.target.wants/smack-default-labeling.service
@@ -99,19 +100,38 @@ then
        mkdir -p /opt/etc/smack-app-early/accesses.d
 fi
 
+if [ ! -e "/opt/dbspace/.rules-db.db3" ]
+then
+       # First installation
+       rm -f /opt/dbspace/.rules-db.db3-journal
+       sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db.sql
+       sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db-data.sql
+
+       api_feature_loader --verbose
+else
+       # There is the rules-db database.
+       sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db.sql
+       sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db-data.sql
+fi
+
+rm -f /opt/dbspace/rules-db.sql
+rm -f /opt/dbspace/rules-db-data.sql
+
 %files
 %{_libdir}/*.so.*
+%{_libdir}/librules-db-sql-udf.so
 %{_bindir}/slp-su
 #%{udev_libdir}/rules.d/*
 #%attr(755,root,root) %{udev_libdir}/uname_env
 %{_datadir}/license/%{name}
 #systemd service
-/usr/lib/systemd/system/smack-late-rules.service
-/usr/lib/systemd/system/smack-early-rules.service
-/usr/bin/rule_loader
+/usr/lib/systemd/system/smack-rules.service
+/usr/bin/api_feature_loader
 #link to activate systemd service
-/usr/lib/systemd/system/multi-user.target.wants/smack-late-rules.service
-/usr/lib/systemd/system/multi-user.target.wants/smack-early-rules.service
+/usr/lib/systemd/system/multi-user.target.wants/smack-rules.service
+/opt/dbspace/rules-db.sql
+/opt/dbspace/rules-db-data.sql
+/opt/etc/smack/load-rules-db.sql
 
 %files conf
 /etc/group
@@ -126,5 +146,5 @@ fi
 
 %files devel
 %{_includedir}/*.h
-%{_libdir}/*.so
+%{_libdir}/libprivilege-control.so
 %{_libdir}/pkgconfig/*.pc
diff --git a/rule_loader/rule_loader.c b/rule_loader/rule_loader.c
deleted file mode 100644 (file)
index 7e5a6e3..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <access-db.h>
-#include <privilege-control.h>
-#include <common.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <errno.h>
-
-#define LOG_PATH    "/root/rules_loader_log.txt"
-#define EARLY_RULES_DIR   "/opt/etc/smack-app/accesses.d"
-
-int main(int argc, char * argv[])
-{
-    FILE * log_file = NULL;
-    int ret = 0;
-    //for searching files in directory
-    struct dirent *file = NULL;
-    DIR *dir = NULL;
-
-    log_file = fopen(LOG_PATH, "w");
-    if (log_file == NULL)
-        goto error;
-    fprintf(log_file, "Loading early rules...\n");
-
-    //opening directory
-    dir = opendir(EARLY_RULES_DIR);
-    if (dir == NULL) {
-        fprintf(log_file, "Error in opendir(): %s\n", strerror(errno));
-        goto error;
-    }
-
-    //iterate trough files
-    while ((file = readdir(dir)) != NULL) {
-        //for each file load rules from it
-        fprintf(log_file, "Loading rulse from file: %s\n", file->d_name);
-        //checking if it is file
-        if (file->d_type != DT_REG) {
-            fprintf(log_file, "Skipping, not regular file\n");
-            continue;
-        }
-        //checking if rules are loaded
-        ret = check_if_rules_were_loaded(file->d_name);
-        if (ret < 0) {
-            fprintf(log_file,"Error in check_if_rules_were_loaded()\n");
-            //we're skipping to the next app_id
-        } else if (ret == 0) {
-            //if not load rules
-            ret = add_app_first_run_rules(file->d_name);
-            if (ret < 0)
-                fprintf(log_file,"Error in add_app_first_run_rules(): %d\n", ret);
-            else
-                //mark rules as loaded
-                mark_rules_as_loaded(file->d_name);
-        } else {
-            fprintf(log_file,"Rules already loaded\n");
-        }
-
-    }
-
-    fprintf(log_file, "DONE\n");
-
-error:
-    if (dir != NULL)
-        closedir(dir);
-    if (log_file)
-        fclose(log_file);
-    return ret;
-}
diff --git a/rule_loader/smack-early-rules.service b/rule_loader/smack-early-rules.service
deleted file mode 100644 (file)
index afa06a7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-[Unit]
-Description=Late SMACK rules loading
-ConditionSecurity=smack
-Before=starter.service
-
-[Service]
-Type=oneshot
-ExecStart=/usr/bin/smackload /opt/etc/smack-app-early/accesses.d
-
-[Install]
-WantedBy=multi-user.target
diff --git a/rule_loader/smack-late-rules.service b/rule_loader/smack-late-rules.service
deleted file mode 100644 (file)
index 53e6442..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-[Unit]
-Description=Late SMACK rules loading
-ConditionSecurity=smack
-After=starter.service
-
-[Service]
-Type=oneshot
-ExecStart=/usr/bin/rule_loader
-
-[Install]
-WantedBy=multi-user.target
diff --git a/smack-rules.service b/smack-rules.service
new file mode 100644 (file)
index 0000000..769d5b7
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=SMACK rules loading
+Before=starter.service
+
+[Service]
+Type=oneshot
+ExecStartPre =  /bin/bash -c '/usr/bin/sqlite3 /opt/dbspace/.rules-db.db3 < /opt/etc/smack/load-rules-db.sql'
+ExecStart =  /usr/bin/smackload /opt/etc/smack/boot-rules.smack
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
index f287d4a..96e1355 100644 (file)
 #include "common.h"
 
 typedef enum {
-       DB_APP_TYPE_APPLICATION,
-       DB_APP_TYPE_ANTIVIRUS,
        DB_APP_TYPE_GROUPS,
-       DB_APP_TYPE_PUBLIC_DIRS,
-       DB_APP_TYPE_GROUPS_DIRS,
-       DB_APP_TYPE_APPSETTING,
-       DB_APP_TYPE_SETTING_DIR,
        DB_APP_TYPE_COUNT /* Dummy enum element to get number of elements */
 } db_app_type_t;
 
 const char* db_file_names[DB_APP_TYPE_COUNT] = {
-               "/opt/dbspace/.privilege_control_all_apps_id.db",
-               "/opt/dbspace/.privilege_control_all_avs_id.db",
-               "/opt/dbspace/.privilege_control_app_gids.db",
-               "/opt/dbspace/.privilege_control_public_dirs.db",
-               "/opt/dbspace/.privilege_control_groups_dirs.db",
-               "/opt/dbspace/.privilege_control_app_setting.db",
-               "/opt/dbspace/.privilege_control_setting_dir.db",
+               "/opt/dbspace/.privilege_control_app_gids.db"
 };
 
 typedef struct element_s {
@@ -84,6 +72,7 @@ static element_t* add_element (element_t* elem, const char* value)
        return new_element;
 }
 
+
 static int remove_list(element_t* first_elem)
 {
        SECURE_C_LOGD("Entering function: %s.", __func__);
@@ -100,6 +89,7 @@ static int remove_list(element_t* first_elem)
        return 0;
 }
 
+
 static int add_id_to_database_internal(const char * id, db_app_type_t app_type)
 {
        SECURE_C_LOGD("Entering function: %s. Params: id=%s",
@@ -123,6 +113,7 @@ static int add_id_to_database_internal(const char * id, db_app_type_t app_type)
        return PC_OPERATION_SUCCESS;
 }
 
+
 static int get_all_ids_internal (char *** ids, int * len, db_app_type_t app_type)
 {
        SECURE_C_LOGD("Entering function: %s.", __func__);
@@ -216,90 +207,6 @@ out:
        return ret;
 }
 
-int get_all_apps_ids (char *** apps_ids, int * len)
-{
-       SECURE_C_LOGD("Entering function: %s.", __func__);
-
-       if (get_all_ids_internal(apps_ids, len, DB_APP_TYPE_APPLICATION))
-               return PC_ERR_DB_OPERATION;
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int get_all_settings_dir_ids(char ***apps_ids, int *len)
-{
-       SECURE_C_LOGD("Entering function: %s.", __func__);
-
-       if (get_all_ids_internal(apps_ids, len, DB_APP_TYPE_SETTING_DIR))
-               return PC_ERR_DB_OPERATION;
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int get_all_appsetting_ids(char ***apps_ids, int *len)
-{
-       SECURE_C_LOGD("Entering function: %s.", __func__);
-
-       if (get_all_ids_internal(apps_ids, len, DB_APP_TYPE_APPSETTING))
-               return PC_ERR_DB_OPERATION;
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int get_all_avs_ids (char *** av_ids, int * len)
-{
-       SECURE_C_LOGD("Entering function: %s.", __func__);
-
-       if (get_all_ids_internal(av_ids, len, DB_APP_TYPE_ANTIVIRUS))
-               return PC_ERR_DB_OPERATION;
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int add_app_id_to_databse(const char * app_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-
-       if (add_id_to_database_internal(app_id, DB_APP_TYPE_APPLICATION))
-               return PC_ERR_DB_OPERATION;
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int add_av_id_to_databse (const char * av_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: av_id=%s",
-                               __func__, av_id);
-
-       if (add_id_to_database_internal(av_id, DB_APP_TYPE_ANTIVIRUS))
-               return PC_ERR_DB_OPERATION;
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int add_appsetting_id_to_databse(const char *appsetting_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: appsetting_id=%s",
-                               __func__, appsetting_id);
-
-       if (add_id_to_database_internal(appsetting_id, DB_APP_TYPE_APPSETTING))
-               return PC_ERR_DB_OPERATION;
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int add_setting_dir_id_to_databse(const char *setting_dir_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: setting_dir_id=%s",
-                               __func__, setting_dir_id);
-
-       if (add_id_to_database_internal(
-                       setting_dir_id, DB_APP_TYPE_SETTING_DIR))
-               return PC_ERR_DB_OPERATION;
-
-       return PC_OPERATION_SUCCESS;
-}
 
 int add_app_gid(const char *app_id, unsigned gid)
 {
@@ -322,6 +229,7 @@ int add_app_gid(const char *app_id, unsigned gid)
        return ret;
 }
 
+
 int get_app_gids(const char *app_id, unsigned **gids, int *len)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
@@ -392,58 +300,4 @@ out:
        }
 
        return ret;
-}
-
-int db_add_public_dir(const char *dir_label)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: dir_label=%s",
-                               __func__, dir_label);
-
-       if (add_id_to_database_internal(dir_label, DB_APP_TYPE_PUBLIC_DIRS))
-       {
-               C_LOGE("add_id_to_database_internal failed.");
-               return PC_ERR_DB_OPERATION;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int db_get_public_dirs(char ***dir_labels, int *len)
-{
-       SECURE_C_LOGD("Entering function: %s.", __func__);
-
-       if (get_all_ids_internal(dir_labels, len, DB_APP_TYPE_PUBLIC_DIRS))
-       {
-               C_LOGE("get_all_ids_internal failed.");
-               return PC_ERR_DB_OPERATION;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int db_add_groups_dir(const char *dir_label)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: dir_label=%s",
-                               __func__, dir_label);
-
-       if (add_id_to_database_internal(dir_label, DB_APP_TYPE_GROUPS_DIRS))
-       {
-               C_LOGE("add_id_to_database_internal failed.");
-               return PC_ERR_DB_OPERATION;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-int db_get_groups_dirs(char ***dir_labels, int *len)
-{
-       SECURE_C_LOGD("Entering function: %s.", __func__);
-
-       if (get_all_ids_internal(dir_labels, len, DB_APP_TYPE_GROUPS_DIRS))
-       {
-               C_LOGE("get_all_ids_internal failed.");
-               return PC_ERR_DB_OPERATION;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
+}
\ No newline at end of file
index 2478ad4..4b68e48 100644 (file)
@@ -94,83 +94,6 @@ void fts_closep(FTS **f)
 
 }
 
-/**
- * This function checks if SMACK rules of application were already loaded
- * by checking if specific file exist. This function doesn't create such file.
- * Return values:
- *  0 if rules weren't yet loaded,
- *  1 if rules were loaded
- * -1 if error occurs while checking
- */
-int check_if_rules_were_loaded(const char *app_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-       int ret;
-       char *path AUTO_FREE;
-
-       ret = smack_mark_file_name(app_id, &path);
-       if(PC_OPERATION_SUCCESS != ret) {
-               return -1;
-       }
-
-       return file_exists(path);
-}
-
-/**
- * This function marks that rules for app were already loaded by creating
- * specific for this app (empty) file.
- */
-void mark_rules_as_loaded(const char *app_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-
-       struct stat s;
-       char *path AUTO_FREE;
-       FILE *file = NULL;
-
-       if(smack_mark_file_name(app_id, &path)) {
-               C_LOGE("smack_mark_file_name failed.");
-               return;
-       }
-
-       if (-1 == stat(SMACK_LOADED_APP_RULES, &s)) {
-               if (ENOENT == errno) {
-                       C_LOGD("Creating dir %s.", SMACK_LOADED_APP_RULES);
-                       mkdir(SMACK_LOADED_APP_RULES, S_IRWXU | S_IRWXG | S_IRWXO);
-               }
-       }
-
-       SECURE_C_LOGD("Creating file %s.", path);
-       file = fopen(path, "w");
-       fclose(file);
-}
-
-int add_app_first_run_rules(const char *app_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-
-       int ret;
-       int fd AUTO_CLOSE;
-       char *smack_path AUTO_FREE;
-       struct smack_accesses* smack AUTO_SMACK_FREE;
-
-       ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("Error in load_smack_from_file");
-               return ret;
-       }
-       if (have_smack() && smack_accesses_apply(smack)) {
-               C_LOGE("smack_accesses_apply failed.");
-               return PC_ERR_INVALID_OPERATION;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-
 static int load_smack_from_file_generic(const char* app_id, struct smack_accesses** smack, int *fd, char** path, bool is_early)
 {
        /* Notice that app_id is ignored when flag is_early is set.
@@ -299,4 +222,4 @@ inline int have_smack(void)
        }
 
        return have_smack;
-}
+}
\ No newline at end of file
index e4b944c..512458e 100644 (file)
@@ -46,6 +46,7 @@
 #include "privilege-control.h"
 #include "access-db.h"
 #include "common.h"
+#include "rules-db.h"
 
 #define APP_GID        5000
 #define APP_UID        5000
@@ -92,6 +93,36 @@ enum {
        DECISION_LABEL = 1
 };
 
+
+// __attribute__ ((constructor))
+// static void libprivilege_constructor()
+// {
+//     SECURE_C_LOGD("Entering function: %s.", __func__);
+//     perm_modification_start();
+// }
+
+__attribute__ ((destructor))
+static void libprivilege_destructor()
+{
+       SECURE_C_LOGD("Entering function: %s.", __func__);
+       perm_modification_finish();
+}
+
+API int perm_modification_start()
+{
+       SECURE_C_LOGD("Entering function: %s.", __func__);
+       return rdb_modification_start();
+}
+
+API int perm_modification_finish()
+{
+       SECURE_C_LOGD("Entering function: %s.", __func__);
+
+       rdb_modification_finish();
+       sync();
+       return PC_OPERATION_SUCCESS;
+}
+
 API int control_privilege(void)//deprecated
 {
        SECURE_C_LOGD("Entering function: %s.", __func__);
@@ -562,7 +593,6 @@ API int perm_app_set_privilege(const char* name, const char* type, const char* p
 
        //SECURE_C_LOGD("Function params: name = %s, type = %s, path = %s", name, type, path);
        int ret = PC_OPERATION_SUCCESS;
-       int were_rules_loaded = 0;
        char *smack_label AUTO_FREE;
 
        if (name == NULL) {
@@ -574,20 +604,6 @@ API int perm_app_set_privilege(const char* name, const char* type, const char* p
                ret = get_smack_from_binary(&smack_label, path, verify_app_type(type, path));
                if (ret != PC_OPERATION_SUCCESS)
                        return ret;
-               were_rules_loaded = check_if_rules_were_loaded(smack_label);
-               if (were_rules_loaded < 0) {
-                       C_LOGE("check_if_rules_was_loaded failed.");
-                       return PC_ERR_INVALID_OPERATION;
-               }
-               if (!were_rules_loaded) { // first run of application
-                       C_LOGD("This is first run of this application. Adding SMACK rules.");
-                       ret = add_app_first_run_rules(smack_label);
-                       if (ret != PC_OPERATION_SUCCESS ) {
-                               C_LOGW("add_app_first_run_rules failed");
-                               // should we return here with error code?
-                       }
-                       mark_rules_as_loaded(smack_label);
-               }
 
                ret = set_smack_for_self(smack_label);
                if (ret != PC_OPERATION_SUCCESS)
@@ -761,85 +777,6 @@ static int perm_file_path(char** path, app_type_t app_type, const char* perm, co
        return PC_OPERATION_SUCCESS;
 }
 
-static int perm_to_smack_from_file(struct smack_accesses* smack,
-                                          const char* app_label,
-                                          const char* app_label_template,
-                                          const char* rules_file_path)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_label_template=%s, rules_file_path=%s",
-                               __func__, app_label, app_label_template, rules_file_path);
-
-       char smack_subject[SMACK_LABEL_LEN + 1];
-       char smack_object[SMACK_LABEL_LEN + 1];
-       char smack_accesses[ACC_LEN + 1];
-       FILE* file AUTO_FCLOSE;
-
-       SECURE_C_LOGD("Opening file %s.", rules_file_path);
-       file = fopen(rules_file_path, "r");
-       if (file == NULL) {
-               SECURE_C_LOGW("fopen failed [%s] %s", rules_file_path, strerror(errno));
-               return PC_OPERATION_SUCCESS;
-       }
-
-       while (fscanf(file,
-                       "%" TOSTRING(SMACK_LABEL_LEN) "s "
-                       "%" TOSTRING(SMACK_LABEL_LEN) "s "
-                       "%" TOSTRING(ACC_LEN) "s\n",
-                       smack_subject, smack_object, smack_accesses) == 3) {
-               if (!strcmp(smack_subject, app_label_template))
-                       strcpy(smack_subject, app_label);
-
-               if (!strcmp(smack_object, app_label_template))
-                       strcpy(smack_object, app_label);
-
-               C_LOGD("smack_accesses_add_modify (subject: %s, object: %s, access: %s)", smack_subject, smack_object, smack_accesses);
-               if (smack_accesses_add_modify(smack, smack_subject, smack_object, smack_accesses, "") != 0) {
-                       C_LOGE("smack_accesses_add_modify failed.");
-                       return PC_ERR_INVALID_OPERATION;
-               }
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-static int perm_to_smack_generic(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm, bool is_early)
-{
-       C_LOGD("Enter function: %s", __func__);
-
-       int ret;
-       char* path AUTO_FREE;
-
-       // get file name for permission (devcap)
-       ret = perm_file_path(&path, app_type, perm, ".smack", is_early);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGD("No smack config file for permission %s", perm);
-               return ret;
-       }
-
-       ret = perm_to_smack_from_file(smack, app_label, SMACK_APP_LABEL_TEMPLATE, path);
-       if (ret != PC_OPERATION_SUCCESS) {
-               return ret;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-static int perm_to_smack_early(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
-                               __func__, app_label, app_type, perm);
-
-       return perm_to_smack_generic(smack, app_label, app_type, perm, 1);
-}
-
-static int perm_to_smack(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
-                               __func__, app_label, app_type, perm);
-
-       return perm_to_smack_generic(smack, app_label, app_type, perm, 0);
-}
-
 static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
@@ -875,7 +812,7 @@ static int perm_to_dac(const char* app_label, app_type_t app_type, const char* p
        return PC_OPERATION_SUCCESS;
 }
 
-static int label_all(const FTSENT* ftsent)
+static int label_all(const FTSENT* ftsent UNUSED)
 {
        SECURE_C_LOGD("Entering function: %s.", __func__);
 
@@ -978,7 +915,6 @@ static int dir_set_smack_r(const char *path, const char* label,
        }
        return PC_OPERATION_SUCCESS;
 }
-
 API char* app_id_from_socket(int sockfd)//deprecated
 {
        SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
@@ -1011,754 +947,234 @@ API char* perm_app_id_from_socket(int sockfd)
        return app_id;
 }
 
-static int app_add_rule(const char *app_id, const char *object, const char *perm)
+
+static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
 {
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, object=%s, perm=%s",
-                               __func__, app_id, object, perm);
+       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
+                               __func__, app_id, app_type, permanent);
 
-       int ret;
+       int i, ret;
+       char* smack_path AUTO_FREE;
+       char* smack_path_early AUTO_FREE;
        int fd AUTO_CLOSE;
-       char *smack_path AUTO_FREE;
-       struct smack_accesses* smack AUTO_SMACK_FREE;
+       int fd_early AUTO_CLOSE;
+       struct smack_accesses *smack AUTO_SMACK_FREE;
+       struct smack_accesses *smack_early AUTO_SMACK_FREE;
 
-       ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("load_smack_from_file failed.");
-               return ret;
+       if (!smack_label_is_valid(app_id)) {
+               C_LOGE("Invalid param app_id.");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       ret = smack_accesses_add_modify(smack, app_id, object, perm, "");
-       if (ret == -1) {
-               C_LOGE("smack_accesses_add_modify failed.");
-               return PC_ERR_INVALID_OPERATION;
+       if(perm_list == NULL) {
+               C_LOGE("Invalid perm_list (NULL).");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       if (have_smack() && smack_accesses_apply(smack)) {
-               C_LOGE("smack_accesses_apply failed.");
-               return PC_ERR_INVALID_OPERATION;
+       if (app_type_group_name(app_type) == NULL) {
+               C_LOGE("Unknown app type.");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       if (smack_accesses_save(smack, fd)) {
-               C_LOGE("smack_accesses_save failed.");
-               return PC_ERR_INVALID_OPERATION;
+       // Add permission to DAC
+       for (i = 0; perm_list[i] != NULL; ++i) {
+               ret = perm_to_dac(app_id, app_type, perm_list[i]);
+               if (ret != PC_OPERATION_SUCCESS){
+                       C_LOGE("perm_to_dac failed");
+                       return ret;
+               }
        }
 
+       // Enable the permissions:
+       ret = rdb_enable_app_permissions(app_id,
+                                        app_type_group_name(app_type),
+                                        perm_list,
+                                        !((bool)permanent));
+       if (ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB rdb_enable_app_permissions failed with: %d", ret);
+               return ret;
+       }
+
+
+       SECURE_C_LOGD("Leaving function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
+                               __func__, app_id, app_type, permanent);
+
        return PC_OPERATION_SUCCESS;
 }
 
+API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
+{
+       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
+                               __func__, app_id);
+
+       return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
+}
 
-static int
-app_register_appsetting(const char *app_id, struct smack_accesses *smack)
+API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
                                __func__, app_id);
 
-       int ret;
-       int i;
+       return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 0);
+}
 
-       char **label_app_list AUTO_FREE;
-       char **label_dir_list AUTO_FREE;
-       int app_list_len = 0;
-       int dir_list_len = 0;
+API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
+{
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
+                               __func__, pkg_id, app_type, persistent);
 
-       if (!smack_label_is_valid(app_id)) {
+       return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
+}
+
+API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)
+{
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
+                               __func__, pkg_id, app_type, persistent);
+
+       return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
+}
+
+API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
+{
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
+                               __func__, pkg_id, app_type);
+
+       return perm_app_disable_permissions(pkg_id, app_type, perm_list);
+}
+
+/* FIXME: this function is only a stub */
+API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
+{
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
+                               __func__, pkg_id, app_type);
+
+       int ret;
+       if (!smack_label_is_valid(pkg_id)) {
                C_LOGE("Invalid param app_id.");
                return PC_ERR_INVALID_PARAM;
        }
 
-       /* writing appsetting_id (app_id) to "database"*/
-       ret = add_appsetting_id_to_databse(app_id);
-       if (ret != PC_OPERATION_SUCCESS)
-               goto out;
-
-
-       /* Reading labels of all installed apps from "database"*/
-       ret = get_all_apps_ids(&label_app_list, &app_list_len);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("Error while getting data from database");
-               goto out;
+       if (perm_list == NULL) {
+               C_LOGE("Invalid perm_list (NULL).");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       /*Add smack rules with rx access to each app*/
-       for (i = 0; i < app_list_len; ++i) {
-               C_LOGD("Appsetting: applying rx rule for %s", label_app_list[i]);
-               if (smack_accesses_add_modify(smack, app_id,
-                               label_app_list[i], "rx", "") == -1) {
-                       C_LOGE("smack_accesses_add_modify failed.");
-                       ret = PC_ERR_INVALID_OPERATION;
-                       goto out;
-               }
+       if (app_type_group_name(app_type) == NULL) {
+               C_LOGE("Unknown app type.");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       /* Reading labels of all registered settings dirs from "database"*/
-       ret = get_all_settings_dir_ids(
-                       &label_dir_list, &dir_list_len);
+       ret = rdb_disable_app_permissions(pkg_id, app_type_group_name(app_type), perm_list);
        if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("Error while getting data from database");
-               goto out;
-       }
-       /*Add smack rules with rwx access to each app*/
-       for (i = 0; i < dir_list_len; ++i) {
-               C_LOGD("Appsetting: applying rwx rule for %s", label_dir_list[i]);
-               if (smack_accesses_add_modify(smack, app_id,
-                               label_dir_list[i], "rwx", "") == -1) {
-                       C_LOGE("smack_accesses_add_modify failed.");
-                       ret = PC_ERR_INVALID_OPERATION;
-                       goto out;
-                       /* Should we abort adding rules if
-                        * smack_accesses_add_modify fails once?*/
-               }
+               C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
+               return ret;
        }
 
-       out:
-       for (i = 0; i < app_list_len; ++i) {
-               free(label_app_list[i]);
-       }
-       for (i = 0; i < dir_list_len; ++i) {
-               free(label_dir_list[i]);
-       }
+       return PC_OPERATION_SUCCESS;
+}
 
-       return ret;
+API int app_revoke_permissions(const char* pkg_id)//deprecated
+{
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
+       return perm_app_revoke_permissions(pkg_id);
 }
 
-static int give_anti_virus_access_to_all_folders(const char *app_av_id, struct smack_accesses* smack, int folder_type)
+API int perm_app_revoke_permissions(const char* pkg_id)
 {
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
        int ret;
-       int i;
 
-       char** smack_label_list AUTO_FREE;
-       int smack_label_list_len = 0;
-
-       switch (folder_type) {
-               case APP_PATH_PUBLIC_RO:
-                       ret = db_get_public_dirs(&smack_label_list, &smack_label_list_len);
-                       break;
-               case APP_PATH_GROUP_RW:
-                       ret = db_get_groups_dirs(&smack_label_list, &smack_label_list_len);
-                       break;
-               case APP_PATH_SETTINGS_RW:
-                       ret = get_all_settings_dir_ids(&smack_label_list, &smack_label_list_len);
-                       break;
-               default:
-                       return PC_OPERATION_SUCCESS;
-       }
-       if (ret != PC_OPERATION_SUCCESS ) {
-               C_LOGE("Error while getting public RO folders from database.");
-               goto out;
+       if (!smack_label_is_valid(pkg_id)) {
+               C_LOGE("Invalid param app_id.");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       for (i = 0; i < smack_label_list_len; ++i) {
-               SECURE_C_LOGD("Applying rwx rule for %s", smack_label_list[i]);
-               if (smack_accesses_add_modify(smack, app_av_id, smack_label_list[i], "wrx", "") == -1) {
-                       C_LOGE("smack_accesses_add_modify failed.");
-                       ret = PC_ERR_INVALID_OPERATION;
-                       goto out;
-               }
+       ret = rdb_revoke_app_permissions(pkg_id);
+       if (ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
+               return ret;
        }
 
-out:
+       return PC_OPERATION_SUCCESS;
+}
 
-       for (i = 0; i < smack_label_list_len; ++i) {
-               free(smack_label_list[i]);
-       }
+API int app_reset_permissions(const char* pkg_id)//deprecated
+{
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
+                               __func__, pkg_id);
 
-       return ret;
+       return perm_app_reset_permissions(pkg_id);
 }
 
-static int app_register_av_internal(const char *app_av_id, struct smack_accesses* smack)
+API int perm_app_reset_permissions(const char* pkg_id)
 {
-       SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s.",
-                               __func__, app_av_id);
-
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
+                               __func__, pkg_id);
        int ret;
-       int i;
 
-       char** smack_label_app_list AUTO_FREE;
-       int smack_label_app_list_len = 0;
-
-       if (!smack_label_is_valid(app_av_id)) {
-               C_LOGE("Invalid param app_av_id.");
+       if (!smack_label_is_valid(pkg_id)) {
+               C_LOGE("Invalid param pkg_id.");
                return PC_ERR_INVALID_PARAM;
        }
 
-       if(smack == NULL) {
-               C_LOGE("Invalid param smack (NULL).");
-               return PC_ERR_INVALID_PARAM;
+       ret = rdb_reset_app_permissions(pkg_id);
+       if (ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
+               return ret;
        }
 
-       // writing anti_virus_id (app_av_id) to "database"
-       ret = add_av_id_to_databse(app_av_id);
-       if (ret != PC_OPERATION_SUCCESS )
-               goto out;
+       return PC_OPERATION_SUCCESS;
+}
 
-       // Reading labels of all installed apps from "database"
-       ret = get_all_apps_ids(&smack_label_app_list, &smack_label_app_list_len);
-       if (ret != PC_OPERATION_SUCCESS ) {
-               C_LOGE("Error while getting installed apps from database.");
-               goto out;
-       }
-       for (i = 0; i < smack_label_app_list_len; ++i) {
-               SECURE_C_LOGD("Applying rwx rule for %s", smack_label_app_list[i]);
-               if (smack_accesses_add_modify(smack, app_av_id, smack_label_app_list[i], "wrx", "") == -1) {
-                       C_LOGE("smack_accesses_add_modify failed.");
-                       ret = PC_ERR_INVALID_OPERATION;
-                       goto out;
-                       // Should we abort adding rules once smack_accesses_add_modify will fail?
-               }
-       }
+API int app_label_dir(const char* label, const char* path)//deprecated
+{
+       SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
+                               __func__, label, path);
 
-       // Giving anti virus RWX access to public RO folders
-       ret = give_anti_virus_access_to_all_folders(app_av_id, smack, APP_PATH_PUBLIC_RO);
-       if (ret != PC_OPERATION_SUCCESS ) {
-               C_LOGE("Error while getting public RO folders from database.");
-               goto out;
+       int ret = PC_OPERATION_SUCCESS;
+
+       if(path == NULL) {
+               C_LOGE("Invalid argument path (NULL).");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       // Giving anti virus RWX access to groups RW folders
-       ret = give_anti_virus_access_to_all_folders(app_av_id, smack, APP_PATH_GROUP_RW);
-       if (ret != PC_OPERATION_SUCCESS ) {
-               C_LOGE("Error while getting groups RW folders from database.");
-               goto out;
+       if (!smack_label_is_valid(label)) {
+               C_LOGE("Invalid param label.");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       // Giving anti virus RWX access to settings RW folders
-       ret = give_anti_virus_access_to_all_folders(app_av_id, smack, APP_PATH_SETTINGS_RW);
-       if (ret != PC_OPERATION_SUCCESS ) {
-               C_LOGE("Error while getting settings RW folders from database.");
-               goto out;
+       //setting access label on everything in given directory and below
+       ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
+       if (PC_OPERATION_SUCCESS != ret)
+       {
+               C_LOGE("dir_set_smack_r failed.");
+               return ret;
        }
 
-out:
-       for (i = 0; i < smack_label_app_list_len; ++i) {
-               free(smack_label_app_list[i]);
+       //setting execute label for everything with permission to execute
+       ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
+       if (PC_OPERATION_SUCCESS != ret)
+       {
+               C_LOGE("dir_set_smack_r failed.");
+               return ret;
        }
 
+       //setting execute label for everything with permission to execute
+       ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
        return ret;
 }
 
-/**
- *  This function will find labels of all anti viruses in database
- *  and for all of them will add a rule "anti_virus_label app_id rwx".
- *  This should be called in app_install function.
- */
-static int register_app_for_av(const char * app_id)
+
+API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
 {
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s.",
-                               __func__, app_id);
+       SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
+                               __func__, app_label, shared_label, path);
+       int ret;
 
-       int ret, i;
-       char** smack_label_av_list AUTO_FREE;
-       int smack_label_av_list_len = 0;
-
-       // Reading labels of all installed anti viruses from "database"
-       ret = get_all_avs_ids(&smack_label_av_list, &smack_label_av_list_len);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("Error while geting data from database.");
-               return ret;
-       }
-
-       // for each anti-virus label put rule: "anti_virus_label app_id rwx"
-       for (i = 0; i < smack_label_av_list_len; ++i) {
-               SECURE_C_LOGD("Antivirus: app_add_rule (%s, %s rx)", smack_label_av_list[i], app_id);
-               if (strcmp(app_id, smack_label_av_list[i])==0) {
-                       SECURE_C_LOGW("Trying to add antivirus rule for self. Skipping");
-                       continue;
-               }
-               ret = app_add_rule(smack_label_av_list[i], app_id, "wrx");
-               if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("app_add_rule failed.");
-                       goto out;
-               }
-
-               free(smack_label_av_list[i]);
-       }
-
-       ret = PC_OPERATION_SUCCESS;
-
-out:
-       // If something failed, then no entry of smack_label_av_list[i]
-       // was deallocated. They all must be freed.
-       for(; i<smack_label_av_list_len; ++i) {
-               free(smack_label_av_list[i]);
-       }
-
-       return ret;
-}
-
-/**
- *  This function will find labels of all setting applications in database
- *  and for all of them will add a rule "appsetting_id app_id rwx".
- *  This should be called in app_install function.
- */
-static int register_app_for_appsetting(const char *app_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-
-       int ret, i;
-       char **smack_label_list AUTO_FREE;
-       int smack_label_list_len = 0;
-
-       /* Reading labels of all installed setting managers from "database"*/
-       ret = get_all_appsetting_ids(&smack_label_list, &smack_label_list_len);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("Error while geting data from database.");
-               return ret;
-       }
-
-       /* for each appsetting put rule: "appsetting_id app_id rx"*/
-       for (i = 0; i < smack_label_list_len; ++i) {
-               SECURE_C_LOGD("Appsetting: app_add_rule (%s, %s rx)", smack_label_list[i], app_id);
-               if (strcmp(app_id, smack_label_list[i])==0) {
-                       SECURE_C_LOGW("Trying to add setting rule for self. Skipping");
-                       continue;
-               }
-
-               ret = app_add_rule(smack_label_list[i], app_id, "rx");
-               if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("app_add_rule failed");
-                       goto out;
-               }
-
-               free(smack_label_list[i]);
-       }
-
-       ret = PC_OPERATION_SUCCESS;
-
-out:
-       /* If something failed, then no entry of smack_label_list[i]
-        was deallocated. They all must be freed.*/
-       for (; i < smack_label_list_len; ++i) {
-               free(smack_label_list[i]);
-       }
-
-       return ret;
-}
-
-
-/**
- *  This function will grant app_id rx access to all public directories and
- *  files previously designated by app_setup_path(APP_PATH_PUBLIC_RO)
- *  This should be called in app_install function.
- */
-static int register_app_for_public_dirs(const char *app_id, struct smack_accesses *smack)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-       int ret, i;
-       char **public_dirs AUTO_FREE;
-       int public_dirs_cnt = 0;
-
-       ret = db_get_public_dirs(&public_dirs, &public_dirs_cnt);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("Error while getting data from database");
-               return ret;
-       }
-
-       for (i = 0; i < public_dirs_cnt; ++i) {
-               SECURE_C_LOGD("Allowing app %s to access public path %s", app_id, public_dirs[i]);
-               if (smack_accesses_add_modify(smack, app_id, public_dirs[i], "rx", "")) {
-                       C_LOGE("app_add_rule_modify failed");
-                       while (i < public_dirs_cnt)
-                               free(public_dirs[i++]);
-                       return PC_ERR_INVALID_OPERATION;
-               }
-               free(public_dirs[i]);
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
-                               __func__, app_id, app_type, permanent);
-
-       int i, ret;
-       char* smack_path AUTO_FREE;
-       char* smack_path_early AUTO_FREE;
-       int fd AUTO_CLOSE;
-       int fd_early AUTO_CLOSE;
-       struct smack_accesses *smack AUTO_SMACK_FREE;
-       struct smack_accesses *smack_early AUTO_SMACK_FREE;
-       const char* base_perm = NULL;
-
-       if (!smack_label_is_valid(app_id)) {
-               C_LOGE("Invalid param app_id.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       if(perm_list == NULL) {
-               C_LOGE("Invalid perm_list (NULL).");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("load_smack_from_file failed");
-               return ret;
-       }
-
-       ret = load_smack_from_file_early(app_id, &smack_early, &fd_early, &smack_path_early);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("load_smack_from_file failed");
-               return ret;
-       }
-
-       /* Implicitly enable base permission for an app_type */
-       base_perm = app_type_name(app_type);
-       if (base_perm) {
-               SECURE_C_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
-               ret = perm_to_smack(smack, app_id, APP_TYPE_OTHER, base_perm);
-               if (ret != PC_OPERATION_SUCCESS){
-                       C_LOGE("perm_to_smack failed");
-                       return ret;
-               }
-
-               // Add early permission - such permissions should be enabled right after system boot
-               SECURE_C_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
-               ret = perm_to_smack_early(smack_early, app_id, APP_TYPE_OTHER, base_perm);
-               if (ret != PC_OPERATION_SUCCESS){
-                       C_LOGE("perm_to_smack failed");
-                       return ret;
-               }
-
-       }
-       for (i = 0; perm_list[i] != NULL; ++i) {
-               SECURE_C_LOGD("perm_to_smack params: app_id: %s, perm_list[%d]: %s", app_id, i, perm_list[i]);
-               if (strcmp(perm_list[i], TIZEN_PRIVILEGE_ANTIVIRUS) == 0) {
-                       ret = app_register_av_internal(app_id, smack);
-                       if (ret != PC_OPERATION_SUCCESS) {
-                               C_LOGE("app_register_av_internal failed");
-                               return ret;
-                       }
-               }
-               if (strcmp(perm_list[i], TIZEN_PRIVILEGE_APPSETTING) == 0) {
-                       ret = app_register_appsetting(app_id, smack);
-                       if (ret != PC_OPERATION_SUCCESS) {
-                               C_LOGE("app_register_appsetting failed");
-                               return ret;
-                       }
-               }
-
-               ret = perm_to_smack(smack, app_id, app_type, perm_list[i]);
-               if (ret != PC_OPERATION_SUCCESS){
-                       C_LOGE("perm_to_smack failed");
-                       return ret;
-               }
-
-               ret = perm_to_smack_early(smack_early, app_id, app_type, perm_list[i]);
-               if (ret != PC_OPERATION_SUCCESS){
-                       C_LOGE("perm_to_smack_early failed");
-                       return ret;
-               }
-
-               ret = perm_to_dac(app_id, app_type, perm_list[i]);
-               if (ret != PC_OPERATION_SUCCESS){
-                       C_LOGE("perm_to_dac failed");
-                       return ret;
-               }
-       }
-
-       if (have_smack() && smack_accesses_apply(smack)) {
-               C_LOGE("smack_accesses_apply failed");
-               return PC_ERR_INVALID_OPERATION;
-       }
-
-       if (have_smack() && smack_accesses_apply(smack_early)) {
-               C_LOGE("smack_accesses_apply (early) failed");
-               return PC_ERR_INVALID_OPERATION;
-       }
-
-       if (permanent && smack_accesses_save(smack, fd)) {
-               C_LOGE("smack_accesses_save failed");
-               return PC_ERR_INVALID_OPERATION;
-       }
-
-       if (permanent && smack_accesses_save(smack_early, fd_early)) {
-               C_LOGE("smack_accesses_save (early) failed");
-               return PC_ERR_INVALID_OPERATION;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-
-       return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
-}
-
-API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-
-       return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 0);
-}
-
-API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
-{
-       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
-                               __func__, pkg_id, app_type, persistent);
-
-       return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
-}
-
-API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
-                               __func__, pkg_id, app_type, persistent);
-
-       return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
-}
-
-API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
-{
-       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
-                               __func__, pkg_id, app_type);
-
-       return perm_app_disable_permissions(pkg_id, app_type, perm_list);
-}
-
-/* FIXME: this function is only a stub */
-API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
-                               __func__, pkg_id, app_type);
-
-       return PC_OPERATION_SUCCESS;
-}
-
-static int app_revoke_permissions_internal(const char* app_id, bool persistent)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, persistent=%d",
-                               __func__, app_id, persistent);
-
-       char* smack_path AUTO_FREE;
-       int ret;
-       int fd AUTO_CLOSE;
-       struct smack_accesses *smack AUTO_SMACK_FREE;
-
-       if (!smack_label_is_valid(app_id)) {
-               C_LOGE("Invalid param app_id.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("load_smack_from_file failed.");
-               return ret;
-       }
-
-       if (have_smack() && smack_accesses_clear(smack)) {
-               ret = PC_ERR_INVALID_OPERATION;
-               C_LOGE("smack_accesses_clear failed.");
-               return ret;
-       }
-
-       if (have_smack() && smack_revoke_subject(app_id)) {
-               ret = PC_ERR_INVALID_OPERATION;
-               C_LOGE("smack_revoke_subject failed.");
-               return ret;
-       }
-
-       if (persistent && ftruncate(fd, 0) == -1)
-               C_LOGW("file truncation failed");
-
-       return PC_OPERATION_SUCCESS;
-}
-
-API int app_revoke_permissions(const char* pkg_id)//deprecated
-{
-       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
-       return perm_app_revoke_permissions(pkg_id);
-}
-
-API int perm_app_revoke_permissions(const char* pkg_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
-       int ret;
-
-       if (!smack_label_is_valid(pkg_id)) {
-               C_LOGE("Invalid param app_id.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       ret = app_revoke_permissions_internal(pkg_id, true);
-       if (ret) {
-               C_LOGE("Revoking permissions failed.");
-               return ret;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-API int app_reset_permissions(const char* pkg_id)//deprecated
-{
-       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
-                               __func__, pkg_id);
-
-       return perm_app_reset_permissions(pkg_id);
-}
-
-API int perm_app_reset_permissions(const char* pkg_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
-                               __func__, pkg_id);
-
-       int ret;
-
-       if (!smack_label_is_valid(pkg_id)) {
-               C_LOGE("Invalid param pkg_id.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       ret = app_revoke_permissions_internal(pkg_id, false);
-       if (ret) {
-               C_LOGE("Revoking permissions failed.");
-               return ret;
-       }
-
-       /* Add empty permissions set to trigger re-read of rules */
-       return perm_app_enable_permissions(pkg_id, APP_TYPE_OTHER, (const char*[]){NULL}, 0);
-}
-
-API int app_label_dir(const char* label, const char* path)//deprecated
-{
-       SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
-                               __func__, label, path);
-
-       int ret = PC_OPERATION_SUCCESS;
-
-       if(path == NULL) {
-               C_LOGE("Invalid argument path (NULL).");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       if (!smack_label_is_valid(label)) {
-               C_LOGE("Invalid param label.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       //setting access label on everything in given directory and below
-       ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
-       if (PC_OPERATION_SUCCESS != ret)
-       {
-               C_LOGE("dir_set_smack_r failed.");
-               return ret;
-       }
-
-       //setting execute label for everything with permission to execute
-       ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
-       if (PC_OPERATION_SUCCESS != ret)
-       {
-               C_LOGE("dir_set_smack_r failed.");
-               return ret;
-       }
-
-       //setting execute label for everything with permission to execute
-       ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
-       return ret;
-}
-
-static int app_uninstall_remove_early_rules(const char *app_id)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-
-       int ret;
-       int fd AUTO_CLOSE;
-       int size;
-       char tmp;
-       char *data, *data_end;
-       char *line_begin, *line_end, *write_pos;
-       char subject[SMACK_LABEL_LEN + 1];
-       char object[SMACK_LABEL_LEN + 1];
-
-       SECURE_C_LOGD("Opening file %s.", SMACK_STARTUP_RULES_FILE);
-       fd = open(SMACK_STARTUP_RULES_FILE, O_RDWR);
-       if (fd < 0) {
-               SECURE_C_LOGE("Unable to open file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
-               return PC_ERR_FILE_OPERATION;
-       }
-
-       if (flock(fd, LOCK_EX)) {
-               SECURE_C_LOGE("flock failed, error %s", strerror(errno));
-               return PC_ERR_FILE_OPERATION;
-       }
-
-       size = lseek(fd, 0, SEEK_END);
-       if (size < 0) {
-               SECURE_C_LOGE("Unable to read file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
-               return PC_ERR_FILE_OPERATION;
-       }
-
-       if (size == 0)
-               return PC_OPERATION_SUCCESS;
-
-       data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-       if (data == MAP_FAILED) {
-               SECURE_C_LOGE("Unable to read file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
-               return PC_ERR_FILE_OPERATION;
-       }
-       data_end = data + size;
-
-       line_begin = write_pos = data;
-       while (line_begin < data_end) {
-               line_end = memchr(line_begin, '\n', data_end - line_begin);
-               if (line_end == NULL)
-                       line_end = data_end - 1;
-
-               tmp = *line_end;
-               *line_end = '\0';
-               SECURE_C_LOGD("Considering early rule: %s", line_begin);
-
-               ret = sscanf(line_begin, "%" TOSTRING(SMACK_LABEL_LEN) "s %" TOSTRING(SMACK_LABEL_LEN) "s", subject, object);
-               if (ret != 2) {
-                       C_LOGD("Rule format is invalid, skipping it.");
-                       goto loop_next;
-               }
-
-               if (!strcmp(subject, app_id) || !strcmp(object, app_id)) {
-                       C_LOGD("Rule belongs to an app being removed, skipping it.");
-                       goto loop_next;
-               }
-
-               C_LOGD("Rule still needed, keeping it.");
-               *line_end = tmp;
-               if (write_pos != line_begin)
-                       memcpy(write_pos, line_begin, line_end - line_begin + 1);
-               write_pos += (line_end - line_begin + 1);
-
-       loop_next:
-               *line_end = tmp;
-               line_begin = line_end + 1;
-       }
-
-       munmap(data, size);
-       ret = ftruncate(fd, write_pos - data);
-       if (ret < 0) {
-               SECURE_C_LOGE("Unable to truncate file %s to %d bytes: %s", SMACK_STARTUP_RULES_FILE, write_pos, strerror(errno));
-
-               return PC_ERR_FILE_OPERATION;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
-                               __func__, app_label, shared_label, path);
-       int ret;
-
-       if(path == NULL) {
-               C_LOGE("Invalid param path.");
-               return PC_ERR_INVALID_PARAM;
-       }
+       if(path == NULL) {
+               C_LOGE("Invalid param path.");
+               return PC_ERR_INVALID_PARAM;
+       }
 
        if(!smack_label_is_valid(app_label)) {
                C_LOGE("Invalid param app_label");
@@ -1789,46 +1205,18 @@ API int app_label_shared_dir(const char* app_label, const char* shared_label, co
                return ret;
        }
 
-       ret = app_add_rule(app_label, shared_label, "rwxat");
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("app_add_rule failed");
-               return ret;
-       }
-
        return PC_OPERATION_SUCCESS;
 }
 
-API int add_shared_dir_readers(const char* shared_label, const char** app_list)//deprecated
+API int add_shared_dir_readers(const char* shared_label UNUSED, const char** app_list UNUSED)//deprecated
 {
        SECURE_C_LOGD("Entering function: %s. Params: shared_label=%s",
                                __func__, shared_label);
-       int ret;
-       int i;
-
-       if(app_list == NULL) {
-               C_LOGE("Invalid param app_list.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       if (!smack_label_is_valid(shared_label)) {
-               C_LOGE("Invalid param shared_label.");
-               return PC_ERR_INVALID_PARAM;
-       }
 
-       for (i = 0; app_list[i] != NULL; i++) {
-               if (!smack_label_is_valid(app_list[i])) {
-                       C_LOGE("Invalid %d element from param app_list.", i);
-                       return PC_ERR_INVALID_PARAM;
-               }
-
-               ret = app_add_rule(app_list[i], shared_label, "rx");
-               if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("app_add_rule failed.");
-                       return ret;
-               }
-       }
+       C_LOGE("add_shared_dir_readers is deprecated and unimplemented!");
 
-       return PC_OPERATION_SUCCESS;
+       // TODO: This function is not implemented with RDB.
+       return PC_ERR_INVALID_OPERATION;
 }
 
 static char* smack_label_for_path(const char *app_id, const char *path)
@@ -1861,84 +1249,6 @@ static char* smack_label_for_path(const char *app_id, const char *path)
 
        return label;
 }
-/*
- * This function should be called in perm_app_setup_path_internal().
- * After installation of new application (pkg_id) and labeling its shared directory (RW or RO),
- * all others apps installed on system should get rules to this shared directory.
- * This function will add and store those rules in rule-file of new installed app (pkg_id)
- */
-static int add_other_apps_rules_for_shared_dir(const char *pkg_id, const char *type_of_shared_dir, const char *shared_dir_label)
-{
-       C_LOGD("Enter function: %s", __func__);
-
-       int ret;
-       int fd AUTO_CLOSE;
-       char *smack_path AUTO_FREE;
-       char *smack_rules_file_path AUTO_FREE;
-       struct smack_accesses* smack AUTO_SMACK_FREE;
-
-       ret = load_smack_from_file(pkg_id, &smack, &fd, &smack_path);
-       if (ret != PC_OPERATION_SUCCESS ) {
-               C_LOGE("load_smack_from_file failed: %d", ret);
-               return ret;
-       }
-
-       ret = asprintf(&smack_rules_file_path, TOSTRING(SHAREDIR)"/%s", type_of_shared_dir);
-       if (ret < 0) {
-               C_LOGE("asprintf failed");
-               return PC_ERR_MEM_OPERATION;
-       }
-
-       ret = perm_to_smack_from_file(smack, shared_dir_label, SMACK_SHARED_DIR_LABEL_TEMPLATE, smack_rules_file_path);
-       if (ret != PC_OPERATION_SUCCESS ) {
-               C_LOGE("perm_to_smack_from_file failed: %d", ret);
-       }
-
-       if (have_smack() && smack_accesses_apply(smack)) {
-               C_LOGE("smack_accesses_apply failed");
-               return PC_ERR_INVALID_OPERATION;
-       }
-
-       if (smack_accesses_save(smack, fd)) {
-               C_LOGE("smack_accesses_save failed");
-               return PC_ERR_INVALID_OPERATION;
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
-
-/* Add all anti-viruses RWX access to specific label.
- * This function should be used grant anti-viruses access to
- * public RO/group RW shared folder
- * const char *path param is used only for logs.
- */
-static int add_all_anti_viruses_access_to_label(const char *label, const char *path)
-{
-       int i;
-       int ret;
-       int avs_ids_cnt = 0;
-       char **avs_ids AUTO_FREE;
-
-       /* Add all anti-viruses RWX access to public RO shared folder */
-       ret = get_all_avs_ids(&avs_ids, &avs_ids_cnt);
-       if (ret != PC_OPERATION_SUCCESS ) {
-               C_LOGE("get_all_avs_ids failed.");
-               return ret;
-       }
-       for (i = 0; i < avs_ids_cnt; ++i) {
-               SECURE_C_LOGD("Allowing anti-virus %s to RWX access public path %s", avs_ids[i], path);
-               ret = app_add_rule(avs_ids[i], label, "rwx");
-               if (ret != PC_OPERATION_SUCCESS ) {
-                       C_LOGE("app_add_rule failed");
-                       while (i < avs_ids_cnt)
-                               free(avs_ids[i++]);
-                       return ret;
-               }
-               free(avs_ids[i]);
-       }
-
-       return PC_OPERATION_SUCCESS;
-}
 
 /* FIXME: remove this pragma once deprecated API is deleted */
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@@ -1980,147 +1290,81 @@ static int perm_app_setup_path_internal(const char* pkg_id, const char* path, ap
                        return PC_ERR_INVALID_PARAM;
                }
 
-               ret = app_label_shared_dir(pkg_id, shared_label, path);
-               if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("app_label_shared_dir failed: %d", ret);
-                       return ret;
-               }
-
-               /* FIXME: This should be in some kind of transaction/lock */
-               ret = db_add_groups_dir(shared_label);
+               // Add the path to the database:
+               ret = rdb_add_path(pkg_id, shared_label, path, "rwxatl", "GROUP_RW");
                if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("db_add_groups_dir failed.");
+                       C_LOGE("RDB rdb_add_path failed with: %d", ret);
                        return ret;
                }
 
-               /* Add all anti-viruses RWX access to groups RW shared folder */
-               ret = add_all_anti_viruses_access_to_label(shared_label, path);
+               ret = app_label_shared_dir(pkg_id, shared_label, path);
                if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("add_all_anti_viruses_access_to_label failed");
+                       C_LOGE("app_label_shared_dir failed: %d", ret);
                        return ret;
                }
 
-               return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_GROUP_RW, shared_label);
+               return PC_OPERATION_SUCCESS;
        }
 
        case APP_PATH_PUBLIC_RO: {
                C_LOGD("app_path_type is APP_PATH_PUBLIC_RO.");
                char **app_ids AUTO_FREE;
-               int app_ids_cnt = 0;
                const char *label;
-               int i, ret;
+               int ret;
 
                C_LOGD("New public RO path %s", path);
+
+               // Generate label:
                label = smack_label_for_path(pkg_id, path);
                if (label == NULL) {
                        C_LOGE("smack_label_for_path failed.");
                        return PC_ERR_INVALID_OPERATION;
                }
-
                C_LOGD("Generated label '%s' for public RO path %s", label, path);
-               ret = app_label_shared_dir(pkg_id, label, path);
-               if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("app_label_shared_dir failed.");
-                       return ret;
-               }
-
-               /* FIXME: This should be in some kind of transaction/lock */
-               ret = db_add_public_dir(label);
-               if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("db_add_public_dir failed.");
-                       return ret;
-               }
 
-               ret = get_all_apps_ids(&app_ids, &app_ids_cnt);
+               // Add the path to the database:
+               ret = rdb_add_path(pkg_id, label, path, "rwxatl", "PUBLIC_RO");
                if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("get_all_aps_ids failed.");
+                       C_LOGE("RDB rdb_add_path failed with: %d", ret);
                        return ret;
                }
 
-               for (i = 0; i < app_ids_cnt; ++i) {
-                       SECURE_C_LOGD("Allowing app %s to access public path %s", app_ids[i], path);
-                       ret = app_add_rule(app_ids[i], label, "rx");
-                       if (ret != PC_OPERATION_SUCCESS) {
-                               C_LOGE("app_add_rule failed");
-                               while (i < app_ids_cnt)
-                                       free(app_ids[i++]);
-                               return ret;
-                       }
-                       free(app_ids[i]);
-               }
-
-               /* Add all anti-viruses RWX access to public RO shared folder */
-               ret = add_all_anti_viruses_access_to_label(label, path);
+               ret = app_label_shared_dir(pkg_id, label, path);
                if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("add_all_anti_viruses_access_to_label failed");
+                       C_LOGE("app_label_shared_dir failed.");
                        return ret;
                }
-
-               return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_PUBLIC_RO, label);
+               return PC_OPERATION_SUCCESS;
        }
 
-       case APP_PATH_SETTINGS_RW:
-       {
+       case APP_PATH_SETTINGS_RW: {
                C_LOGD("app_path_type is APP_PATH_SETTINGS_RW.");
                char **app_ids AUTO_FREE;
-               int app_ids_cnt = 0;
                const char *label;
-               int i;
                int ret;
 
-               /*get path id*/
+               // Generate label:
                label = smack_label_for_path(pkg_id, path);
                if (label == NULL) {
                        C_LOGE("smack_label_for_path failed.");
                        return PC_ERR_INVALID_OPERATION;
                }
-
-               /*set id for path and all subfolders*/
                C_LOGD("Appsetting: generated label '%s' for setting path %s", label, path);
-               ret = app_label_shared_dir(pkg_id, label, path);
-               if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
-                       return ret;
-               }
 
-               /* add path to database */
-               /* FIXME: This should be in some kind of transaction/lock */
-               ret = add_setting_dir_id_to_databse(label);
-               if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("Appsetting: add_setting_dir_id_to_databse failed");
-                       return ret;
-               }
 
-               /*read all apps with appsetting privilege*/
-               ret = get_all_appsetting_ids(&app_ids, &app_ids_cnt);
+               // Add the path to the database:
+               ret = rdb_add_path(pkg_id, label, path, "rwxatl", "SETTINGS_RW");
                if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("Appsetting: get_all_appsetting_ids failed");
+                       C_LOGE("RDB rdb_add_path failed with: %d", ret);
                        return ret;
                }
-               C_LOGD("Appsetting: %d appsetting privileged apps registered",
-                               app_ids_cnt);
-
-               /*give RWX rights to all apps that have appsetting privilege*/
-               for (i = 0; i < app_ids_cnt; ++i) {
-                       C_LOGD("Appsetting: allowing app %s to access setting path %s",
-                                       app_ids[i], label);
-                       ret = app_add_rule(app_ids[i], label, "rwx");
-                       if (ret != PC_OPERATION_SUCCESS) {
-                               C_LOGE("app_add_rule failed");
-                               while (i < app_ids_cnt)
-                                       free(app_ids[i++]);
-                               return ret;
-                       }
-                       free(app_ids[i]);
-               }
 
-               /* Add all anti-viruses RWX access to settings RW shared folder */
-               ret = add_all_anti_viruses_access_to_label(label, path);
+               /*set id for path and all subfolders*/
+               ret = app_label_shared_dir(pkg_id, label, path);
                if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("add_all_anti_viruses_access_to_label failed");
+                       C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
                        return ret;
                }
-
                return PC_OPERATION_SUCCESS;
        }
 
@@ -2176,31 +1420,15 @@ API int app_add_friend(const char* pkg_id1, const char* pkg_id2)//deprecated
        return perm_app_add_friend(pkg_id1, pkg_id2);
 }
 
-API int perm_app_add_friend(const char* pkg_id1, const char* pkg_id2)
+API int perm_app_add_friend(const char* pkg_id1 UNUSED, const char* pkg_id2 UNUSED)
 {
        SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
                                __func__, pkg_id1, pkg_id2);
 
-       int ret;
-
-       if (!smack_label_is_valid(pkg_id1) || !smack_label_is_valid(pkg_id2)) {
-               C_LOGE("Invalid pkg_id1 or pkg_id2.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       ret = app_add_rule(pkg_id1, pkg_id2, "rwxat");
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("app_add_rule failed");
-               return ret;
-       }
-
-       ret = app_add_rule(pkg_id2, pkg_id1, "rwxat");
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("app_add_rule failed");
-               return ret;
-       }
+       C_LOGE("app_register_av is deprecated and unimplemented!");
 
-       return PC_OPERATION_SUCCESS;
+       // TODO: This function is not implemented with RDB.
+       return PC_ERR_INVALID_OPERATION;
 }
 
 API int app_install(const char* pkg_id)//deprecated
@@ -2215,63 +1443,29 @@ API int perm_app_install(const char* pkg_id)
 {
        SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
                                __func__, pkg_id);
-
        int ret;
        int fd AUTO_CLOSE;
        char* smack_path AUTO_FREE;
        struct smack_accesses *smack AUTO_SMACK_FREE;
 
-       if (!smack_label_is_valid(pkg_id)) {
-               C_LOGE("Invalid param pkg_id.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       ret = smack_file_name(pkg_id, &smack_path);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("smack_file_name failed.");
-               return ret;
-       }
-
-       ret = load_smack_from_file(pkg_id, &smack, &fd, &smack_path);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("load_smack_from_file failed");
-               return ret;
-       }
-
-       ret = add_app_id_to_databse(pkg_id);
-       if (ret != PC_OPERATION_SUCCESS ) {
-               SECURE_C_LOGE("Error while adding app %s to database: %s ", pkg_id, strerror(errno));
-               return ret;
-       }
-
-       ret = register_app_for_av(pkg_id);
-       if (ret != PC_OPERATION_SUCCESS) {
-               SECURE_C_LOGE("Error while adding rules for anti viruses to app %s: %s ", pkg_id, strerror(errno));
+       ret = perm_modification_start();
+       if(ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB perm_modification_start failed with: %d", ret);
                return ret;
        }
 
-       ret = register_app_for_appsetting(pkg_id);
-       if (ret != PC_OPERATION_SUCCESS) {
-               SECURE_C_LOGE("Error while adding rules for setting managers to app %s: %s ", pkg_id, strerror(errno));
-               return ret;
+       if (!smack_label_is_valid(pkg_id)) {
+               C_LOGE("Invalid param pkg_id.");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       ret = register_app_for_public_dirs(pkg_id, smack);
+       // Add application to the database:
+       ret = rdb_add_application(pkg_id);
        if (ret != PC_OPERATION_SUCCESS) {
-               SECURE_C_LOGE("Error while adding rules for access to public dirs for app %s: %s ", pkg_id, strerror(errno));
+               C_LOGE("RDB rdb_add_application failed with: %d", ret);
                return ret;
        }
 
-       if (have_smack() && smack_accesses_apply(smack)) {
-               C_LOGE("smack_accesses_apply failed");
-               return PC_ERR_INVALID_OPERATION;
-       }
-
-       if (smack_accesses_save(smack, fd)) {
-               C_LOGE("smack_accesses_save failed");
-               return PC_ERR_INVALID_OPERATION;
-       }
-
        return PC_OPERATION_SUCCESS;
 }
 
@@ -2285,9 +1479,6 @@ API int app_uninstall(const char* pkg_id)//deprecated
 
 API int perm_app_uninstall(const char* pkg_id)
 {
-       // TODO: When real database will be used, then this function should remove app_id
-       //       from database.
-       //       It also should remove rules like: "anti_virus_label app_id rwx".
        SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
        char* smack_path AUTO_FREE;
        int ret;
@@ -2297,117 +1488,18 @@ API int perm_app_uninstall(const char* pkg_id)
                return PC_ERR_INVALID_PARAM;
        }
 
-       ret = smack_file_name(pkg_id, &smack_path);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("smack_file_name failed.");
-               return ret;
-       }
-
-       if (unlink(smack_path)) {
-               C_LOGE("unlink failed (error: %s)", strerror(errno));
-               return PC_OPERATION_SUCCESS;
-       }
-
-       ret = app_uninstall_remove_early_rules(pkg_id);
+       // Remove application from the database
+       ret = rdb_remove_application(pkg_id);
        if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("app_uninstall_remove_early_rules failed.");
+               C_LOGE("RDB rdb_remove_application failed with: %d", ret);
                return ret;
        }
 
        return PC_OPERATION_SUCCESS;
 }
 
-static int save_rules(int fd, struct smack_accesses* accesses) {
-       SECURE_C_LOGD("Entering function: %s. Params: fd=%d", __func__, fd);
-
-       if (flock(fd, LOCK_EX)) {
-               C_LOGE("flock failed (error: %s)", strerror(errno));
-               return PC_ERR_FILE_OPERATION;
-       }
-
-       if (smack_accesses_save(accesses, fd)) {
-               C_LOGE("smack_accesses_save failed");
-               return PC_ERR_FILE_OPERATION;
-       }
-       return PC_OPERATION_SUCCESS ;
-}
-
-static int label_valid(const char *label) {
-       if (label == NULL)
-               return 0;
-
-       // allow ~APP~ template when adding new feature
-       if (strcmp(label, SMACK_APP_LABEL_TEMPLATE) == 0)
-               return 1;
-
-       return smack_label_is_valid(label);
-}
-
-static int validate_and_add_rule(char* rule, struct smack_accesses* accesses) {
-       SECURE_C_LOGD("Entering function: %s. Params: rule=%s",
-                               __func__, rule);
-
-       const char* subject = NULL;
-       const char* object = NULL;
-       const char* access = NULL;
-       char* saveptr = NULL;
-
-       subject = strtok_r(rule, " \t\n", &saveptr);
-       object = strtok_r(NULL, " \t\n", &saveptr);
-       access = strtok_r(NULL, " \t\n", &saveptr);
-
-       // check rule validity
-       if (access == NULL ||
-               strtok_r(NULL, " \t\n", &saveptr) != NULL ||
-               !label_valid(subject) ||
-               !label_valid(object))
-       {
-               C_LOGE("Incorrect rule format: %s", rule);
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       if (smack_accesses_add(accesses, subject, object, access)) {
-               C_LOGE("smack_accesses_add failed");
-               return PC_ERR_INVALID_OPERATION;
-       }
-       return PC_OPERATION_SUCCESS ;
-}
-
-static int parse_and_save_rules(const char** smack_rules,
-               struct smack_accesses* accesses, const char* feature_file) {
-       SECURE_C_LOGD("Entering function: %s. Params: feature_file=%s",
-                               __func__, feature_file);
-
-       size_t i = 0;
-       int fd = 0;
-       int ret = PC_OPERATION_SUCCESS;
-       char* tmp = NULL;
-
-       for (i = 0; smack_rules[i] != NULL ; i++) {
-               // ignore empty lines
-               if (strspn(smack_rules[i], " \t\n") == strlen(smack_rules[i]))
-                       continue;
-
-               tmp = strdup(smack_rules[i]);
-               ret = validate_and_add_rule(tmp, accesses);
-               free(tmp);
-               if (ret != PC_OPERATION_SUCCESS )
-                       return ret;
-       }
-
-       // save to file
-       fd = open(feature_file, O_CREAT | O_WRONLY, 0644);
-       if (fd == -1) {
-               SECURE_C_LOGE("Unable to create file %s. (error: %s)", feature_file, strerror(errno));
-               return PC_ERR_FILE_OPERATION;
-       }
-
-       ret = save_rules(fd, accesses);
-       close(fd);
-       return ret;
-}
-
 static int save_gids(FILE* file, const gid_t* list_of_db_gids, size_t list_size) {
+
        SECURE_C_LOGD("Entering function: %s.", __func__);
        int ret = PC_OPERATION_SUCCESS;
        int written = 0;
@@ -2457,24 +1549,27 @@ API int perm_add_api_feature(app_type_t app_type,
        int ret = PC_OPERATION_SUCCESS;
        char* smack_file AUTO_FREE;
        char* dac_file AUTO_FREE;
-       struct smack_accesses* accesses = NULL;
+       char * base_api_feature_name AUTO_FREE;
        FILE* file = NULL;
+       // struct smack_accesses* accesses = NULL;
+       const char *s_type_name = app_type_name(app_type);
 
-       // TODO check process capabilities
-
-       // get feature SMACK file name
-       ret = perm_file_path(&smack_file, app_type, api_feature_name, ".smack", 0);
-       if (ret != PC_OPERATION_SUCCESS || !smack_file ) {
-               C_LOGE("perm_file_path failed.");
-               return ret;
+       // Check input values
+       if (s_type_name == NULL || !strcmp(s_type_name, "")) {
+               C_LOGE("Unknown api type");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       // check if feature exists
-       if (file_exists(smack_file)) {
-               C_LOGE("Feature file %s already exists", smack_file);
+       if (api_feature_name == NULL || strlen(api_feature_name) == 0) {
+               C_LOGE("Api feature name is empty.");
                return PC_ERR_INVALID_PARAM;
        }
 
+       if (smack_rules && ((ret = validate_all_rules(smack_rules) ) != PC_OPERATION_SUCCESS) ) {
+               C_LOGE("Error in rules list.");
+               return ret;
+       }
+
        // check .dac existence only if gids are supported
        if (list_of_db_gids && list_size > 0) {
                // get feature DAC file name
@@ -2484,22 +1579,7 @@ API int perm_add_api_feature(app_type_t app_type,
                        return ret;
                }
 
-               // check if feature exists
-               if (file_exists(dac_file)) {
-                       C_LOGE("Feature file %s already exists", dac_file);
-                       return PC_ERR_INVALID_PARAM;
-               }
-       }
-
-       // parse & save rules
-       if (smack_rules) {
-               if (smack_accesses_new(&accesses)) {
-                       C_LOGE("smack_acceses_new failed");
-                       return PC_ERR_MEM_OPERATION;
-               }
-
-               ret = parse_and_save_rules(smack_rules, accesses, smack_file);
-               smack_accesses_free(accesses);
+               unlink(dac_file);
        }
 
        // go through gid list
@@ -2508,15 +1588,25 @@ API int perm_add_api_feature(app_type_t app_type,
                SECURE_C_LOGD("Opening file %s.", dac_file);
                file = fopen(dac_file, "w+");
                ret = save_gids(file, list_of_db_gids, list_size);
-               fclose(file);
+               if(file) fclose(file);
+       }
+
+       // remove file in case of failure
+       if (ret != PC_OPERATION_SUCCESS && dac_file) {
+               unlink(dac_file);
+       }
+
+       ret = base_name_from_perm(api_feature_name, &base_api_feature_name);
+       if (ret != PC_OPERATION_SUCCESS){
+               C_LOGE("Error during creating base name: ", ret);
+               return ret;
        }
 
-       // remove both files in case of failure
+       // Save api feature to the database.
+       ret = rdb_add_permission_rules(base_api_feature_name, s_type_name, smack_rules);
        if (ret != PC_OPERATION_SUCCESS) {
-               unlink(smack_file);
-               if (dac_file) {
-                       unlink(dac_file);
-               }
+               C_LOGE("RDB rdb_add_permission_rules failed with: %d", ret);
+               return ret;
        }
 
        return ret;
@@ -2525,58 +1615,13 @@ API int perm_add_api_feature(app_type_t app_type,
 /**
  * This function is marked as deprecated and will be removed
  */
-API int app_register_av(const char* app_av_id)//deprecated
+API int app_register_av(const char* app_av_id UNUSED)//deprecated
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s",
                                __func__, app_av_id);
 
-       int ret;
-       int fd AUTO_CLOSE;
-       char* smack_path AUTO_FREE;
-       struct smack_accesses* smack AUTO_SMACK_FREE;
-
-       if(app_av_id == NULL) {
-               C_LOGE("Invalid param app_av_id.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       ret = load_smack_from_file(app_av_id, &smack, &fd, &smack_path);
-       if (ret != PC_OPERATION_SUCCESS ) {
-               C_LOGE("load_smack_from_file failed");
-               return ret;
-       }
-
-       ret = app_register_av_internal(app_av_id, smack);
-       if (PC_OPERATION_SUCCESS != ret) {
-               C_LOGE("app_register_av_internal failed");
-               return ret;
-       }
-
-       // Add permisions from OSP_antivirus.smack file
-       ret = perm_to_smack(smack, app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
-       if (PC_OPERATION_SUCCESS != ret) {
-               C_LOGE("perm_to_smack failed");
-               return ret;
-       }
-
-       // Add permisions from OSP_antivirus.dac file
-       ret = perm_to_dac(app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
-       if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("perm_to_dac failed");
-               return ret;
-       }
-
-       if (have_smack() && smack_accesses_apply(smack)) {
-               C_LOGE("smack_accesses_apply failed");
-               ret = PC_ERR_INVALID_OPERATION;
-               return ret;
-       }
-
-       if (smack_accesses_save(smack, fd)) {
-               C_LOGE("smack_accesses_save failed");
-               ret = PC_ERR_INVALID_OPERATION;
-               return ret;
-       }
+       C_LOGE("app_register_av is deprecated and unimplemented!");
 
-       return ret;
+       // TODO: This function is not implemented with RDB.
+       return PC_ERR_INVALID_OPERATION;
 }
diff --git a/src/rules-db-internals.c b/src/rules-db-internals.c
new file mode 100644 (file)
index 0000000..c5d9956
--- /dev/null
@@ -0,0 +1,1072 @@
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+* @file        rules-db-internals.c
+* @author      Jan Olszak (j.olszak@samsung.com)
+* @version     1.0
+* @brief       Definition of internal functions of the rules-db API.
+*/
+
+#include <errno.h>      // For error logging
+#include <stdarg.h>     // For handling multiple arguments
+#include <stdlib.h>     // For free
+#include <stdio.h>      // For file manipulation
+#include "common.h"     // For smack_label_is_valid
+#include <unistd.h>     // For sleep
+
+#include "rules-db-internals.h"
+#include "rules-db.h"
+
+#define RDB_MAX_QUERY_ATTEMPTS    50
+#define RDB_TIME_BETWEEN_ATTEMPTS 1 // sec
+
+
+
+
+/**
+ * Helper function. Use on INSERT or DELETE or UPDATE, when not interested in returned value
+ *
+ * @ingroup RDB: internal functions
+ *
+ * @param  p_stmt SQLite3 statement
+ * @return        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+static int step_and_convert_returned_value(sqlite3_stmt *p_stmt)
+{
+       if(sqlite3_step(p_stmt) == SQLITE_DONE) {
+               return PC_OPERATION_SUCCESS;
+       } else {
+               C_LOGE("RDB: Error during stepping: %s",
+                      sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
+               return PC_ERR_DB_QUERY_STEP;
+       }
+}
+
+int add_modified_label_internal(sqlite3 *p_db, const char *const s_label_name)
+{
+       int ret = PC_OPERATION_SUCCESS;
+       sqlite3_stmt *p_stmt = NULL;
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "INSERT OR IGNORE INTO modified_label(name) VALUES(%Q)",
+                          s_label_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+/**
+ * Adds label names of applications with the permission to modified labels.
+ * Used when permission is going to change and we're going to change some
+ * accesses granted by this permission.
+ *
+ *
+ * @param  p_db            [description]
+ * @param  i_permission_id [description]
+ * @return                 [description]
+ */
+int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id)
+{
+       int ret = PC_OPERATION_SUCCESS;
+       sqlite3_stmt *p_stmt = NULL;
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "INSERT INTO modified_label(name)    \
+                           SELECT app_permission_view.app_name \
+                           FROM   app_permission_view          \
+                           WHERE  app_permission_view.permission_id = %d",
+                          i_permission_id);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+/**
+ * Function called when the target database is busy.
+ * We attempt to access the database every
+ * RDB_TIME_BETWEEN_ATTEMPTS seconds
+ *
+ * @param  not_used  not used
+ * @param  i_attempt number of the attempt
+ * @return           0 when stops waiting
+ *                   1 when waiting
+ */
+static int database_busy_handler(void *not_used UNUSED,
+                                int i_attempt)
+{
+       if(i_attempt > RDB_MAX_QUERY_ATTEMPTS) {
+               // I ain't gonna wait for you forever!
+               C_LOGE("RDB: Database busy for too long.");
+               return 0;
+       }
+       C_LOGW("RDB: Database busy, waiting");
+       sleep(RDB_TIME_BETWEEN_ATTEMPTS);
+       return 1;
+}
+
+
+int open_rdb_connection(sqlite3 **p_db)
+{
+       RDB_LOG_ENTRY;
+
+       char *p_err_msg;
+
+       // Open connection:
+       int ret = sqlite3_open_v2(RDB_PATH,
+                                 p_db,
+                                 RDB_READWRITE_FLAG,
+                                 NULL);
+       if(*p_db == NULL) {
+               C_LOGE("RDB: Error opening the database: Unable to allocate memory.");
+               return PC_ERR_DB_CONNECTION;
+       }
+       if(ret != SQLITE_OK) {
+               C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
+               return PC_ERR_DB_CONNECTION;
+       }
+
+       //Register busy handler:
+       if(sqlite3_busy_handler(*p_db, database_busy_handler, NULL) != SQLITE_OK) {
+               C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
+               return PC_ERR_DB_CONNECTION;
+       }
+
+       // Load extensions:
+       if(sqlite3_enable_load_extension(*p_db, 1)) {
+               C_LOGE("RDB: Error enabling extensions: %s", sqlite3_errmsg(*p_db));
+               return PC_ERR_DB_CONNECTION;
+       }
+
+       if(sqlite3_load_extension(*p_db,
+                                 "/usr/lib/librules-db-sql-udf.so", 0,
+                                 &p_err_msg) != SQLITE_OK) {
+
+               C_LOGE("RDB: Error during loading librules-db-sql-udf.so: %s",
+                      p_err_msg);
+               sqlite3_free(p_err_msg);
+               return PC_ERR_DB_CONNECTION;
+       }
+       sqlite3_free(p_err_msg);
+
+
+       // Create the temporary tables:
+       if(sqlite3_exec(*p_db,
+                      "CREATE TEMPORARY TABLE history_smack_rule(                 \
+                               subject VARCHAR NOT NULL,                          \
+                               object  VARCHAR NOT NULL,                          \
+                               access  INTEGER NOT NULL);                         \
+                                                                                  \
+                       CREATE TEMPORARY TABLE modified_label(                     \
+                               name VARCHAR NOT NULL,                             \
+                               UNIQUE(name));                                     \
+                                                                                  \
+                       CREATE TEMPORARY TABLE all_smack_binary_rule_modified(     \
+                               subject VARCHAR NOT NULL,                          \
+                               object  VARCHAR NOT NULL,                          \
+                               access  INTEGER NOT NULL);                         \
+                                                                                  \
+                       CREATE TEMPORARY TABLE history_smack_rule_modified(        \
+                               subject VARCHAR NOT NULL,                          \
+                               object  VARCHAR NOT NULL,                          \
+                               access  INTEGER NOT NULL);                         \
+                                                                                  \
+                        CREATE TEMPORARY VIEW modified_smack_rules AS              \
+                       SELECT  subject, object,                                   \
+                               access_to_str(access_add) AS access_add,           \
+                               access_to_str(access_del) AS access_del            \
+                       FROM    (                                                  \
+                               SELECT     subject, object,                        \
+                                          s1.access & ~s2.access AS access_add,   \
+                                          s2.access & ~s1.access AS access_del    \
+                               FROM       all_smack_binary_rule_modified AS s1    \
+                               INNER JOIN history_smack_rule_modified AS s2       \
+                                          USING (subject, object)                 \
+                               WHERE      s1.access != s2.access                  \
+                               UNION                                              \
+                               SELECT     subject, object,                        \
+                                          s1.access AS access_add,                \
+                                          0 AS access_del                         \
+                               FROM       all_smack_binary_rule_modified s1       \
+                               LEFT JOIN  history_smack_rule_modified s2          \
+                                          USING (subject, object)                 \
+                               WHERE      s2.subject IS NULL AND                  \
+                                          s2.object  IS NULL                      \
+                               UNION                                              \
+                               SELECT     subject, object,                        \
+                                          0 AS access_add,                        \
+                                          s1.access AS access_del                 \
+                               FROM       history_smack_rule_modified s1          \
+                               LEFT JOIN  all_smack_binary_rule_modified s2       \
+                                          USING (subject, object)                 \
+                               WHERE      s2.subject IS NULL AND                  \
+                                          s2.object  IS NULL                      \
+                               )                                                  \
+                       ORDER BY subject, object ASC;                              \
+                       PRAGMA foreign_keys = ON;                                  \
+                       ANALYZE;",
+                       0, 0, 0) != SQLITE_OK) {
+               C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
+               return PC_ERR_DB_OPERATION;
+       }
+
+       return PC_OPERATION_SUCCESS;
+}
+
+
+int prepare_stmt(sqlite3 *p_db,
+                sqlite3_stmt **pp_stmt,
+                const char *const s_sql,
+                ...)
+{
+       int ret = PC_ERR_DB_QUERY_PREP;
+       char *s_query = NULL;
+       va_list args;
+       va_start(args, s_sql);
+
+       s_query = sqlite3_vmprintf(s_sql, args);
+
+       if(s_query == NULL) {
+               C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
+               ret = PC_ERR_DB_QUERY_PREP;
+               goto finish;
+       }
+
+       if(sqlite3_prepare_v2(p_db,
+                             s_query,
+                             strlen(s_query) + 1,
+                             pp_stmt,
+                             NULL)) {
+               C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_QUERY_PREP;
+               goto finish;
+       }
+
+       if(*pp_stmt == NULL) {
+               C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
+               ret = PC_ERR_DB_QUERY_PREP;
+               goto finish;
+       }
+
+       ret = PC_OPERATION_SUCCESS;
+
+finish:
+       va_end(args);
+       sqlite3_free(s_query);
+       return ret;
+}
+
+
+int check_app_label_internal(sqlite3 *p_db,
+                            const char *const s_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "SELECT COUNT(application_view.name) \
+                          FROM application_view                \
+                          WHERE application_view.name=%Q       \
+                          LIMIT 1",
+                          s_label_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = sqlite3_step(p_stmt);
+       if(ret == SQLITE_ROW) {
+               switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
+               case 0: ret = PC_OPERATION_SUCCESS; break;
+               case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
+               }
+
+       } else {
+               C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_QUERY_STEP;
+       }
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int check_label_internal(sqlite3 *p_db,
+                        const char *const s_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "SELECT COUNT(label.name) \
+                          FROM label WHERE name=%Q LIMIT 1",
+                          s_label_name);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = sqlite3_step(p_stmt);
+       if(ret == SQLITE_ROW) {
+               switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
+               case 0: ret = PC_OPERATION_SUCCESS; break;
+               case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
+               }
+
+       } else {
+               C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_QUERY_STEP;
+       }
+
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int add_app_internal(sqlite3 *p_db,
+                    const char *const s_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "INSERT into application_view(name) VALUES(%Q)",
+                          s_label_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int remove_app_internal(sqlite3 *p_db,
+                       const char *const s_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "DELETE FROM application_view \
+                            WHERE application_view.name=%Q",
+                          s_label_name);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int add_path_internal(sqlite3 *p_db,
+                     const char *const s_owner_label_name,
+                     const char *const s_path_label_name,
+                     const char *const s_path,
+                     const char *const s_access,
+                     const char *const s_type)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
+                           s_owner_label_name, s_path_label_name,
+                           s_path, s_access, s_type);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "INSERT INTO path_view(owner_app_label_name, \
+                                                 path,                 \
+                                                 path_label_name,      \
+                                                 access,               \
+                                                 path_type_name)       \
+                            VALUES(%Q, %Q, %Q,  %Q, %Q);",
+                          s_owner_label_name, s_path,
+                          s_path_label_name, s_access, s_type);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int check_permission_internal(sqlite3 *p_db,
+                             const char *const s_permission_name,
+                             const char *const s_permission_type_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "SELECT COUNT(SELECT permission_view.permission_id \
+                                        FROM   permission_view               \
+                                        WHERE  name=%Q AND                   \
+                                               type_name=%Q                  \
+                                        LIMIT 1)",
+                          s_permission_name, s_permission_type_name);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = sqlite3_step(p_stmt);
+       if(ret == SQLITE_ROW) {
+               switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
+               case 0: ret = PC_OPERATION_SUCCESS; break;  // No such permission
+               case 1: ret = PC_PERMISSION_EXISTS; break;  // Permission exists
+               }
+
+       } else {
+               C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_QUERY_STEP;
+       }
+
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int add_permission_internal(sqlite3 *p_db,
+                           const char *const s_permission_name,
+                           const char *const s_permission_type_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "INSERT INTO permission_view(name, type_name) \
+                          VALUES (%Q,%Q)",
+                          s_permission_name, s_permission_type_name);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int get_permission_id_internal(sqlite3 *p_db,
+                              const char *const s_permission_name,
+                              const char *const s_permission_type_name,
+                              sqlite3_int64 *p_permission_id)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "SELECT permission_view.permission_id  \
+                           FROM   permission_view                \
+                           WHERE  permission_view.name = %Q AND  \
+                                  permission_view.type_name = %Q \
+                           LIMIT  1",
+                          s_permission_name, s_permission_type_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = sqlite3_step(p_stmt);
+       if(ret == SQLITE_ROW) {
+               ret = PC_OPERATION_SUCCESS;
+               *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
+       } else if(ret == SQLITE_DONE) {
+               C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
+               ret = PC_ERR_DB_OPERATION;
+
+       } else {
+               C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_QUERY_STEP;
+       }
+
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+
+       return ret;
+}
+
+
+int parse_rule(const char *const s_rule,
+              char s_subject[],
+              char s_object[],
+              char s_access[])
+{
+       int ret = PC_OPERATION_SUCCESS;
+       char *tmp_s_rule = NULL;
+       const char *tmp_s_subject = NULL;
+       const char *tmp_s_object = NULL;
+       const char *tmp_s_access = NULL;
+       char *saveptr = NULL;
+
+       // Parse subject, object and access:
+       tmp_s_rule = strdup(s_rule);
+       tmp_s_subject = strtok_r(tmp_s_rule, " \t\n", &saveptr);
+       tmp_s_object = strtok_r(NULL, " \t\n", &saveptr);
+       tmp_s_access = strtok_r(NULL, " \t\n", &saveptr);
+
+       // Check rule validity:
+       if(tmp_s_subject == NULL ||
+           tmp_s_object == NULL ||
+           tmp_s_access == NULL ||
+           strtok_r(NULL, " \t\n", &saveptr) != NULL) {
+               C_LOGE("RDB: Incorrect rule format: %s", s_rule);
+               ret = PC_ERR_INVALID_PARAM;
+               goto finish;
+       }
+
+       // Copy rules
+       strcpy(s_subject, tmp_s_subject);
+       strcpy(s_object, tmp_s_object);
+       strcpy(s_access, tmp_s_access);
+finish:
+       if(tmp_s_rule) free(tmp_s_rule);
+       return ret;
+}
+
+
+int add_permission_rules_internal(sqlite3 *p_db,
+                                 sqlite3_int64 permission_id,
+                                 const char *const *const pp_smack_rules)
+{
+       RDB_LOG_ENTRY;
+
+       int i;
+       int ret = PC_OPERATION_SUCCESS;
+       sqlite3_stmt *p_stmt = NULL;
+       char s_subject[SMACK_LABEL_LEN + 1];
+       char s_object[SMACK_LABEL_LEN + 1];
+       char s_access[ACC_LEN + 1];
+
+       // Prepare statement.
+       const char *s_query = "INSERT INTO \
+               permission_label_rule_view(permission_id,access,label_name,is_reverse) \
+               VALUES(?,?,?,?)";
+       if(sqlite3_prepare_v2(p_db,
+                             s_query,
+                             strlen(s_query) + 1,
+                             &p_stmt,
+                             NULL)) {
+               C_LOGE("RDB: Error during preparing statement: %s",
+                      sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_QUERY_PREP;
+               goto finish;
+       }
+
+       for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
+               C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
+
+               // Ignore empty lines
+               if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
+                       continue;
+
+               ret = parse_rule(pp_smack_rules[i], s_subject, s_object, s_access);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               // Bind values to the statement and run it:
+               sqlite3_bind_int(p_stmt, 1, permission_id);
+               sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0);
+               if(!strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE)) {
+                       // Not reversed
+                       sqlite3_bind_text(p_stmt, 3, s_object, RDB_AUTO_DETERM_SIZE, 0);
+                       sqlite3_bind_int(p_stmt, 4, 0);
+
+               } else if(!strcmp(s_object, SMACK_APP_LABEL_TEMPLATE)) {
+                       sqlite3_bind_text(p_stmt, 3, s_subject, RDB_AUTO_DETERM_SIZE, 0);
+                       sqlite3_bind_int(p_stmt, 4, 1);
+
+               } else {
+                       C_LOGE("RDB: Incorrect rule format: %s", pp_smack_rules[i]);
+                       ret = PC_ERR_INVALID_PARAM;
+                       goto finish;
+               }
+
+               // Perform the insert
+               ret = step_and_convert_returned_value(p_stmt);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               // Reset and unbind statement:
+               if(sqlite3_reset(p_stmt) != SQLITE_OK) {
+                       C_LOGE("RDB: Error reseting statement: %s",
+                              sqlite3_errmsg(p_db));
+                       ret = PC_ERR_DB_QUERY_STEP;
+                       goto finish;
+               }
+               if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
+                       C_LOGE("RDB: Error reseting statement: %s",
+                              sqlite3_errmsg(p_db));
+                       ret = PC_ERR_DB_QUERY_STEP;
+                       goto finish;
+               }
+       }
+
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int get_app_id_internal(sqlite3 *p_db,
+                       int *pi_app_id,
+                       const char *const s_app_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "SELECT application_view.app_id \
+                            FROM application_view \
+                            WHERE application_view.name = %Q",
+                          s_app_label_name);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = sqlite3_step(p_stmt);
+       if(ret == SQLITE_ROW) {
+               ret = PC_OPERATION_SUCCESS;
+               *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
+
+       } else if(ret == SQLITE_DONE) {
+               C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
+               ret = PC_ERR_DB_OPERATION;
+
+       } else {
+               C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_QUERY_STEP;
+       }
+
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int add_app_permission_internal(sqlite3 *p_db,
+                               int i_app_id,
+                               const char *const s_permission_name,
+                               const char *const s_permission_type_name,
+                               const bool b_is_volatile_new,
+                               const bool b_is_enabled_new)
+{
+       RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
+                           s_permission_name, s_permission_type_name,
+                           b_is_volatile_new, b_is_enabled_new);
+
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "INSERT INTO                                  \
+                           app_permission_view(app_id, name, type_name, \
+                           is_volatile, is_enabled)                     \
+                           VALUES(%d,%Q,%Q,%d,%d)",
+                          i_app_id, s_permission_name, s_permission_type_name,
+                          (int)b_is_volatile_new, (int)b_is_enabled_new);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int switch_app_permission_internal(sqlite3 *p_db,
+                                  const int i_app_id,
+                                  const char *const s_permission_name,
+                                  const char *const s_permission_type_name,
+                                  const bool b_is_enabled_new)
+{
+       RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
+                           s_permission_name, s_permission_type_name,
+                           b_is_enabled_new);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "UPDATE app_permission_view \
+                           SET    is_enabled=%d       \
+                           WHERE  app_id = %d  AND    \
+                                  name =%Q AND        \
+                                  type_name=%Q",
+                          b_is_enabled_new, i_app_id,
+                          s_permission_name, s_permission_type_name);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int update_app_permission_internal(sqlite3 *p_db,
+                                  const int i_app_id,
+                                  const int i_permission_id,
+                                  const bool b_is_volatile_new,
+                                  const bool b_is_enabled_new)
+{
+       RDB_LOG_ENTRY_PARAM("%d %d %d %d",
+                           i_app_id, i_permission_id,
+                           b_is_volatile_new, b_is_enabled_new);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "UPDATE app_permission \
+                            SET is_volatile = %d, is_enabled=%d \
+                            WHERE app_id = %d AND permission_id = %d",
+                          b_is_volatile_new, b_is_enabled_new,
+                          i_app_id, i_permission_id);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int change_app_permission_internal(sqlite3 *p_db,
+                                  int i_app_id,
+                                  const char *const s_permission_name,
+                                  const char *const s_permission_type_name,
+                                  int i_is_volatile_new,
+                                  int i_is_enabled_new)
+{
+       RDB_LOG_ENTRY_PARAM("%d %d %d %d %d", i_app_id,
+                           s_permission_name, s_permission_type_name,
+                           i_is_volatile_new, i_is_enabled_new);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+       int i_is_volatile_old, i_is_enabled_old, i_permission_id;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "SELECT is_volatile, is_enabled, permission_id      \
+                            FROM    app_permission_list_view                   \
+                            WHERE   app_id = %d AND                            \
+                            permission_name=%Q AND                             \
+                            permission_type_name=%Q LIMIT 1",
+                          i_app_id, s_permission_name, s_permission_type_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = sqlite3_step(p_stmt);
+       if(ret == SQLITE_ROW) {
+               // Phi, I already have this permission...
+               i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
+               i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
+
+               if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
+                       // Confucius say, No man can down-cast volatility.
+                       C_LOGE("RDB: Down-casting volatility is forbidden.");
+                       ret = PC_ERR_DB_PERM_FORBIDDEN;
+                       goto finish;
+               }
+
+               if(i_is_volatile_old == i_is_volatile_new &&
+                   i_is_enabled_old == i_is_enabled_new) {
+                       // There is no change. Nice.
+                       C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
+                       ret = PC_OPERATION_SUCCESS;
+                       goto finish;
+               }
+
+               i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
+
+               // Finalize statement
+               if(sqlite3_finalize(p_stmt) < 0)
+                       C_LOGE("RDB: Error during finalizing statement: %s",
+                              sqlite3_errmsg(p_db));
+               p_stmt = NULL;
+
+               C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
+               ret = update_app_permission_internal(p_db,
+                                                    i_app_id,
+                                                    i_permission_id,
+                                                    i_is_volatile_new,
+                                                    i_is_enabled_new);
+
+       } else if(ret == SQLITE_DONE) {
+               // Wow! A brand new permission! Omnomnom...
+
+               if(sqlite3_finalize(p_stmt) < 0)
+                       C_LOGE("RDB: Error during finalizing statement: %s",
+                              sqlite3_errmsg(p_db));
+               p_stmt = NULL;
+
+               C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
+               ret = add_app_permission_internal(p_db,
+                                                 i_app_id,
+                                                 s_permission_name,
+                                                 s_permission_type_name,
+                                                 i_is_volatile_new,
+                                                 i_is_enabled_new);
+       } else {
+               C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_QUERY_STEP;
+       }
+
+finish:
+       if(p_stmt && sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int revoke_app_permissions_internal(sqlite3 *p_db,
+                                   const char *const s_app_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "DELETE FROM app_permission_view \
+                           WHERE app_permission_view.app_name=%Q;",
+                          s_app_label_name);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int reset_app_permissions_internal(sqlite3 *p_db,
+                                  const char *const s_app_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "DELETE FROM app_permission_volatile_view \
+                            WHERE app_permission_volatile_view.app_name=%Q;",
+                          s_app_label_name);
+
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = step_and_convert_returned_value(p_stmt);
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
+}
+
+
+int save_smack_rules(sqlite3 *p_db)
+{
+       RDB_LOG_ENTRY;
+
+       if(sqlite3_exec(p_db,
+                       "DELETE FROM history_smack_rule",
+                       0, 0, 0) != SQLITE_OK) {
+               C_LOGE("RDB: Error during clearing history table: %s",
+                      sqlite3_errmsg(p_db));
+               return PC_ERR_DB_OPERATION;
+       }
+       if(sqlite3_exec(p_db,
+                       "INSERT INTO history_smack_rule \
+                       SELECT subject, object, access  \
+                       FROM all_smack_binary_rules",
+                       0, 0, 0) != SQLITE_OK) {
+               C_LOGE("RDB: Error during inserting into history_smack_rule table: %s",
+                      sqlite3_errmsg(p_db));
+               return PC_ERR_DB_OPERATION;
+       }
+
+       // TODO: Maybe don't use index?
+       if(sqlite3_exec(p_db,
+                       "CREATE INDEX history_smack_rule_subject_object_index \
+                       ON history_smack_rule(subject, object)",
+                       0, 0, 0) != SQLITE_OK) {
+               C_LOGE("RDB: Error during indexing history_smack_rule table: %s",
+                      sqlite3_errmsg(p_db));
+               return PC_ERR_DB_OPERATION;
+       }
+       return PC_OPERATION_SUCCESS;
+}
+
+
+static int update_rules_in_db(sqlite3 *p_db)
+{
+       RDB_LOG_ENTRY;
+
+       // All rules generated by the present state of the database
+       if(sqlite3_exec(p_db,
+                       "DELETE FROM all_smack_binary_rules;        \
+                                                                   \
+                       INSERT INTO all_smack_binary_rules          \
+                       SELECT subject, object, access, is_volatile \
+                       FROM all_smack_binary_rules_view;           \
+                                                                   \
+                       DELETE FROM all_smack_binary_rule_modified; \
+                                                                   \
+                       INSERT INTO all_smack_binary_rule_modified  \
+                       SELECT subject, object, access              \
+                       FROM   all_smack_binary_rules,              \
+                              modified_label                       \
+                       WHERE  subject IN modified_label OR         \
+                              object IN modified_label;            \
+                                                                   \
+                       DELETE FROM history_smack_rule_modified;    \
+                                                                   \
+                       INSERT INTO history_smack_rule_modified     \
+                       SELECT subject, object, access              \
+                       FROM   history_smack_rule,                  \
+                              modified_label                       \
+                       WHERE  subject IN modified_label OR         \
+                              object IN modified_label;            \
+                       ",
+                       0, 0, 0) != SQLITE_OK) {
+               C_LOGE("RDB: Error during updating rules: %s",
+                      sqlite3_errmsg(p_db));
+               return PC_ERR_DB_OPERATION;
+       }
+       return PC_OPERATION_SUCCESS;
+}
+
+int update_smack_rules(sqlite3 *p_db)
+{
+       RDB_LOG_ENTRY;
+
+       int ret = PC_OPERATION_SUCCESS;
+       sqlite3_stmt *p_stmt = NULL;
+       const unsigned char *s_subject    = NULL;
+       const unsigned char *s_object     = NULL;
+       const unsigned char *s_access_add = NULL;
+       const unsigned char *s_access_del = NULL;
+       struct smack_accesses *smack = NULL;
+
+       ret = update_rules_in_db(p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       if(smack_accesses_new(&smack)) {
+               C_LOGE("RDB: Error during updating smack rules: smack_accesses_new failed.");
+               ret = PC_ERR_MEM_OPERATION;
+               goto finish;
+       }
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "SELECT * from modified_smack_rules;");
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       while((ret = sqlite3_step(p_stmt)) == SQLITE_ROW) {
+               s_subject    = sqlite3_column_text(p_stmt, RDB_FIRST_COLUMN);
+               s_object     = sqlite3_column_text(p_stmt, RDB_SECOND_COLUMN);
+               s_access_add = sqlite3_column_text(p_stmt, RDB_THIRD_COLUMN);
+               s_access_del = sqlite3_column_text(p_stmt, RDB_FOURTH_COLUMN);
+
+               C_LOGD("RDB: Added rule to smack:: %s %s %s %s",
+                      s_subject, s_object, s_access_add, s_access_del);
+
+               if(smack_accesses_add_modify(smack,
+                                            (const char *) s_subject,
+                                            (const char *) s_object,
+                                            (const char *) s_access_add,
+                                            (const char *) s_access_del)) {
+                       C_LOGE("RDB: Error during updating smack rules: %s",
+                              sqlite3_errmsg(p_db));
+                       ret = PC_ERR_INVALID_OPERATION;
+                       goto finish;
+               }
+       }
+       if(ret == SQLITE_DONE) {
+               ret = PC_OPERATION_SUCCESS;
+       } else {
+               C_LOGE("RDB: Error during updating smack rules [%d]: %s",
+                      ret, sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_OPERATION;
+       }
+
+       if(smack_accesses_apply(smack)) {
+               C_LOGE("RDB: Error in smack_accesses_apply");
+               ret = PC_ERR_INVALID_OPERATION;
+       }
+
+finish:
+       if(sqlite3_finalize(p_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+
+       smack_accesses_free(smack);
+       return ret;
+}
\ No newline at end of file
diff --git a/src/rules-db.c b/src/rules-db.c
new file mode 100644 (file)
index 0000000..53544b1
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+* @file        rules-db.c
+* @author      Jan Olszak (j.olszak@samsung.com)
+* @version     1.0
+* @brief       This file contains declaration of the API to rules database.
+*/
+
+#include "rules-db-internals.h"
+
+static sqlite3 *p_db__          = NULL;
+static int i_session_ret_code__ = PC_OPERATION_SUCCESS;
+
+/**
+ * Prepare to modify the database.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  pp_db pointer to a pointer to a SQLite3 database object
+ * @return       PC_OPERATION_SUCCESS on success,
+ *               error code otherwise
+ */
+static int rdb_begin(sqlite3 **pp_db)
+{
+       RDB_LOG_ENTRY;
+
+       // If rdb_modification_start was called we use a global connection.
+       if(p_db__) {
+               *pp_db = p_db__;
+               return PC_OPERATION_SUCCESS;
+       }
+
+       int ret = open_rdb_connection(pp_db);
+       if(ret != PC_OPERATION_SUCCESS) return ret;
+
+       if(sqlite3_exec(*pp_db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0)
+           != SQLITE_OK) {
+               C_LOGE("RDB: Error during transaction begin: %s",
+                      sqlite3_errmsg(*pp_db));
+               return PC_ERR_DB_CONNECTION;
+       }
+
+       if(have_smack()) {
+               ret = save_smack_rules(*pp_db);
+               if(ret != PC_OPERATION_SUCCESS) return ret;
+       }
+
+       return PC_OPERATION_SUCCESS;
+}
+
+
+/**
+ * Finish database modification.
+ * If previous operation returned an error try to rollback changes.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db pointer to a SQLite3 database object
+ * @param  ret  previous return code
+ */
+static void rdb_end(sqlite3 *p_db, int ret)
+{
+       RDB_LOG_ENTRY;
+
+       if(have_smack()) {
+               if(ret == PC_OPERATION_SUCCESS &&
+                   (ret = update_smack_rules(p_db))
+                   != PC_OPERATION_SUCCESS) {
+                       C_LOGE("RDB: Error updating smack rules");
+               }
+       }
+
+       // Finish transaction
+       C_LOGD("RDB: Closing connection.");
+       if(ret == PC_OPERATION_SUCCESS) {
+               if(sqlite3_exec(p_db, "COMMIT TRANSACTION", 0, 0, 0)
+                   != SQLITE_OK) {
+                       C_LOGE("RDB: Error during transaction commit: %s",
+                              sqlite3_errmsg(p_db));
+               }
+       } else if(ret == PC_ERR_DB_CONNECTION) {
+               /* Life is pointless. I can't even rollback...*/
+               C_LOGE("RDB: No rollback nor commit.");
+       } else if(sqlite3_exec(p_db, "ROLLBACK TRANSACTION", 0, 0, 0)
+                 != SQLITE_OK) {
+               C_LOGE("RDB: Error during transaction rollback: %s",
+                      sqlite3_errmsg(p_db));
+       }
+
+       if(sqlite3_close(p_db)) {
+               C_LOGE("RDB: Error during closing the database.");
+       }
+}
+
+
+static void update_ret_code(int i_ret)
+{
+       i_session_ret_code__ = i_session_ret_code__ ? i_session_ret_code__ : i_ret;
+}
+
+
+int rdb_modification_start(void)
+{
+       if(p_db__) {
+               // We have to finish the previous session:
+               C_LOGW("RDB: rdb_modification_finish was not called!");
+               rdb_modification_finish();
+       }
+
+       return rdb_begin(&p_db__);
+}
+
+
+void rdb_modification_finish(void)
+{
+       if(p_db__) {
+               rdb_end(p_db__, i_session_ret_code__);
+               p_db__ = NULL;
+               i_session_ret_code__ = PC_OPERATION_SUCCESS;
+       }
+}
+
+
+int rdb_add_application(const char *const s_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = check_app_label_internal(p_db, s_label_name);
+       if(ret == PC_ERR_DB_LABEL_TAKEN) {
+               ret = PC_OPERATION_SUCCESS;
+               C_LOGW("RDB: There is an application with label: %s", s_label_name);
+
+       } else if(ret == PC_OPERATION_SUCCESS) {
+               // There is no such label yet.
+               ret = add_app_internal(p_db, s_label_name);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       }
+
+       ret = add_modified_label_internal(p_db, s_label_name);
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
+}
+
+
+int rdb_remove_application(const char *const s_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = remove_app_internal(p_db, s_label_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_modified_label_internal(p_db, s_label_name);
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
+}
+
+
+int rdb_add_path(const char *const s_owner_label_name,
+                const char *const s_path_label_name,
+                const char *const s_path,
+                const char *const s_access,
+                const char *const s_type)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
+                           s_owner_label_name, s_path_label_name,
+                           s_path, s_access, s_type);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_path_internal(p_db,
+                               s_owner_label_name,
+                               s_path_label_name,
+                               s_path,
+                               s_access,
+                               s_type);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_modified_label_internal(p_db, s_path_label_name);
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
+}
+
+
+int rdb_add_permission_rules(const char *const s_permission_name,
+                            const char *const s_permission_type_name,
+                            const char *const *const pp_smack_rules)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+       sqlite3_int64 permission_id = -1;
+
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_permission_internal(p_db,
+                                     s_permission_name,
+                                     s_permission_type_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = get_permission_id_internal(p_db,
+                                        s_permission_name,
+                                        s_permission_type_name,
+                                        &permission_id);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_modified_permission_internal(p_db, permission_id);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       if(pp_smack_rules != NULL) {
+               ret = add_permission_rules_internal(p_db,
+                                                   permission_id,
+                                                   pp_smack_rules);
+       }
+
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
+}
+
+
+int rdb_enable_app_permissions(const char *const s_app_label_name,
+                              const char *const s_permission_type_name,
+                              const char *const *const pp_permissions_list,
+                              const bool   b_is_volatile)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s %d", s_app_label_name, s_permission_type_name, b_is_volatile);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+       int i;
+       int i_app_id = 0;
+       C_LOGD("RDB: Enabling permissions START");
+
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       // Add permissions specific for the permission type:
+       ret = change_app_permission_internal(p_db,
+                                            i_app_id,
+                                            s_permission_type_name,
+                                            s_permission_type_name,
+                                            b_is_volatile,
+                                            RDB_ENABLE);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       // Add permissions from the list:
+       for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
+               // Ignore empty lines
+               if(strspn(pp_permissions_list[i], " \t\n")
+                   == strlen(pp_permissions_list[i]))
+                       continue;
+
+               ret = change_app_permission_internal(p_db,
+                                                    i_app_id,
+                                                    pp_permissions_list[i],
+                                                    s_permission_type_name,
+                                                    b_is_volatile,
+                                                    RDB_ENABLE);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+       }
+
+       ret = add_modified_label_internal(p_db, s_app_label_name);
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
+}
+
+
+int rdb_disable_app_permissions(const char *const s_app_label_name,
+                               const char *const s_permission_type_name,
+                               const char *const *const pp_permissions_list)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s", s_app_label_name, s_permission_type_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+       int i, i_app_id;
+
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
+               // Ignore empty lines
+               if(strspn(pp_permissions_list[i], " \t\n")
+                   == strlen(pp_permissions_list[i]))
+                       continue;
+
+               ret = switch_app_permission_internal(p_db,
+                                                    i_app_id,
+                                                    pp_permissions_list[i],
+                                                    s_permission_type_name,
+                                                    RDB_DISABLE);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+       }
+
+       ret = add_modified_label_internal(p_db, s_app_label_name);
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
+}
+
+
+int rdb_revoke_app_permissions(const char *const s_app_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = revoke_app_permissions_internal(p_db, s_app_label_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_modified_label_internal(p_db, s_app_label_name);
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
+}
+
+
+int rdb_reset_app_permissions(const char *const s_app_label_name)
+{
+       RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = reset_app_permissions_internal(p_db, s_app_label_name);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_modified_label_internal(p_db, s_app_label_name);
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
+}
+
+
+int validate_all_rules(const char *const *const pp_permissions_list)
+{
+       RDB_LOG_ENTRY;
+
+       int i;
+       char s_subject[SMACK_LABEL_LEN + 1];
+       char s_object[SMACK_LABEL_LEN + 1];
+       char s_access[ACC_LEN + 1];
+
+       // Parse and check rules.
+       for(i = 0; pp_permissions_list[i] != NULL; ++i) {
+               // C_LOGE("RDB: Validating rules: %s", pp_permissions_list[i]);
+
+               // Ignore empty lines
+               if(strspn(pp_permissions_list[i], " \t\n")
+                   == strlen(pp_permissions_list[i]))
+                       continue;
+
+               if(parse_rule(pp_permissions_list[i], s_subject, s_object, s_access)
+                   != PC_OPERATION_SUCCESS) {
+                       C_LOGE("RDB: Invalid parameter");
+                       return PC_ERR_INVALID_PARAM;
+               }
+
+               if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) != 0 &&
+                   strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) != 0) {
+                       C_LOGE("RDB: There is no " SMACK_APP_LABEL_TEMPLATE " argument in template rule.");
+                       return PC_ERR_INVALID_PARAM;
+               }
+
+               if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
+                   strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0) {
+                       C_LOGE("RDB: Rule with two " SMACK_APP_LABEL_TEMPLATE " has no sense.");
+                       return PC_ERR_INVALID_PARAM;
+               }
+
+               // Check the other label
+               if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
+                   !smack_label_is_valid(s_object)) {
+                       C_LOGE("RDB: Incorrect object label: %s", s_object);
+                       return PC_ERR_INVALID_PARAM;
+               } else if(strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0 &&
+                         !smack_label_is_valid(s_subject)) {
+                       C_LOGE("RDB: Incorrect subject label: %s", s_subject);
+                       return PC_ERR_INVALID_PARAM;
+               }
+       }
+
+       return PC_OPERATION_SUCCESS;
+}
\ No newline at end of file