[Release] libprivilege-control_0.0.43.TIZEN
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 25 Oct 2013 12:47:00 +0000 (14:47 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 25 Oct 2013 12:47:03 +0000 (14:47 +0200)
* Revert "add API definition"
* Implement new wildcard ~NPRUNTIME_PATH~ +fix workaround
* Implement adding new WRT rules in libprivilege-control
* add API definition
* Correction in enabling permissions.
* Renamed enums and deleted unused defines
* Modified checking labels and deleted unused checking.
* Change in setup path.
* Change in boot script.
* Adding additional rules.
* Implementation of cross-app rule patterns in *.smack files
* Corrected a mistake in deleting paths.
* Deleting paths on revoking permissions.
* Deleted volatile rules on boot and corrected permission format.
* Modified boot script, added deleting volatile rules.
* Made marking labels as modified beautiful.
* Changed new API names.
* Loading api-features from a file.
* Revert "rollback because of rule database"
* add systemd options
* Add README file
* Compilation flags 'verbose' mode
* Unused function smack_get_access_new removed
* Libprivilege API cleanup
* Add missing information about APP_PATH_ANY_LABEL in header
* Takes compilation profile from command line.
* Add for all anti viruses RWX access to all public-RO and group-RW shared folder
* Simple corrections in api-feature handling. +Fix

Change-Id: I0749261e11e71463e48ec5978cc2e824e6278309

27 files changed:
CMakeLists.txt
README [new file with mode: 0644]
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
packaging/smack-default-labeling.service
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 7c5b0ea..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,25 +14,30 @@ 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}")
 ENDFOREACH(flag)
 
-SET(CMAKE_C_FLAGS_CCOV "--coverage")
-SET(CMAKE_CXX_FLAGS_CCOV "--coverage")
+# TIZEN_ENGINEER_MODE is used in  dlog.h file.
+# Without this flag all logs defined with SLOGD macro
+# will be expanded to empty instruction.
+
+SET(CMAKE_C_FLAGS_CCOV    "--coverage")
+SET(CMAKE_C_FLAGS_DEBUG   "-O0 -g -ggdb -DDLOG_DEBUG_ENABLED -DTIZEN_ENGINEER_MODE")
+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")
 
@@ -42,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)
@@ -61,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)
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..dd56e9c
--- /dev/null
+++ b/README
@@ -0,0 +1,32 @@
+README for libprivilege-control project
+
+libprivilege-control is a library that is designed to work with Simplified
+Mandatory Access Control Kernel (SMACK/Smack) on Tizen platform.
+
+The library introduces and works with a new abstraction layer for access control
+above the SMACK's rules layer: a privilege layer.
+The privilege is a group of rules combined together to represent SMACK accesses
+(rights) that application needs to have in order to work with some distinctive
+subsystems.
+This library provides an interface allowing maintenance of application
+privileges for Tizen.
+
+The library's API is available in the header file incluce/privilege-control.h.
+The API provides functions that can be used to perform security context actions
+for the whole lifecycle of application: installing, running, uninstalling.
+Such actions are:
+- for installing:
+    ->registering application in a database,
+    ->setting privileges for an application that is being installed,
+    ->setting up rights and giving SMACK labels for application's shared
+    directiories or files,
+    ->adding new privilege definitions,
+- for running:
+    ->setting privileges for an application that is being run,
+- for uninstaling:
+    ->cleaning up data set up during installation.
+
+
+Internally the package implements a database of SMACK rules that are maintained
+via the library API. Each time an API for changing rules is called, the rules
+in database are processed and are loaded to kernel SMACK.
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..d032432
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * 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 <dirent.h>             // For iterating directories
+#include <getopt.h>             // For getopt
+#include <obstack.h>            // For obstack implementation
+#include <privilege-control.h>  // For app_type
+#include <stdio.h>              // For file manipulation
+#include <stdlib.h>             // For malloc and free
+#include <sys/smack.h>          // For SMACK_LABEL_LEN
+#include <unistd.h>             // For basename
+
+
+#define API_FEATURE_LOADER_VERSION "1.0"
+#define API_FEATURES_DIR "/usr/share/privilege-control/"
+#define API_FEATURE_LOADER_LOG(format, ...) if(i_verbose_flag__) printf(format, ##__VA_ARGS__)
+
+// Obstack configuration
+#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)
+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);
+}
+
+int additional_rules_filter(const struct dirent *entry)
+{
+       return !strcmp(entry->d_name, "ADDITIONAL_RULES.smack");;
+}
+
+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);
+       }
+}
+
+
+char *get_permission_name(const char *s_file_name, const char *s_prefix)
+{
+       int i_prefix_len = strlen(s_prefix);
+
+       // Allocate memory
+       int i_perm_name_len = strlen(s_file_name);
+       char *s_permission_name = (char *) malloc(i_perm_name_len);
+       if(!s_permission_name) {
+               API_FEATURE_LOADER_LOG("Error during allocating memory.\n");
+               return NULL;
+       }
+
+       strncpy(s_permission_name,
+               &(s_file_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';
+
+       return s_permission_name;
+}
+
+void load_permission_family(int (*filter)(const struct dirent *),
+                           const char const *s_prefix,
+                           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;
+
+
+       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;
+
+               s_permission_name = get_permission_name(file_list[i]->d_name, s_prefix);
+               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_begin()) return;
+
+       // Load rules specific to permission's types:
+       load_pemission_type_rules(wrt_filter,          "WRT",          PERM_APP_TYPE_WGT,          s_dir);
+       load_pemission_type_rules(wrt_partner_filter,  "WRT_partner",  PERM_APP_TYPE_WGT_PARTNER,  s_dir);
+       load_pemission_type_rules(wrt_platform_filter, "WRT_platform", PERM_APP_TYPE_WGT_PLATFORM, s_dir);
+       load_pemission_type_rules(osp_filter,          "OSP",          PERM_APP_TYPE_OSP,          s_dir);
+       load_pemission_type_rules(osp_partner_filter,  "OSP_partner" , PERM_APP_TYPE_OSP_PARTNER,  s_dir);
+       load_pemission_type_rules(osp_platform_filter, "OSP_platform", PERM_APP_TYPE_OSP_PLATFORM, s_dir);
+       load_pemission_type_rules(efl_filter,          "EFL",          PERM_APP_TYPE_EFL,          s_dir);
+
+       // Load rules for each permission type:
+       load_permission_family(wrt_family_filter, "WRT_", PERM_APP_TYPE_WGT, s_dir);
+       load_permission_family(osp_family_filter, "OSP_", PERM_APP_TYPE_OSP, s_dir);
+       load_permission_family(efl_family_filter, "EFL_", PERM_APP_TYPE_EFL, s_dir);
+
+
+       perm_end();
+       API_FEATURE_LOADER_LOG("Done.\n");
+}
+
+void load_from_file(const char  *const s_file_path)
+{
+       API_FEATURE_LOADER_LOG("Loading rules from file...\n");
+       if(perm_begin()) return;
+
+       char *s_permission_name = NULL;
+       char *s_file_name;
+       struct dirent file;
+
+       if(!has_smack_ext(s_file_path)) {
+               API_FEATURE_LOADER_LOG("File doesn't have smack extension.");
+               perm_end();
+               return;
+       }
+
+       s_file_name = basename(s_file_path);
+       strcpy(file.d_name, s_file_name);
+
+       // Load as the right type of permission
+       if(wrt_family_filter(&file)) {
+               s_permission_name = get_permission_name(s_file_name, "WRT_");
+               load_rules_from_file(s_file_path, s_permission_name, PERM_APP_TYPE_WGT);
+
+       } else if(osp_family_filter(&file)) {
+               s_permission_name = get_permission_name(s_file_name, "OSP_");
+               load_rules_from_file(s_file_path, s_permission_name, PERM_APP_TYPE_OSP);
+
+       } else if(efl_family_filter(&file)) {
+               s_permission_name = get_permission_name(s_file_name, "EFL_");
+               load_rules_from_file(s_file_path, s_permission_name, PERM_APP_TYPE_EFL);
+
+       } else {
+               API_FEATURE_LOADER_LOG("Unknown api-feature type.");
+       }
+
+       free(s_permission_name);
+
+       perm_end();
+       API_FEATURE_LOADER_LOG("Done.\n");
+}
+
+void load_additional_rules(const char  *const s_rules_file_path)
+{
+       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;
+
+       API_FEATURE_LOADER_LOG("Loading additional rules from file...\n");
+
+       p_file = fopen(s_rules_file_path, "r");
+       if(!p_file) goto finish;
+
+
+       vector_init(rules_vector);
+       while(getline(&s_rule, &i, p_file) > 0) {
+               vector_push_back_ptr(rules_vector, s_rule);
+               API_FEATURE_LOADER_LOG("Loading rule: %s", s_rule);
+               ++i_num_rules;
+               s_rule = NULL;
+       }
+       vector_push_back_ptr(rules_vector, NULL);
+
+       rules_array = vector_finish(rules_vector);
+
+       ret = perm_add_additional_rules((const char **)rules_array);
+       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);
+       }
+
+       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_name = NULL;
+
+       bool b_load_from_dir = false;
+       const char *s_dir_name = NULL;
+
+       bool b_load_additional_rules = false;
+       const char *s_additional_rules_file_name = NULL;
+
+       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'},
+               {"rules",   required_argument, 0, 'r'},
+               {0, 0, 0, 0}
+       };
+
+       while((c = getopt_long(argc, argv,
+                              "f:d:hv",
+                              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_name = optarg;
+                       break;
+
+               case 'd':
+                       b_load_from_dir = true;
+                       s_dir_name = optarg;
+                       break;
+
+               case 'r':
+                       b_load_additional_rules = true;
+                       s_additional_rules_file_name = 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("        -r,--rules           load additional rules from the file\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;
+       }
+
+       // Run task
+       if(b_load_additional_rules)
+               load_additional_rules(s_additional_rules_file_name);
+       if(b_load_from_dir)
+               load_from_dir(s_dir_name);
+       if(b_load_from_file)
+               load_from_file(s_file_name);
+       if(!b_load_additional_rules &&
+           !b_load_from_dir &&
+           !b_load_from_file)
+               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..b5de8b2
--- /dev/null
@@ -0,0 +1,17 @@
+.load librules-db-sql-udf.so
+.separator " "
+
+PRAGMA journal_mode = DELETE;
+
+
+BEGIN TRANSACTION;
+
+-- Delete volatile rules
+DELETE FROM app_permission WHERE is_volatile = 1;
+
+
+.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;
+COMMIT TRANSACTION;
\ No newline at end of file
diff --git a/db/rules-db-data.sql b/db/rules-db-data.sql
new file mode 100644 (file)
index 0000000..b49cd7c
--- /dev/null
@@ -0,0 +1,108 @@
+-- !!! 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("GROUP_PATH");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("PUBLIC_PATH");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("SETTINGS_PATH");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("NPRUNTIME_PATH");
+
+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_PATH
+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_PATH", "rx", 0);
+
+
+-- SETTINGS ----------------------------------------------------------------------------------------
+-- Permission name == TIZEN_PRIVILEGE_APPSETTING
+-- SETTINGS_PATH
+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_PATH", "rwx", 0),
+       ("org.tizen.privilege.appsetting","OSP", "SETTINGS_PATH", "rwx", 0),
+       ("org.tizen.privilege.appsetting","EFL", "SETTINGS_PATH", "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_PATH",    "rwx", 0),
+       ("org.tizen.privilege.antivirus","OSP", "GROUP_PATH",    "rwx", 0),
+       ("org.tizen.privilege.antivirus","EFL", "GROUP_PATH",    "rwx", 0),
+       ("org.tizen.privilege.antivirus","WRT", "SETTINGS_PATH", "rwx", 0),
+       ("org.tizen.privilege.antivirus","OSP", "SETTINGS_PATH", "rwx", 0),
+       ("org.tizen.privilege.antivirus","EFL", "SETTINGS_PATH", "rwx", 0),
+       ("org.tizen.privilege.antivirus","WRT", "PUBLIC_PATH",   "rwx", 0),
+       ("org.tizen.privilege.antivirus","OSP", "PUBLIC_PATH",   "rwx", 0),
+       ("org.tizen.privilege.antivirus","EFL", "PUBLIC_PATH",   "rwx", 0);
+
+COMMIT TRANSACTION;
+
+VACUUM;
diff --git a/db/rules-db-sql-udf.c b/db/rules-db-sql-udf.c
new file mode 100644 (file)
index 0000000..bd079b0
--- /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]);
+}
+
+
+static 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..6f7a5e3
--- /dev/null
@@ -0,0 +1,890 @@
+-- !!! 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;
+PRAGMA auto_vacuum = NONE;
+
+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,
+    access_reverse 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_app_path_type_rule (
+    label_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 (label_id, app_path_type_id, is_reverse),
+
+    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 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 USING(permission_type_id);
+
+DROP TRIGGER IF EXISTS permission_view_insert_trigger;
+CREATE TRIGGER permission_view_insert_trigger
+INSTEAD OF INSERT ON permission_view
+BEGIN
+    -- Add the permission
+    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;
+
+
+    -- Delete the previous definition of the permission
+    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 USING(permission_id)
+LEFT JOIN label USING(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 OR REPLACE 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 USING(permission_id)
+LEFT JOIN app_path_type USING(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
+WHEN NEW.permission_id IS NULL
+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;
+
+DROP TRIGGER IF EXISTS permission_app_path_type_rule_view_delete_trigger;
+CREATE TRIGGER permission_app_path_type_rule_view_delete_trigger
+INSTEAD OF DELETE
+ON permission_app_path_type_rule_view
+BEGIN
+    -- Delete the rule
+    DELETE FROM permission_app_path_type_rule
+    WHERE       permission_app_path_type_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;
+
+
+CREATE TRIGGER permission_app_path_type_id_rule_view_insert_trigger
+INSTEAD OF INSERT
+ON permission_app_path_type_rule_view
+WHEN NEW.permission_id IS NOT NULL
+BEGIN
+    INSERT OR REPLACE INTO permission_app_path_type_rule(permission_id,
+                                                         app_path_type_id,
+                                                         access,
+                                                         is_reverse)
+    SELECT      NEW.permission_id,
+                app_path_type.app_path_type_id,
+                str_to_access(NEW.access),
+                NEW.is_reverse
+    FROM        app_path_type
+    WHERE       app_path_type.name = NEW.app_path_type_name;
+END;
+
+
+-- LABEL TO APP PATH TYPE RULE VIEW --------------------------------------------
+DROP VIEW IF EXISTS label_app_path_type_rule_view;
+CREATE VIEW label_app_path_type_rule_view AS
+SELECT
+        label_app_path_type_rule.label_id   AS label_id,
+        label.name                          AS label_name,
+        app_path_type.name                  AS app_path_type_name,
+        label_app_path_type_rule.access     AS access,
+        label_app_path_type_rule.is_reverse AS is_reverse
+FROM    label_app_path_type_rule
+LEFT JOIN label USING(label_id)
+LEFT JOIN app_path_type USING(app_path_type_id);
+
+
+DROP TRIGGER IF EXISTS label_app_path_type_rule_view_insert_trigger;
+CREATE TRIGGER label_app_path_type_rule_view_insert_trigger
+INSTEAD OF INSERT
+ON label_app_path_type_rule_view
+BEGIN
+    INSERT OR IGNORE INTO label(name) VALUES (NEW.label_name);
+
+    INSERT INTO label_app_path_type_rule(label_id,
+                                         app_path_type_id,
+                                         access,
+                                         is_reverse)
+    SELECT      label.label_id,
+                app_path_type.app_path_type_id,
+                str_to_access(NEW.access),
+                NEW.is_reverse
+    FROM        label, app_path_type
+    WHERE       label.name = NEW.label_name AND
+                app_path_type.name = NEW.app_path_type_name;
+END;
+
+
+DROP TRIGGER IF EXISTS label_app_path_type_rule_view_delete_trigger;
+CREATE TRIGGER label_app_path_type_rule_view_delete_trigger
+INSTEAD OF DELETE
+ON label_app_path_type_rule_view
+BEGIN
+    -- Delete the rules with this label
+    DELETE FROM label_app_path_type_rule
+    WHERE       label_app_path_type_rule.label_id
+                IN (SELECT label.label_id
+                    FROM   label
+                    WHERE  label.name = OLD.label_name);
+
+    -- Delete the label if it's not referenced
+    DELETE FROM label_view
+    WHERE label_view.name = OLD.label_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 USING(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 OR REPLACE 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;
+
+
+DROP TRIGGER IF EXISTS permission_permission_rule_view_delete_trigger;
+CREATE TRIGGER  permission_permission_rule_view_delete_trigger
+INSTEAD OF DELETE ON  permission_permission_rule_view
+BEGIN
+    -- Delete the rule
+    DELETE FROM permission_permission_rule_view
+    WHERE       permission_permission_rule_view.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;
+
+
+
+-- 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) AND
+        OLD.label_id NOT IN (SELECT label_app_path_type_rule.label_id
+                             FROM   label_app_path_type_rule)
+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 USING(label_id);
+
+DROP TRIGGER IF EXISTS application_view_insert_trigger;
+CREATE TRIGGER application_view_insert_trigger
+INSTEAD OF INSERT ON application_view
+BEGIN
+    -- The app's label could have been added by the permission.
+    INSERT OR IGNORE INTO label(name) VALUES (NEW.name);
+
+    -- Add application:
+    INSERT INTO app(label_id)
+    SELECT label_id
+    FROM   label
+    WHERE  label.name = NEW.name;
+
+    -- Add the permission granted to all applications
+    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 USING(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.access_reverse AS access_reverse,
+        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
+    -- The path's label could have been added by the permission.
+    INSERT OR IGNORE INTO label(name) VALUES (NEW.path_label_name);
+
+    -- Add the path
+    INSERT INTO app_path(app_id, path, label_id, access, access_reverse, app_path_type_id)
+    SELECT  application_view.app_id,
+            NEW.path,
+            label.label_id,
+            str_to_access(NEW.access),
+            str_to_access(NEW.access_reverse),
+            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 the path
+        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 the path's label if it's not used any more
+        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 USING(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 USING(app_id)
+INNER JOIN  permission_view USING(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");
+    -- Delete paths
+    DELETE FROM path_view
+    WHERE path_view.owner_app_label_name=OLD.app_name;
+
+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 USING(app_id)
+WHERE       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 USING(permission_id)
+INNER JOIN  app_label_with_permission_view AS app2
+            ON app2.permission_id = p.target_permission_id
+WHERE       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 USING(permission_id)
+INNER JOIN  label USING(label_id)
+WHERE       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 USING(permission_id)
+INNER JOIN  app_path USING(app_path_type_id)
+INNER JOIN  label USING(label_id)
+WHERE       app.name != label.name;
+
+
+-- LABEL TO PATH TYPE RULE VIEW -------------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_label_app_path_type_rule_view;
+CREATE VIEW ltl_label_app_path_type_rule_view AS
+SELECT      (CASE WHEN is_reverse = 0 THEN label.name ELSE path_label.name END) AS subject,
+            (CASE WHEN is_reverse = 1 THEN label.name ELSE path_label.name END) AS object,
+            l.access AS access,
+            0 AS is_volatile
+FROM        label_app_path_type_rule AS l
+INNER JOIN  label USING(label_id)
+INNER JOIN  app_path USING(app_path_type_id)
+INNER JOIN  label AS path_label ON app_path.label_id = path_label.label_id
+WHERE       path_label.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 USING(app_id)
+INNER JOIN  label USING(label_id);
+
+
+-- PERMISSION FROM PATHS TO APPLICATIONS ---------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_app_path_reverse_view;
+CREATE VIEW ltl_app_path_reverse_view AS
+SELECT      label.name                AS subject,
+            application_view.name     AS object,
+            app_path.access_reverse   AS access
+FROM        app_path
+INNER JOIN  application_view USING(app_id)
+INNER JOIN  label USING(label_id)
+WHERE       app_path.access_reverse != 0 ;
+
+
+-- 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, is_volatile
+        FROM   ltl_label_app_path_type_rule_view
+        UNION ALL
+        SELECT subject, object, access, 0
+        FROM   ltl_app_path_view
+        UNION ALL
+        SELECT subject, object, access, 0
+        FROM   ltl_app_path_reverse_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.1;
+
+COMMIT TRANSACTION;
diff --git a/db/rules-db.xml b/db/rules-db.xml
new file mode 100644 (file)
index 0000000..35e16b0
--- /dev/null
@@ -0,0 +1,247 @@
+<?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="access_reverse" 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" />
+<relation table="label_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>
+<table x="849" y="620" name="label_app_path_type_rule">
+<row name="label_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+<relation table="label" row="label_id" />
+</row>
+<row name="app_path_type_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+<default>0</default></row>
+<row name="is_reverse" null="1" autoincrement="0">
+<datatype>TINYINT</datatype>
+<default>NULL</default></row>
+<key type="PRIMARY" name="">
+<part>label_id</part>
+<part>app_path_type_id</part>
+<part>is_reverse</part>
+</key>
+</table>
+</sql>
index 6b1c1d2..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,15 +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);
-
 #endif // _ACCESS_DB_H_
index 5c88e65..2ffc389 100644 (file)
@@ -26,6 +26,8 @@
 #include <dlog.h>
 #include <fts.h>
 #include <stdbool.h>
+#include <sys/smack.h>
+#include "privilege-control.h"
 
 #ifdef LOG_TAG
     #undef LOG_TAG
@@ -41,7 +43,7 @@
 #else
 #define C_LOGD(...) do { } while(0)
 #define SECURE_C_LOGD(...) do { } while(0)
-#endif //DDLOG_DEBUG_ENABLED
+#endif //DLOG_DEBUG_ENABLED
 
 // conditional log macro for dlogutil (warning)
 #ifdef DLOG_WARN_ENABLED
@@ -96,16 +98,105 @@ void fts_closep(FTS **f);
 #define SMACK_STARTUP_RULES_FILE "/opt/etc/smack-app-early/accesses.d/rules"
 #define SMACK_LOADED_APP_RULES   "/var/run/smack-app/"
 
+#define SMACK_APP_LABEL_TEMPLATE        "~APP~"
+#define SMACK_SHARED_DIR_LABEL_TEMPLATE "~APP_SHARED_DIR~"
+#define ACC_LEN 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);
 inline int have_smack(void);
+int base_name_from_perm(const char *perm, char **name);
+
+
+/**
+ * Set EXEC label on executable file or symlink to executable file
+ *
+ * @param label label to be set
+ * @param path  link to exec file or symbolic link to exec file
+ * @return      PC_OPERATION_SUCCESS on success,
+ *              error code otherwise
+ */
+int set_exec_label(const char *label, const char *path);
+
+
+/**
+ * Get the permission family type name.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  app_type type of the application
+ * @return          PC_OPERATION_SUCCESS on success,
+ *                  error code otherwise
+ */
+const char* app_type_name(app_type_t app_type);
+
+/**
+ * Get the permission type name
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  app_type type of the application
+ * @return          PC_OPERATION_SUCCESS on success,
+ *                  error code otherwise
+ */
+const char* app_type_group_name(app_type_t app_type);
+
+/**
+ * Divide a Smack rule into subject, object and access
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  s_rule    the rule
+ * @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 tokenize_rule(const char *const s_rule,
+                 char s_subject[],
+                 char s_object[],
+                 char s_access[]);
+
+/**
+ * Check if the label is a wildcard.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  s_label the label
+ * @return         is the label a wildcard?
+ */
+bool is_wildcard(const char *const s_label);
+
+/**
+ * Divides the rule into subject, object and access strings.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  s_rule         the string that we parse
+ * @param  s_label        buffer for the label
+ * @param  s_access       buffer for the access
+ * @param  pi_is_reverse  buffer for the is_reversed
+ * @return                PC_OPERATION_SUCCESS on success,
+ *                        error code otherwise
+ */
+int parse_rule(const char *const s_rule,
+              char s_label[],
+              char s_access[],
+              int *pi_is_reverse);
+
+/**
+ * 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);
 
 #endif /* COMMON_H_ */
index d8576cc..76c7aa5 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <stdbool.h>
 #include <sys/types.h>
-#include <sys/smack.h>
 
 #ifndef _PRIVILEGE_CONTROL_H_
 #define _PRIVILEGE_CONTROL_H_
@@ -39,6 +38,7 @@ extern "C" {
 #endif // API
 
 #define DEPRECATED __attribute__((deprecated));
+#define UNUSED __attribute__((unused))
 
 /* error codes */
 #define        PC_OPERATION_SUCCESS            ((int)0)
@@ -47,27 +47,74 @@ extern "C" {
 #define PC_ERR_NOT_PERMITTED           -3
 #define PC_ERR_INVALID_PARAM           -4
 #define PC_ERR_INVALID_OPERATION       -5
-#define PC_ERR_DB_OPERATION                    -6
+#define PC_ERR_DB_OPERATION            -6
+
+/// Label is taken by another application
+#define PC_ERR_DB_LABEL_TAKEN           -7
+
+/// Query fails during preparing a SQL statement
+#define PC_ERR_DB_QUERY_PREP            -8
+
+/// Query fails during binding to a SQL statement
+#define PC_ERR_DB_QUERY_BIND            -9
+
+/// Query fails during stepping a SQL statement
+#define PC_ERR_DB_QUERY_STEP            -10
+
+// Unable to establish a connection with the database
+#define PC_ERR_DB_CONNECTION            -11
+
+// There is no application with such app_id
+#define PC_ERR_DB_NO_SUCH_APP           -12
+
+// There already exists a permission with this name and type
+#define PC_ERR_DB_PERM_FORBIDDEN        -13
+
 
 typedef enum {
-       APP_TYPE_WGT,
-       APP_TYPE_OSP,
-       APP_TYPE_OTHER,
-       APP_TYPE_WGT_PARTNER,
-       APP_TYPE_WGT_PLATFORM,
-       APP_TYPE_OSP_PARTNER,
-       APP_TYPE_OSP_PLATFORM,
-       APP_TYPE_EFL,
+       PERM_APP_TYPE_WGT,
+       PERM_APP_TYPE_OSP,
+       PERM_APP_TYPE_OTHER,
+       PERM_APP_TYPE_WGT_PARTNER,
+       PERM_APP_TYPE_WGT_PLATFORM,
+       PERM_APP_TYPE_OSP_PARTNER,
+       PERM_APP_TYPE_OSP_PLATFORM,
+       PERM_APP_TYPE_EFL,
 } app_type_t;
 
 typedef enum {
-       APP_PATH_PRIVATE,
-       APP_PATH_GROUP_RW,
-       APP_PATH_PUBLIC_RO,
-       APP_PATH_SETTINGS_RW,
-       APP_PATH_ANY_LABEL,
+       PERM_APP_PATH_PRIVATE,
+       PERM_APP_PATH_GROUP,
+       PERM_APP_PATH_PUBLIC,
+       PERM_APP_PATH_SETTINGS,
+       PERM_APP_PATH_NPRUNTIME,
+       PERM_APP_PATH_ANY_LABEL,
 } app_path_type_t;
 
+
+// TODO: after all projects change their code delete these defines
+// Historical in app_type_t
+#define APP_TYPE_WGT PERM_APP_TYPE_WGT
+#define APP_TYPE_OSP PERM_APP_TYPE_OSP
+#define APP_TYPE_OTHER PERM_APP_TYPE_OTHER
+#define APP_TYPE_WGT_PARTNER PERM_APP_TYPE_WGT_PARTNER
+#define APP_TYPE_WGT_PLATFORM PERM_APP_TYPE_WGT_PLATFORM
+#define APP_TYPE_OSP_PARTNER PERM_APP_TYPE_OSP_PARTNER
+#define APP_TYPE_OSP_PLATFORM PERM_APP_TYPE_OSP_PLATFORM
+#define APP_TYPE_EFL PERM_APP_TYPE_EFL
+
+// Historical names in app_path_type_t
+#define APP_PATH_PRIVATE PERM_APP_PATH_PRIVATE
+#define APP_PATH_GROUP PERM_APP_PATH_GROUP
+#define APP_PATH_PUBLIC PERM_APP_PATH_PUBLIC
+#define APP_PATH_SETTINGS PERM_APP_PATH_SETTINGS
+#define APP_PATH_ANY_LABEL PERM_APP_PATH_ANY_LABEL
+#define APP_PATH_GROUP_RW APP_PATH_GROUP
+#define APP_PATH_PUBLIC_RO APP_PATH_PUBLIC
+#define APP_PATH_SETTINGS_RW APP_PATH_SETTINGS
+
+
+
 /* APIs - used by applications */
 int control_privilege(void) DEPRECATED;
 
@@ -79,7 +126,7 @@ int set_privilege(const char* pkg_name) DEPRECATED;
  * @param out: label of process
  * @return PC_OPERATION_SUCCESS on success PC_ERR_* on error.
  */
-int get_smack_label_from_process(pid_t pid, char smack_label[SMACK_LABEL_LEN + 1]);
+int get_smack_label_from_process(pid_t pid, char *smack_label);
 
 /**
  * Check if process with pid has access to object.
@@ -293,23 +340,31 @@ int app_label_shared_dir(const char* app_label, const char* shared_label,
 int add_shared_dir_readers(const char* shared_label, const char** app_list) DEPRECATED;
 
 /**
- * Recursively set SMACK labels for an application directory. The exact behavior
- * depends on app_path_type argument:
+ * Set SMACK labels for an application directory (recursively) or for an executable/symlink file.
+ * The exact behavior depends on app_path_type argument:
  *     - APP_PATH_PRIVATE: label with app's label, set access label on everything
  *    and execute label on executable files and symlinks to executable files
  *
- *     - APP_PATH_GROUP_RW: label with given shared_label, set access label on
+ *     - APP_PATH_GROUP: label with given shared_label, set access label on
  *       everything and enable transmute on directories. Also give pkg_id full access
  *       to the shared label.
  *
- *     - APP_PATH_PUBLIC_RO: label with autogenerated label, set access label on
+ *     - APP_PATH_PUBLIC: label with autogenerated label, set access label on
  *       everything and enable transmute on directories. Give full access to the label to
  *       pkg_id and RX access to all other apps.
  *
- *     - APP_PATH_SETTINGS_RW: label with autogenerated label, set access label on
+ *     - APP_PATH_SETTINGS: label with autogenerated label, set access label on
  *       everything and enable transmute on directories. Give full access to the label to
  *       pkg_id and RWX access to all appsetting apps.
  *
+ *     - PERM_APP_PATH_NPRUNTIME: label executable file or symlink to an exec given in path param
+ *       with label "<pkg_id>.npruntime". Set execute label on it.
+ *       Give pkg_id RW access to new created label and give new label RXAT access to pkg_id.
+ *
+ *     - APP_PATH_ANY_LABEL: label with given shared_label. Set access label on
+ *       everything and execute label on executable files and symlinks to
+ *       executable files.
+ *
  * This function should be called during app installation.
  * Results will be persistent on the file system.
  * It must be called by privileged user.
@@ -317,7 +372,8 @@ int add_shared_dir_readers(const char* shared_label, const char** app_list) DEPR
  * @param pkg_id
  * @param path
  * @param app_path_type
- * @param shared_label (optional argument for APP_PATH_GROUP_RW path type)
+ * @param shared_label (optional argument for APP_PATH_GROUP_RW and
+ *        APP_PATH_ANY_LABEL path type; type is const char*)
  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
  */
 int perm_app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...);
@@ -361,6 +417,29 @@ 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_begin(void);
+
+/**
+ * Run after any privilege modification.
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int perm_end(void);
+
+/**
+ * Add additional rules to libprivilege.
+ * The rules can use wild-cards and labels.
+ *
+ * @param  set_smack_rule_set an array of rules, NULL terminated
+ * @return                    PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int perm_add_additional_rules(const char** set_smack_rule_set);
+
+
 #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..2dc7412
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @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.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @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);
+
+/**
+ * Adds label names of the application's folders to the modified labels.
+ * Used during removing application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db             pointer to a SQLite3 database object
+ * @param  s_app_label_name label of the application
+ * @return                  PC_OPERATION_SUCCESS on success,
+ *                          error code otherwise
+ */
+int add_modified_apps_path_internal(sqlite3 *p_db, const char *const s_app_label_name);
+/**
+ * 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 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);
+
+
+/**
+ * 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  s_access           owner to path label access rights
+ * @param  s_access_reverse   path label to owner 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_access_reverse,
+                     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);
+
+
+/**
+ * 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);
+
+
+/**
+ * Prepare tables with smack rules.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db pointer to a SQLite3 database object
+ * @return      PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int update_rules_in_db(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);
+
+
+/**
+ * Add additional rules to the database.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db           pointer to a SQLite3 database object
+ * @param  pp_smack_rules a list of smack rules
+ * @return                PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_additional_rules_internal(sqlite3 *p_db,
+                                 const char  *const *const pp_smack_rules);
+
+#endif // _RULES_DB_INTERNALS_H_
diff --git a/include/rules-db.h b/include/rules-db.h
new file mode 100644 (file)
index 0000000..81f5014
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * 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  s_access           owner to path label access rights
+ * @param  s_access_reverse   path label to owner 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_access_reverse,
+                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  i_permission_type      permission's type id
+ * @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 app_type_t i_permission_type,
+                              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  i_permission_type      permission's type id
+ * @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 app_type_t i_permission_type,
+                               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);
+
+/**
+ * Add the additional rules to the database. Erase the previous rules.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  pp_smack_rules NULL terminated table of rules
+ * @return                PC_OPERATION_SUCCESS on success,
+ *                        error code otherwise
+ */
+int rdb_add_additional_rules(const char *const *const pp_smack_rules);
+
+#endif /*_RULES_DB_H_*/
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..7e00638 100644 (file)
@@ -1,5 +1,92 @@
-* Tue Aug 20 2013 Rafal Krypa <r.krypa@samsung.com> - 0.0.42.TIZEN
-- Changed dlog logging buffer.
+* Fri Oct 25 2013 Krzysztof Jackiewicz - 0.0.43.TIZEN
+[Krzysztof Jackiewicz]
+- Revert "add API definition"
+[Marcin Lis]
+- Implement new wildcard ~NPRUNTIME_PATH~ +fix workaround
+[Marcin Lis]
+- Implement adding new WRT rules in libprivilege-control
+[Kidong Kim]
+- add API definition
+[Jan Olszak]
+- Correction in enabling permissions.
+[Jan Olszak]
+- Renamed enums and deleted unused defines
+[Jan Olszak]
+- Modified checking labels and deleted unused checking.
+[Jan Olszak]
+- Change in setup path.
+[Jan Olszak]
+- Change in boot script.
+[Jan Olszak]
+- Adding additional rules.
+[Jan Olszak]
+- Implementation of cross-app rule patterns in *.smack files
+[Jan Olszak]
+- Corrected a mistake in deleting paths.
+[Jan Olszak]
+- Deleting paths on revoking permissions.
+[Jan Olszak]
+- Deleted volatile rules on boot and corrected permission format.
+[Jan Olszak]
+- Modified boot script, added deleting volatile rules.
+[Jan Olszak]
+- Made marking labels as modified beautiful.
+[Jan Olszak]
+- Changed new API names.
+[Jan Olszak]
+- Loading api-features from a file.
+[Jan Olszak]
+- Revert "rollback because of rule database"
+[Kidong Kim]
+- add systemd options
+[Jan Cybulski]
+- Add README file
+[Marcin Lis]
+- Compilation flags 'verbose' mode
+[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.
+[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. +Fix
+
+* 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 a61a9fb..22705d4 100644 (file)
@@ -2,7 +2,7 @@
 
 Name:       libprivilege-control
 Summary:    Library to control privilege of application
-Version:    0.0.42.TIZEN
+Version:    0.0.43.TIZEN
 Release:    1
 Group:      System/Security
 License:    Apache 2.0
@@ -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
@@ -43,9 +45,10 @@ Library to control privilege of application files
 
 %build
 export CFLAGS="${CFLAGS} -Wno-implicit-function-declaration"
-%cmake . -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}
+%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}
@@ -65,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
@@ -98,19 +100,30 @@ then
        mkdir -p /opt/etc/smack-app-early/accesses.d
 fi
 
+sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db.sql
+rm -f /opt/dbspace/rules-db.sql
+
+sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db-data.sql
+rm -f /opt/dbspace/rules-db-data.sql
+
+api_feature_loader --verbose --dir=/usr/share/privilege-control/
+api_feature_loader --verbose --rules=/usr/share/privilege-control/ADDITIONAL_RULES.smack
+
 %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
@@ -125,5 +138,5 @@ fi
 
 %files devel
 %{_includedir}/*.h
-%{_libdir}/*.so
+%{_libdir}/libprivilege-control.so
 %{_libdir}/pkgconfig/*.pc
index 50201c4..c03114c 100644 (file)
@@ -1,5 +1,6 @@
 [Unit]
 Description=Default SMACK labeling
+ConditionSecurity=smack
 DefaultDependencies=no
 Requires=smack.service local-fs.target
 After=smack.service local-fs.target
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 ef4decb..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-[Unit]
-Description=Late SMACK rules loading
-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 6796bfd..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-[Unit]
-Description=Late SMACK rules loading
-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..f8bbc2b
--- /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 = /bin/bash -c '/bin/grep ^ /opt/etc/smack/boot-rules.smack --line-buffered > /smack/change-rule'
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
index b4167ca..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_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_app_setting.db",
-               "/opt/dbspace/.privilege_control_setting_dir.db",
+               "/opt/dbspace/.privilege_control_app_gids.db"
 };
 
 typedef struct element_s {
@@ -82,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__);
@@ -98,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",
@@ -121,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__);
@@ -214,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)
 {
@@ -320,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",
@@ -390,31 +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;
-}
+}
\ No newline at end of file
index 2478ad4..2ae67b5 100644 (file)
 #include <sys/smack.h>
 #include <sys/stat.h>
 #include <sys/file.h>
+#include <iri.h>
 
 #include "common.h"
 #include "privilege-control.h"
 
 /* TODO: implement such function in libsmack instead */
-int smack_label_is_valid(const charsmack_label)
+int smack_label_is_valid(const char *smack_label)
 {
        SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s",
-                               __func__, smack_label);
+                     __func__, smack_label);
 
        int i;
 
-       if (!smack_label || smack_label[0] == '\0' || smack_label[0] == '-')
+       if(!smack_label || smack_label[0] == '\0' || smack_label[0] == '-')
                goto err;
 
-       for (i = 0; smack_label[i]; ++i) {
-               if (i >= SMACK_LABEL_LEN)
+       for(i = 0; smack_label[i]; ++i) {
+               if(i >= SMACK_LABEL_LEN)
                        goto err;
-               switch (smack_label[i]) {
+               switch(smack_label[i]) {
                case '~':
                case ' ':
                case '/':
@@ -64,160 +65,236 @@ err:
        return 0;
 }
 
-/* Auto cleanup stuff */
-void freep(void *p)
-{
-       free(*(void**) p);
-}
 
-void closep(int *fd)
+int set_exec_label(const char *label, const char *path)
 {
-       if (*fd >= 0)
-               close(*fd);
-}
+       struct stat st;
 
-void fclosep(FILE **f)
-{
-       if (*f)
-               fclose(*f);
+       if(stat(path, &st) < 0) {
+               SECURE_C_LOGE("stat failed for %s (Error = %s)", path, strerror(errno));
+               return PC_ERR_FILE_OPERATION;
+       }
+
+       // check if it's a link
+       if((st.st_mode & S_IFLNK) != 0) {
+               SECURE_C_LOGD("%s is a symbolic link", path);
+               char* target AUTO_FREE;
+               target = realpath(path, NULL);
+               if(!target) {
+                       SECURE_C_LOGE("getting link target for %s failed (Error = %s)",
+                                     path, strerror(errno));
+                       return PC_ERR_FILE_OPERATION;
+               }
+
+               if(stat(target, &st) < 0) {
+                       SECURE_C_LOGE("stat failed for %s (Error = %s)", target, strerror(errno));
+                       return PC_ERR_FILE_OPERATION;
+               }
+
+               if((st.st_mode & (S_IXUSR | S_IFREG)) != (S_IXUSR | S_IFREG)) {
+                       SECURE_C_LOGE("%s is not a regular executable file.", target);
+                       return PC_ERR_FILE_OPERATION;
+               }
+       } else if((st.st_mode & (S_IXUSR | S_IFREG)) != (S_IXUSR | S_IFREG)) {
+               SECURE_C_LOGE("%s is not a regular executable file nor a symbolic link.", path);
+               return PC_ERR_FILE_OPERATION;
+       }
+
+       SECURE_C_LOGD("smack_lsetlabel (label: %s (type: SMACK_LABEL_EXEC), path: %s)",
+                     label, path);
+       if (smack_lsetlabel(path, label, SMACK_LABEL_EXEC) != 0) {
+               SECURE_C_LOGE("smack_lsetlabel failed.");
+               return PC_ERR_FILE_OPERATION;
+       }
+       return PC_OPERATION_SUCCESS;
 }
 
-void smack_freep(struct smack_accesses **smack)
+
+int tokenize_rule(const char *const s_rule,
+                 char s_subject[],
+                 char s_object[],
+                 char s_access[])
 {
-       smack_accesses_free(*smack);
+       if(sscanf(s_rule, "%s %s %s", s_subject, s_object, s_access) < 3) {
+               C_LOGE("RDB: Failed to tokenize the rule: %s", s_rule);
+               return PC_ERR_INVALID_OPERATION;
+       }
+       return PC_OPERATION_SUCCESS;
 }
 
-void fts_closep(FTS **f)
-{
-       if (*f)
-               fts_close(*f);
 
+bool is_wildcard(const char *const s_label)
+{
+       return  !strcmp(s_label, "~ALL_APPS~") ||
+               !strcmp(s_label, "~ALL_APPS_WITH_SAME_PERMISSION~") ||
+               !strcmp(s_label, "~PUBLIC_PATH~") ||
+               !strcmp(s_label, "~GROUP_PATH~") ||
+               !strcmp(s_label, "~SETTINGS_PATH~") ||
+               !strcmp(s_label, "~NPRUNTIME_PATH~");
 }
 
-/**
- * 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)
+
+int parse_rule(const char *const s_rule,
+              char s_label[],
+              char s_access[],
+              int *pi_is_reverse)
 {
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
-       int ret;
-       char *path AUTO_FREE;
+       int ret = PC_OPERATION_SUCCESS;
+       char tmp_s_subject[SMACK_LABEL_LEN + 1];
+       char tmp_s_object[SMACK_LABEL_LEN + 1];
+       char tmp_s_access[ACC_LEN + 1];
+
+       bool b_subject_is_template;
+       bool b_object_is_template;
+
+       // Tokenize
+       ret = tokenize_rule(s_rule, tmp_s_subject, tmp_s_object, tmp_s_access);
+       if(ret != PC_OPERATION_SUCCESS) return ret;
+
+       // Check SMACK_APP_LABEL_TEMPLATE
+       b_subject_is_template = (bool) !strcmp(tmp_s_subject, SMACK_APP_LABEL_TEMPLATE);
+       b_object_is_template = (bool) !strcmp(tmp_s_object, SMACK_APP_LABEL_TEMPLATE);
+       if((b_subject_is_template && b_object_is_template) ||
+           (!b_subject_is_template && !b_object_is_template)) {
+               C_LOGE("RDB: Incorrect rule format in rule: %s", s_rule);
+               ret = PC_ERR_INVALID_PARAM;
+               return ret;
+       }
 
-       ret = smack_mark_file_name(app_id, &path);
-       if(PC_OPERATION_SUCCESS != ret) {
-               return -1;
+       // Check label validity and copy rules
+       if(b_subject_is_template) {
+               // Not reversed
+               if(!smack_label_is_valid(tmp_s_object) &&
+                   !is_wildcard(tmp_s_object)) {
+                       C_LOGE("RDB: Incorrect subject label: %s", tmp_s_object);
+                       return ret;
+               }
+               strcpy(s_label, tmp_s_object);
+               if(pi_is_reverse != NULL) *pi_is_reverse = 0;
+       } else if(b_object_is_template) {
+               // Reversed
+               if(!smack_label_is_valid(tmp_s_subject) &&
+                   !is_wildcard(tmp_s_subject)) {
+                       C_LOGE("RDB: Incorrect subject label: %s", tmp_s_subject);
+                       return ret;
+               }
+               strcpy(s_label, tmp_s_subject);
+               if(pi_is_reverse != NULL) *pi_is_reverse = 1;
        }
+       strcpy(s_access, tmp_s_access);
 
-       return file_exists(path);
+       return PC_OPERATION_SUCCESS;
 }
 
-/**
- * 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;
-       }
+int validate_all_rules(const char *const *const pp_permissions_list)
+{
+       int i;
+       char s_label[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_label, s_access, NULL)
+                   != PC_OPERATION_SUCCESS) {
+                       C_LOGE("RDB: Invalid parameter");
+                       return PC_ERR_INVALID_PARAM;
+               }
 
-       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);
+               // Check the other label
+               if(!is_wildcard(s_label) &&
+                   !smack_label_is_valid(s_label)) {
+                       C_LOGE("RDB: Incorrect object label: %s", s_label);
+                       return PC_ERR_INVALID_PARAM;
                }
        }
 
-       SECURE_C_LOGD("Creating file %s.", path);
-       file = fopen(path, "w");
-       fclose(file);
+       return PC_OPERATION_SUCCESS;
 }
 
-int add_app_first_run_rules(const char *app_id)
+/* Auto cleanup stuff */
+void freep(void *p)
 {
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+       free(*(void **) p);
+}
 
-       int ret;
-       int fd AUTO_CLOSE;
-       char *smack_path AUTO_FREE;
-       struct smack_accesses* smack AUTO_SMACK_FREE;
+void closep(int *fd)
+{
+       if(*fd >= 0)
+               close(*fd);
+}
 
-       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;
-       }
+void fclosep(FILE **f)
+{
+       if(*f)
+               fclose(*f);
+}
 
-       return PC_OPERATION_SUCCESS;
+void smack_freep(struct smack_accesses **smack)
+{
+       smack_accesses_free(*smack);
 }
 
+void fts_closep(FTS **f)
+{
+       if(*f)
+               fts_close(*f);
+
+}
 
-static int load_smack_from_file_generic(const char* app_id, struct smack_accesses** smack, int *fd, char** path, bool is_early)
+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.
         * It's because all of the "early rules" (for all apps) should
         * be in one common file: SMACK_STARTUP_RULES_FILE
         */
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
        int ret;
 
-       if (is_early) {
-               if (0 > asprintf(path, "%s", SMACK_STARTUP_RULES_FILE)) {
+       if(is_early) {
+               if(0 > asprintf(path, "%s", SMACK_STARTUP_RULES_FILE)) {
                        *path = NULL;
                        C_LOGE("asprintf failed.");
                        return PC_ERR_MEM_OPERATION;
                }
-       }
-       else {
+       } else {
                ret = smack_file_name(app_id, path);
-               if (ret != PC_OPERATION_SUCCESS)
+               if(ret != PC_OPERATION_SUCCESS)
                        return ret;
        }
 
-       if (smack_accesses_new(smack)) {
+       if(smack_accesses_new(smack)) {
                C_LOGE("smack_accesses_new failed.");
                return PC_ERR_MEM_OPERATION;
        }
 
-       *fd = open(*path, O_CREAT|O_RDWR, 0644);
-       if (*fd == -1) {
+       *fd = open(*path, O_CREAT | O_RDWR, 0644);
+       if(*fd == -1) {
                C_LOGE("file open failed (error: %s)", strerror(errno));
                return PC_ERR_FILE_OPERATION;
        }
 
-       if (flock(*fd, LOCK_EX)) {
+       if(flock(*fd, LOCK_EX)) {
                C_LOGE("flock failed");
                return PC_ERR_INVALID_OPERATION;
        }
 
-       if (smack_accesses_add_from_file(*smack, *fd)) {
+       if(smack_accesses_add_from_file(*smack, *fd)) {
                C_LOGE("smack_accesses_add_from_file failed.");
                return PC_ERR_INVALID_OPERATION;
        }
 
        /* Rewind the file */
-       if (lseek(*fd, 0, SEEK_SET) == -1) {
+       if(lseek(*fd, 0, SEEK_SET) == -1) {
                C_LOGE("lseek failed.");
                return PC_ERR_FILE_OPERATION;
        }
@@ -225,18 +302,18 @@ static int load_smack_from_file_generic(const char* app_id, struct smack_accesse
        return PC_OPERATION_SUCCESS;
 }
 
-int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd, char** path)
+int load_smack_from_file(const char *app_id, struct smack_accesses **smack, int *fd, char **path)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
        return load_smack_from_file_generic(app_id, smack, fd, path, 0);
 }
 
-int load_smack_from_file_early(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)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
        return load_smack_from_file_generic(app_id, smack, fd, path, 1);
 }
@@ -244,9 +321,9 @@ int load_smack_from_file_early(const char* app_id, struct smack_accesses** smack
 int smack_mark_file_name(const char *app_id, char **path)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
-       if (asprintf(path, SMACK_LOADED_APP_RULES "/%s", app_id) == -1) {
+       if(asprintf(path, SMACK_LOADED_APP_RULES "/%s", app_id) == -1) {
                C_LOGE("asprintf failed.");
                *path = NULL;
                return PC_ERR_MEM_OPERATION;
@@ -255,25 +332,26 @@ int smack_mark_file_name(const char *app_id, char **path)
        return PC_OPERATION_SUCCESS;
 }
 
-bool file_exists(const char* path) {
+bool file_exists(const char *path)
+{
        SECURE_C_LOGD("Entering function: %s. Params: path=%s",
-                               __func__, path);
+                     __func__, path);
 
        SECURE_C_LOGD("Opening file %s.", path);
-       FILEfile = fopen(path, "r");
-       if (file) {
+       FILE *file = fopen(path, "r");
+       if(file) {
                fclose(file);
                return true;
        }
        return false;
 }
 
-int smack_file_name(const char* app_id, char** path)
+int smack_file_name(const char *app_id, char **path)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
-       if (asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) {
+       if(asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) {
                C_LOGE("asprintf failed.");
                *path = NULL;
                return PC_ERR_MEM_OPERATION;
@@ -288,8 +366,8 @@ inline int have_smack(void)
 
        static int have_smack = -1;
 
-       if (-1 == have_smack) {
-               if (NULL == smack_smackfs_path()) {
+       if(-1 == have_smack) {
+               if(NULL == smack_smackfs_path()) {
                        C_LOGD("Libprivilege-control: no smack found on phone");
                        have_smack = 0;
                } else {
@@ -300,3 +378,114 @@ inline int have_smack(void)
 
        return have_smack;
 }
+
+inline const char* app_type_name(app_type_t app_type)
+{
+       SECURE_C_LOGD("Entering function: %s. Params: app_type=%d",
+                               __func__, app_type);
+
+       switch (app_type) {
+       case PERM_APP_TYPE_WGT:
+               C_LOGD("App type = WRT");
+               return "WRT";
+       case PERM_APP_TYPE_OSP:
+               C_LOGD("App type = OSP");
+               return "OSP";
+       case PERM_APP_TYPE_WGT_PARTNER:
+               C_LOGD("App type = WRT_partner");
+               return "WRT_partner";
+       case PERM_APP_TYPE_WGT_PLATFORM:
+               C_LOGD("App type = WRT_platform");
+               return "WRT_platform";
+       case PERM_APP_TYPE_OSP_PARTNER:
+               C_LOGD("App type = OSP_partner");
+               return "OSP_partner";
+       case PERM_APP_TYPE_OSP_PLATFORM:
+               C_LOGD("App type = OSP_platform");
+               return "OSP_platform";
+       case PERM_APP_TYPE_EFL:
+               C_LOGD("App type = EFL");
+               return "EFL";
+       default:
+               C_LOGD("App type = other");
+               return NULL;
+       }
+}
+
+inline const char* app_type_group_name(app_type_t app_type)
+{
+       SECURE_C_LOGD("Entering function: %s. Params: app_type=%d",
+                               __func__, app_type);
+
+       switch (app_type) {
+       case PERM_APP_TYPE_WGT:
+       case PERM_APP_TYPE_WGT_PARTNER:
+       case PERM_APP_TYPE_WGT_PLATFORM:
+               C_LOGD("App type group name = WRT");
+               return "WRT";
+       case PERM_APP_TYPE_OSP:
+       case PERM_APP_TYPE_OSP_PARTNER:
+       case PERM_APP_TYPE_OSP_PLATFORM:
+               C_LOGD("App type group name = OST");
+               return "OSP";
+       case PERM_APP_TYPE_EFL:
+               C_LOGD("App type = EFL");
+               return "EFL";
+       default:
+               return NULL;
+       }
+}
+
+
+/**
+ * This function changes permission URI to basename for file name.
+ * For e.g. from http://tizen.org/privilege/contact.read will be
+ * created basename : org.tizen.privilege.contact.read
+ */
+
+int base_name_from_perm(const char *perm, char **name)
+{
+       SECURE_C_LOGD("Entering function: %s. Params: perm=%s",
+                               __func__, perm);
+
+       iri_t *ip = NULL;
+       char *host_dot = NULL;
+       char *rest_slash = NULL;
+       int ret;
+
+       ip = iri_parse(perm);
+       if (ip == NULL || ip->host == NULL) {
+               SECURE_C_LOGE("Bad permission format : %s", perm);
+               iri_destroy(ip);
+               return PC_ERR_INVALID_PARAM;
+       }
+
+       if (ip->path == NULL) {
+               ip->path = ip->host;
+               ip->host = NULL;
+       }
+
+       if (ip->host) {
+               host_dot = strrchr(ip->host, '.');
+               if (host_dot) {
+                       *host_dot = '\0';
+                       ++host_dot;
+               }
+       }
+
+       while ((rest_slash = strchr(ip->path, '/'))) {
+               *rest_slash = '.';
+       }
+
+       ret = asprintf(name, "%s%s%s%s",
+                       host_dot ? host_dot : "", host_dot ? "." : "",
+                       ip->host ? ip->host : "", ip->path);
+       if (ret == -1) {
+               C_LOGE("asprintf failed");
+               iri_destroy(ip);
+               return PC_ERR_MEM_OPERATION;
+       }
+
+       iri_destroy(ip);
+       return PC_OPERATION_SUCCESS;
+}
index 8fe7ede..4dc7c8d 100644 (file)
 #include <sys/mman.h>
 #include <stdbool.h>
 #include <search.h>
-#include <iri.h>
 
 #include "privilege-control.h"
 #include "access-db.h"
 #include "common.h"
+#include "rules-db.h"
 
 #define APP_GID        5000
 #define APP_UID        5000
@@ -61,9 +61,6 @@
 #define APP_GROUP_PATH TOSTRING(SHAREDIR) "/app_group_list"
 #define DEV_GROUP_PATH TOSTRING(SHAREDIR) "/dev_group_list"
 
-#define SMACK_APP_LABEL_TEMPLATE        "~APP~"
-#define SMACK_SHARED_DIR_LABEL_TEMPLATE "~APP_SHARED_DIR~"
-
 #define SMACK_SRC_FILE_SUFFIX   "_src_file"
 #define SMACK_SRC_DIR_SUFFIX    "_src_dir"
 #define SMACK_DATA_SUFFIX       "_data"
@@ -95,6 +92,28 @@ enum {
        DECISION_LABEL = 1
 };
 
+__attribute__ ((destructor))
+static void libprivilege_destructor()
+{
+       SECURE_C_LOGD("Entering function: %s.", __func__);
+       perm_end();
+}
+
+API int perm_begin(void)
+{
+       SECURE_C_LOGD("Entering function: %s.", __func__);
+       return rdb_modification_start();
+}
+
+API int perm_end(void)
+{
+       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__);
@@ -113,7 +132,7 @@ API int control_privilege(void)//deprecated
 /**
  * TODO: this function should be moved to libsmack in open-source.
  */
-API int get_smack_label_from_process(pid_t pid, char smack_label[SMACK_LABEL_LEN + 1])
+API int get_smack_label_from_process(pid_t pid, char *smack_label)
 {
        SECURE_C_LOGD("Entering function: %s. Params: pid=%i", __func__, pid);
 
@@ -433,9 +452,9 @@ static int get_smack_from_binary(char **smack_label, const char* path, app_type_
        int ret;
 
        *smack_label = NULL;
-       if (type == APP_TYPE_WGT
-       || type == APP_TYPE_WGT_PARTNER
-       || type == APP_TYPE_WGT_PLATFORM) {
+       if (type == PERM_APP_TYPE_WGT
+       || type == PERM_APP_TYPE_WGT_PARTNER
+       || type == PERM_APP_TYPE_WGT_PLATFORM) {
                ret = smack_lgetlabel(path, smack_label, SMACK_LABEL_EXEC);
        } else {
                ret = smack_getlabel(path, smack_label, SMACK_LABEL_EXEC);
@@ -527,13 +546,13 @@ static app_type_t verify_app_type(const char* type, const char* path)
        if (is_widget(path)) {
                if (!strcmp(type, "wgt")) {
                        C_LOGD("PKG_TYPE_WGT");
-                       return APP_TYPE_WGT; /* good */
+                       return PERM_APP_TYPE_WGT; /* good */
                } else if (!strcmp(type, "wgt_partner")) {
                        C_LOGD("PKG_TYPE_WGT_PARTNER");
-                       return APP_TYPE_WGT_PARTNER; /* good */
+                       return PERM_APP_TYPE_WGT_PARTNER; /* good */
                } else if (!strcmp(type, "wgt_platform")) {
                        C_LOGD("PKG_TYPE_WGT_PLATFORM");
-                       return APP_TYPE_WGT_PLATFORM; /* good */
+                       return PERM_APP_TYPE_WGT_PLATFORM; /* good */
                }
 
        } else {
@@ -541,7 +560,7 @@ static app_type_t verify_app_type(const char* type, const char* path)
                                && strcmp(type, "wgt_partner")
                                && strcmp(type, "wgt_platform"))){
                        C_LOGD("PKG_TYPE_OTHER");
-                       return APP_TYPE_OTHER; /* good */
+                       return PERM_APP_TYPE_OTHER; /* good */
                }
        }
 
@@ -565,7 +584,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) {
@@ -577,20 +595,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)
@@ -614,114 +618,6 @@ API int set_privilege(const char* pkg_name)//deprecated
        return perm_app_set_privilege(pkg_name, NULL, NULL);
 }
 
-static inline const char* app_type_name(app_type_t app_type)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_type=%d",
-                               __func__, app_type);
-
-       switch (app_type) {
-       case APP_TYPE_WGT:
-               C_LOGD("App type = APP_TYPE_WGT");
-               return "WRT";
-       case APP_TYPE_OSP:
-               C_LOGD("App type = APP_TYPE_OSP");
-               return "OSP";
-       case APP_TYPE_WGT_PARTNER:
-               C_LOGD("App type = APP_TYPE_WGT_PARTNER");
-               return "WRT_partner";
-       case APP_TYPE_WGT_PLATFORM:
-               C_LOGD("App type = APP_TYPE_WGT_PLATFORM");
-               return "WRT_platform";
-       case APP_TYPE_OSP_PARTNER:
-               C_LOGD("App type = APP_TYPE_OSP_PARTNER");
-               return "OSP_partner";
-       case APP_TYPE_OSP_PLATFORM:
-               C_LOGD("App type = APP_TYPE_OSP_PLATFORM");
-               return "OSP_platform";
-       case APP_TYPE_EFL:
-               return "EFL";
-       default:
-               C_LOGD("App type = other");
-               return NULL;
-       }
-}
-
-static inline const char* app_type_group_name(app_type_t app_type)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: app_type=%d",
-                               __func__, app_type);
-
-       switch (app_type) {
-       case APP_TYPE_WGT:
-       case APP_TYPE_WGT_PARTNER:
-       case APP_TYPE_WGT_PLATFORM:
-               C_LOGD("App type group name = WRT");
-               return "WRT";
-       case APP_TYPE_OSP:
-       case APP_TYPE_OSP_PARTNER:
-       case APP_TYPE_OSP_PLATFORM:
-               C_LOGD("App type group name = OST");
-               return "OSP";
-       case APP_TYPE_EFL:
-               return "EFL";
-       default:
-               return NULL;
-       }
-}
-
-/**
- * This function changes permission URI to basename for file name.
- * For e.g. from http://tizen.org/privilege/contact.read will be
- * created basename : org.tizen.privilege.contact.read
- */
-
-static int base_name_from_perm(const char *perm, char **name)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: perm=%s",
-                               __func__, perm);
-
-       iri_t *ip = NULL;
-       char *host_dot = NULL;
-       char *rest_slash = NULL;
-       int ret;
-
-       ip = iri_parse(perm);
-       if (ip == NULL || ip->host == NULL) {
-               SECURE_C_LOGE("Bad permission format : %s", perm);
-               iri_destroy(ip);
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       if (ip->path == NULL) {
-               ip->path = ip->host;
-               ip->host = NULL;
-       }
-
-       if (ip->host) {
-               host_dot = strrchr(ip->host, '.');
-               if (host_dot) {
-                       *host_dot = '\0';
-                       ++host_dot;
-               }
-       }
-
-       while ((rest_slash = strchr(ip->path, '/'))) {
-               *rest_slash = '.';
-       }
-
-       ret = asprintf(name, "%s%s%s%s",
-                       host_dot ? host_dot : "", host_dot ? "." : "",
-                       ip->host ? ip->host : "", ip->path);
-       if (ret == -1) {
-               C_LOGE("asprintf failed");
-               iri_destroy(ip);
-               return PC_ERR_MEM_OPERATION;
-       }
-
-       iri_destroy(ip);
-       return PC_OPERATION_SUCCESS;
-}
-
 static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix, bool is_early)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, perm=%s, suffix=%s, is_early=%d",
@@ -764,85 +660,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",
@@ -878,7 +695,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__);
 
@@ -981,7 +798,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",
@@ -1014,556 +830,185 @@ 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,
+                                        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;
 }
 
-
-static int
-app_register_appsetting(const char *app_id, struct smack_accesses *smack)
+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);
 
-       int ret;
-       int i;
-
-       char **label_app_list AUTO_FREE;
-       char **label_dir_list AUTO_FREE;
-       int app_list_len = 0;
-       int dir_list_len = 0;
+       return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
+}
 
-       if (!smack_label_is_valid(app_id)) {
-               C_LOGE("Invalid param app_id.");
-               return PC_ERR_INVALID_PARAM;
-       }
+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);
 
-       /* writing appsetting_id (app_id) to "database"*/
-       ret = add_appsetting_id_to_databse(app_id);
-       if (ret != PC_OPERATION_SUCCESS)
-               goto out;
+       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);
 
-       /* 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;
-       }
+       return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
+}
 
-       /*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;
-               }
-       }
+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);
 
-       /* Reading labels of all registered settings dirs from "database"*/
-       ret = get_all_settings_dir_ids(
-                       &label_dir_list, &dir_list_len);
-       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?*/
-               }
-       }
+       return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
+}
 
-       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]);
-       }
+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 ret;
+       return perm_app_disable_permissions(pkg_id, app_type, perm_list);
 }
 
-static int app_register_av_internal(const char *app_av_id, struct smack_accesses* smack)
+/* 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: app_av_id=%s.",
-                               __func__, app_av_id);
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
+                               __func__, pkg_id, app_type);
 
        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 app_id.");
                return PC_ERR_INVALID_PARAM;
        }
 
-       if(smack == NULL) {
-               C_LOGE("Invalid param smack (NULL).");
+       if (perm_list == NULL) {
+               C_LOGE("Invalid perm_list (NULL).");
                return PC_ERR_INVALID_PARAM;
        }
 
-       // 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;
-
-       // 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 geting data 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?
-               }
+       if (app_type_group_name(app_type) == NULL) {
+               C_LOGE("Unknown app type.");
+               return PC_ERR_INVALID_PARAM;
        }
 
-out:
-       for (i = 0; i < smack_label_app_list_len; ++i) {
-               free(smack_label_app_list[i]);
+       ret = rdb_disable_app_permissions(pkg_id, app_type, perm_list);
+       if (ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
+               return ret;
        }
 
-       return ret;
+       return PC_OPERATION_SUCCESS;
 }
 
-/**
- *  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_revoke_permissions(const char* pkg_id)//deprecated
 {
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s.",
-                               __func__, app_id);
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
+       return perm_app_revoke_permissions(pkg_id);
+}
 
-       int ret, i;
-       char** smack_label_av_list AUTO_FREE;
-       int smack_label_av_list_len = 0;
+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;
 
-       // 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;
+       if (!smack_label_is_valid(pkg_id)) {
+               C_LOGE("Invalid param app_id.");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       // 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 = rdb_revoke_app_permissions(pkg_id);
+       if (ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
+               return ret;
        }
 
-       ret = PC_OPERATION_SUCCESS;
+       return 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]);
-       }
+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);
 }
 
-/**
- *  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)
+API int perm_app_reset_permissions(const char* pkg_id)
 {
-       SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
+                               __func__, pkg_id);
+       int ret;
 
-       int ret, i;
-       char **smack_label_list AUTO_FREE;
-       int smack_label_list_len = 0;
+       if (!smack_label_is_valid(pkg_id)) {
+               C_LOGE("Invalid param pkg_id.");
+               return PC_ERR_INVALID_PARAM;
+       }
 
-       /* Reading labels of all installed setting managers from "database"*/
-       ret = get_all_appsetting_ids(&smack_label_list, &smack_label_list_len);
+       ret = rdb_reset_app_permissions(pkg_id);
        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.");
+               C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
                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",
@@ -1602,134 +1047,6 @@ API int app_label_dir(const char* label, const char* path)//deprecated
        return ret;
 }
 
-int smack_get_access_new(const char* subject, const char* object, char** label)
-{
-       SECURE_C_LOGD("Entering function: %s. Params: subject=%s, object=%s",
-                               __func__, subject, object);
-       
-       char buff[ACC_LEN] = {'r', 'w', 'x', 'a', 't', 'l'};
-       char perm[2] = {'-'};
-       int i;
-
-       if(!smack_label_is_valid(subject)) {
-               C_LOGE("Invalid param subject.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       if(!smack_label_is_valid(object)) {
-               C_LOGE("Invalid param object.");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       if(!label) {
-               C_LOGE("Invalid param label (NULL).");
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       for (i=0; i<ACC_LEN; ++i) {
-               perm[0] = buff[i];
-               int ret = smack_have_access(subject, object, perm);
-               if (-1 == ret) {
-                       C_LOGE("smack_have_access failed during %c check.", perm[0]);
-                       return PC_ERR_INVALID_OPERATION;
-               }
-               if (0 == ret)
-                       buff[i] = '-';
-       }
-
-       *label = malloc(ACC_LEN+1);
-       if (NULL == *label)
-               return PC_ERR_MEM_OPERATION;
-
-       memcpy(*label, buff, ACC_LEN);
-       (*label)[ACC_LEN] = 0;
-       return PC_OPERATION_SUCCESS;
-}
-
-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
 {
@@ -1771,46 +1088,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;
-               }
+       C_LOGE("add_shared_dir_readers is deprecated and unimplemented!");
 
-               ret = app_add_rule(app_list[i], shared_label, "rx");
-               if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("app_add_rule failed.");
-                       return ret;
-               }
-       }
-
-       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)
@@ -1843,51 +1132,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;
-}
 
 /* FIXME: remove this pragma once deprecated API is deleted */
 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@@ -1912,8 +1156,8 @@ static int perm_app_setup_path_internal(const char* pkg_id, const char* path, ap
                C_LOGD("app_path_type is APP_PATH_PRIVATE.");
                return app_label_dir(pkg_id, path);
 
-       case APP_PATH_GROUP_RW: {
-               C_LOGD("app_path_type is APP_PATH_GROUP_RW.");
+       case APP_PATH_GROUP: {
+               C_LOGD("app_path_type is APP_PATH_GROUP.");
                int ret;
                const char *shared_label;
 
@@ -1935,111 +1179,108 @@ static int perm_app_setup_path_internal(const char* pkg_id, const char* path, ap
                        return ret;
                }
 
-               return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_GROUP_RW, shared_label);
+               // Add the path to the database:
+               ret = rdb_add_path(pkg_id, shared_label, path, "rwxatl", "-", "GROUP_PATH");
+               if (ret != PC_OPERATION_SUCCESS) {
+                       C_LOGE("RDB rdb_add_path failed with: %d", ret);
+                       return ret;
+               }
+
+               return PC_OPERATION_SUCCESS;
        }
 
-       case APP_PATH_PUBLIC_RO: {
-               C_LOGD("app_path_type is APP_PATH_PUBLIC_RO.");
+       case APP_PATH_PUBLIC: {
+               C_LOGD("app_path_type is APP_PATH_PUBLIC.");
                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_PATH");
                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("smack_accesses_new failed");
-                               while (i < app_ids_cnt)
-                                       free(app_ids[i++]);
-                               return ret;
-                       }
-                       free(app_ids[i]);
-               }
-
-               return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_PUBLIC_RO, label);
+               return PC_OPERATION_SUCCESS;
        }
 
-       case APP_PATH_SETTINGS_RW:
-       {
-               C_LOGD("app_path_type is APP_PATH_SETTINGS_RW.");
+       case APP_PATH_SETTINGS: {
+               C_LOGD("app_path_type is APP_PATH_SETTINGS.");
                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;
                }
+               C_LOGD("Appsetting: generated label '%s' for setting path %s", label, path);
 
                /*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);
+               // Add the path to the database:
+               ret = rdb_add_path(pkg_id, label, path, "rwxatl", "-", "SETTINGS_PATH");
                if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("Appsetting: add_setting_dir_id_to_databse failed");
+                       C_LOGE("RDB rdb_add_path failed with: %d", ret);
                        return ret;
                }
 
-               /*read all apps with appsetting privilege*/
-               ret = get_all_appsetting_ids(&app_ids, &app_ids_cnt);
+               return PC_OPERATION_SUCCESS;
+       }
+
+       case PERM_APP_PATH_NPRUNTIME: {
+               C_LOGD("app_path_type is PERM_APP_PATH_NPRUNTIME.");
+               char label[SMACK_LABEL_LEN + 1];
+               int ret;
+
+               // Create label:
+               if ((strlen(pkg_id) + strlen(".npruntime")) > SMACK_LABEL_LEN) {
+                       C_LOGE("cannot create npruntime label, pkg_id is too long.");
+                       return PC_ERR_INVALID_PARAM;
+               }
+               ret = sprintf(label, "%s.npruntime", pkg_id);
+               if (ret <= 0) {
+                       C_LOGE("creating npruntime label failed.");
+                       return PC_ERR_INVALID_OPERATION;
+               }
+               C_LOGD("Generated npruntime label '%s' for path %s", label, path);
+
+               // Label executable/symlink
+               ret = set_exec_label(label, path);
                if (ret != PC_OPERATION_SUCCESS) {
-                       C_LOGE("Appsetting: get_all_appsetting_ids failed");
+                       C_LOGE("cannot set executable label '%s' for path %s.", label, path);
                        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 the path to the database:
+               ret = rdb_add_path(pkg_id, label, path, "rw", "rxat", "NPRUNTIME_PATH");
+               if (ret != PC_OPERATION_SUCCESS) {
+                       C_LOGE("RDB rdb_add_path failed with: %d", ret);
+                       return ret;
                }
 
                return PC_OPERATION_SUCCESS;
@@ -2097,31 +1338,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
@@ -2136,63 +1361,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));
+       ret = perm_begin();
+       if(ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB perm_begin failed with: %d", ret);
                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));
-               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;
 }
 
@@ -2206,9 +1397,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;
@@ -2218,108 +1406,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 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 (subject == NULL ||
-               object == NULL ||
-               access == NULL ||
-               strtok_r(NULL, " \t\n", &saveptr) != NULL ||
-               !smack_label_is_valid(subject) ||
-               !smack_label_is_valid(object))
-       {
-               C_LOGE("Incorrect rule format: %s", rule);
-               return PC_ERR_INVALID_PARAM;
-       }
-
-       if (smack_accesses_add_modify(accesses, subject, object, access, "")) {
-               C_LOGE("smack_accesses_add_modify 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;
@@ -2369,24 +1467,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
@@ -2396,22 +1497,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
@@ -2420,15 +1506,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 both files in case of failure
+       // 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;
+       }
+
+       // 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;
@@ -2437,58 +1533,30 @@ 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;
+       C_LOGE("app_register_av is deprecated and unimplemented!");
 
-       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;
-       }
+       // TODO: This function is not implemented with RDB.
+       return PC_ERR_INVALID_OPERATION;
+}
 
-       // 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;
+API int perm_add_additional_rules(const char** smack_rules){
+       SECURE_C_LOGD("Entering function: %s.", __func__);
+       int ret;
+       if (!smack_rules){
+               C_LOGE("smack_rules is NULL");
+               return PC_ERR_INVALID_PARAM;
        }
 
-       // Add permisions from OSP_antivirus.dac file
-       ret = perm_to_dac(app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
+       ret = rdb_add_additional_rules(smack_rules);
        if (ret != PC_OPERATION_SUCCESS) {
-               C_LOGE("perm_to_dac failed");
+               C_LOGE("RDB rdb_add_additional_rules failed with: %d", ret);
                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;
-       }
-
-       return ret;
+       return PC_OPERATION_SUCCESS;
 }
diff --git a/src/rules-db-internals.c b/src/rules-db-internals.c
new file mode 100644 (file)
index 0000000..b7113c0
--- /dev/null
@@ -0,0 +1,1249 @@
+/*
+ * 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
+
+/**
+ * Reset and unbind statement. Used in functions that use bindings.
+ * @param  p_stmt SQLite3 statement
+ * @return        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+static int reset_and_unbind_stmt(sqlite3_stmt *p_stmt)
+{
+       if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
+               C_LOGE("RDB: Error unbinding statement: %s",
+                      sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
+               return PC_ERR_DB_QUERY_STEP;
+       }
+
+       if(sqlite3_reset(p_stmt) != SQLITE_OK) {
+               C_LOGE("RDB: Error reseting statement: %s",
+                      sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
+               return PC_ERR_DB_QUERY_STEP;
+       }
+       return PC_OPERATION_SUCCESS;
+}
+
+
+
+/**
+ * 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;
+}
+
+
+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 OR IGNORE 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;
+}
+
+
+int add_modified_apps_path_internal(sqlite3 *p_db,
+                                   const char *const s_app_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) \
+                           SELECT path_view.path_label_name           \
+                           FROM   path_view                           \
+                           WHERE  path_view.owner_app_label_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;
+}
+
+/**
+ * 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,
+                       "PRAGMA foreign_keys = ON;                                 \
+                       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;",
+                       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 1                      \
+                           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) {
+               // There is such application label
+               ret = PC_ERR_DB_LABEL_TAKEN;
+       } if(ret == SQLITE_DONE) {
+               // No such application label
+               ret = PC_OPERATION_SUCCESS;
+       } 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_access_reverse,
+                     const char *const s_type)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s %s %s %s %s",
+                           s_owner_label_name, s_path_label_name,
+                           s_path, s_access, s_access_reverse, 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,               \
+                                                 access_reverse,       \
+                                                 path_type_name)       \
+                            VALUES(%Q, %Q, %Q, %Q, %Q, %Q);",
+                          s_owner_label_name, s_path, s_path_label_name,
+                          s_access, s_access_reverse, 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 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 prepare_stmts_for_bind(sqlite3 *p_db,
+                          sqlite3_stmt **pp_stmt,
+                          const char *const s_query)
+{
+       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));
+               return PC_ERR_DB_QUERY_PREP;
+       }
+       return PC_OPERATION_SUCCESS;
+}
+
+
+static int add_permission_label_rule(sqlite3_stmt *p_stmt,
+                                    const sqlite3_int64 i_permission_id,
+                                    const char *const s_label_name,
+                                    const char *const s_access,
+                                    const int i_is_reverse)
+{
+       int ret = PC_OPERATION_SUCCESS;
+
+       // Bind values to the statement and run it:
+       // Bind returns SQLITE_OK == 0 on success
+       if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
+           sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
+           sqlite3_bind_text(p_stmt, 3, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
+           sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
+               C_LOGE("RDB: Error during binding to statement: %s",
+                      sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
+               ret = PC_ERR_DB_QUERY_BIND;
+               goto finish;
+       }
+
+       // Perform the insert
+       ret = step_and_convert_returned_value(p_stmt);
+
+finish:
+       reset_and_unbind_stmt(p_stmt);
+       return ret;
+}
+
+
+static int add_permission_permission_rule(sqlite3_stmt *p_stmt,
+               const sqlite3_int64 i_permission_id,
+               const sqlite3_int64 i_target_permission_id,
+               const char *const s_access,
+               const int i_is_reverse)
+{
+       int ret = PC_OPERATION_SUCCESS;
+
+       if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
+           sqlite3_bind_int(p_stmt, 2, i_target_permission_id)  ||
+           sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
+           sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
+               C_LOGE("RDB: Error during binding to statement: %s",
+                      sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
+               ret = PC_ERR_DB_QUERY_BIND;
+               goto finish;
+       }
+
+       ret = step_and_convert_returned_value(p_stmt);
+
+finish:
+       reset_and_unbind_stmt(p_stmt);
+       return ret;
+}
+
+
+static int add_permission_app_path_type_rule(sqlite3_stmt *p_stmt,
+               const sqlite3_int64 i_permission_id,
+               const char *const s_path_type_name,
+               const char *const s_access,
+               const int i_is_reverse)
+{
+       int ret = PC_OPERATION_SUCCESS;
+
+       if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
+           sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0)  ||
+           sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
+           sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
+               C_LOGE("RDB: Error during binding to statement: %s",
+                      sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
+               ret = PC_ERR_DB_QUERY_BIND;
+               goto finish;
+       }
+
+       ret = step_and_convert_returned_value(p_stmt);
+
+finish:
+       reset_and_unbind_stmt(p_stmt);
+       return ret;
+}
+
+int add_permission_rules_internal(sqlite3 *p_db,
+                                 const sqlite3_int64 i_permission_id,
+                                 const char *const *const pp_smack_rules)
+{
+       RDB_LOG_ENTRY;
+
+       int ret = PC_OPERATION_SUCCESS;
+       char s_label[SMACK_LABEL_LEN + 1];
+       char s_access[ACC_LEN + 1];
+       sqlite3_int64 i_all_apps_permission_id = 1;
+       int i_is_reverse = 0;
+       int i;
+       sqlite3_stmt *p_perm_to_label_stmt = NULL;
+       sqlite3_stmt *p_perm_to_perm_stmt = NULL;
+       sqlite3_stmt *p_perm_to_app_path_type_stmt = NULL;
+
+       // Prepare stmts. They are static, so we parse SQL only once per process and reuse it.
+       ret = prepare_stmts_for_bind(p_db, &p_perm_to_label_stmt,
+                                    "INSERT INTO permission_label_rule_view(        \
+                                     permission_id, access, label_name, is_reverse) \
+                                     VALUES(?,?,?,?)");
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = prepare_stmts_for_bind(p_db, &p_perm_to_perm_stmt,
+                                    "INSERT OR REPLACE INTO permission_permission_rule( \
+                                     permission_id, target_permission_id,               \
+                                     access, is_reverse)                                \
+                                     VALUES(?,?,str_to_access(?),?)");
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+
+       ret = prepare_stmts_for_bind(p_db, &p_perm_to_app_path_type_stmt,
+                                    "INSERT INTO permission_app_path_type_rule_view(        \
+                                     permission_id, app_path_type_name, access, is_reverse) \
+                                     VALUES(?,?,?,?)");
+       if(ret != PC_OPERATION_SUCCESS) 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_label, s_access, &i_is_reverse);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               // Interpret wildcards
+               if(s_label[0] != '~' &&
+                   s_label[strlen(s_label) - 1] != '~') {
+                       // It's not a wildcard!
+                       ret = add_permission_label_rule(p_perm_to_label_stmt,
+                                                       i_permission_id,
+                                                       s_label,
+                                                       s_access,
+                                                       i_is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               } else if(!strcmp(s_label, "~ALL_APPS~")) {
+                       ret = get_permission_id_internal(p_db,
+                                                        "ALL_APPS",
+                                                        "ALL_APPS",
+                                                        &i_all_apps_permission_id);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+                       ret = add_permission_permission_rule(p_perm_to_perm_stmt,
+                                                            i_permission_id,
+                                                            i_all_apps_permission_id,
+                                                            s_access,
+                                                            i_is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               } else if(!strcmp(s_label, "~ALL_APPS_WITH_SAME_PERMISSION~")) {
+                       ret = add_permission_permission_rule(p_perm_to_perm_stmt,
+                                                            i_permission_id,
+                                                            i_permission_id,
+                                                            s_access,
+                                                            i_is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               } else if(!strcmp(s_label, "~PUBLIC_PATH~")) {
+                       ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
+                                                               i_permission_id,
+                                                               "PUBLIC_PATH",
+                                                               s_access,
+                                                               i_is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               } else if(!strcmp(s_label, "~GROUP_PATH~")) {
+                       ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
+                                                               i_permission_id,
+                                                               "GROUP_PATH",
+                                                               s_access,
+                                                               i_is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               } else if(!strcmp(s_label, "~SETTINGS_PATH~")) {
+                       ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
+                                                               i_permission_id,
+                                                               "SETTINGS_PATH",
+                                                               s_access,
+                                                               i_is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+               }
+       }
+
+       ret = PC_OPERATION_SUCCESS;
+
+finish:
+       if(p_perm_to_label_stmt &&
+           sqlite3_finalize(p_perm_to_label_stmt) < 0) {
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       }
+
+       if(p_perm_to_perm_stmt &&
+           sqlite3_finalize(p_perm_to_perm_stmt) < 0) {
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       }
+
+       if(p_perm_to_app_path_type_stmt &&
+           sqlite3_finalize(p_perm_to_app_path_type_stmt) < 0) {
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       }
+       return ret;
+}
+
+static int add_label_app_path_type_rule(sqlite3_stmt *p_stmt,
+                                       const char *const s_label_name,
+                                       const char *const s_path_type_name,
+                                       const char *const s_access,
+                                       const int i_is_reverse)
+{
+       int ret = PC_OPERATION_SUCCESS;
+
+       if(sqlite3_bind_text(p_stmt, 1, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
+           sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0)  ||
+           sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
+           sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
+               C_LOGE("RDB: Error during binding to statement: %s",
+                      sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
+               ret = PC_ERR_DB_QUERY_BIND;
+               goto finish;
+       }
+
+       ret = step_and_convert_returned_value(p_stmt);
+
+finish:
+       reset_and_unbind_stmt(p_stmt);
+       return ret;
+}
+
+
+int add_additional_rules_internal(sqlite3 *p_db, const char *const *const pp_smack_rules)
+{
+       RDB_LOG_ENTRY;
+       int ret = PC_OPERATION_SUCCESS;
+       size_t i;
+       char s_subject[SMACK_LABEL_LEN + 1];
+       char s_object[SMACK_LABEL_LEN + 1];
+       char s_access[ACC_LEN + 1];
+       sqlite3_stmt *p_label_to_app_path_type_stmt = NULL;
+       int is_reverse = 0;
+       char *ps_subject, *ps_object;
+
+       // Clear the label_app_path_type_rule table
+       if(sqlite3_exec(p_db, "DELETE FROM label_app_path_type_rule_view;", 0, 0, 0) != SQLITE_OK) {
+               C_LOGE("RDB: Error during clearing additional rules: %s", sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_OPERATION;
+               goto finish;
+       }
+
+       ret = prepare_stmts_for_bind(p_db, &p_label_to_app_path_type_stmt,
+                                    "INSERT INTO label_app_path_type_rule_view(          \
+                                     label_name, app_path_type_name, access, is_reverse) \
+                                     VALUES(?,?,?,?)");
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       // Add rules to the database
+       for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
+
+               // Ignore empty lines
+               if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
+                       continue;
+
+               // Tokenize
+               ret = tokenize_rule(pp_smack_rules[i], s_subject , s_object, s_access);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               if(is_wildcard(s_subject)) {
+                       ps_subject = s_object;
+                       ps_object = s_subject;
+                       is_reverse = 1;
+               } else {
+                       ps_subject = s_subject;
+                       ps_object = s_object;
+                       is_reverse = 0;
+               }
+
+               // Check validity
+               if(!smack_label_is_valid(ps_subject)) {
+                       C_LOGE("Subject is not a valid label");
+                       ret = PC_ERR_INVALID_PARAM;
+                       goto finish;
+               }
+
+               // Add access to paths
+               if(!strcmp(ps_object, "~PUBLIC_PATH~")) {
+                       ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
+                                                          ps_subject,
+                                                          "PUBLIC_PATH",
+                                                          s_access,
+                                                          is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               } else if(!strcmp(ps_object, "~GROUP_PATH~")) {
+                       ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
+                                                          ps_subject,
+                                                          "GROUP_PATH",
+                                                          s_access,
+                                                          is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               } else if(!strcmp(ps_object, "~SETTINGS_PATH~")) {
+                       ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
+                                                          ps_subject,
+                                                          "SETTINGS_PATH",
+                                                          s_access,
+                                                          is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+               } else if(!strcmp(ps_object, "~NPRUNTIME_PATH~")) {
+                       ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
+                                                          ps_subject,
+                                                          "NPRUNTIME_PATH",
+                                                          s_access,
+                                                          is_reverse);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+               }
+
+
+               // Mark label as modified
+               ret = add_modified_label_internal(p_db, ps_subject);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+       }
+
+finish:
+       if(p_label_to_app_path_type_stmt &&
+           sqlite3_finalize(p_label_to_app_path_type_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 %s %s %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;                     \
+                                                                            \
+                       INSERT INTO history_smack_rule                       \
+                       SELECT subject, object, access                       \
+                       FROM all_smack_binary_rules;                         \
+                                                                            \
+                       CREATE INDEX history_smack_rule_subject_object_index \
+                       ON history_smack_rule(subject, object);",
+                       0, 0, 0) != SQLITE_OK) {
+               C_LOGE("RDB: Error during saving history table: %s",
+                      sqlite3_errmsg(p_db));
+               return PC_ERR_DB_OPERATION;
+       }
+
+       return PC_OPERATION_SUCCESS;
+}
+
+
+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;
+
+       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;
+}
diff --git a/src/rules-db.c b/src/rules-db.c
new file mode 100644 (file)
index 0000000..bdd3d77
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * 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 <stdlib.h>
+
+#include "privilege-control.h"
+#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;
+       }
+
+       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(ret == PC_OPERATION_SUCCESS &&
+           (ret = update_rules_in_db(p_db))
+           != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB: Error during updating rules in the database: %d", ret);;
+       }
+
+       if(have_smack()) {
+               if(ret == PC_OPERATION_SUCCESS &&
+                   (ret = update_smack_rules(p_db))
+                   != PC_OPERATION_SUCCESS) {
+                       C_LOGE("RDB: Error updating smack rules: %d", ret);
+               }
+       }
+
+       // 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. Error: %s", sqlite3_errmsg(p_db));
+       }
+}
+
+
+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);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_modified_apps_path_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_access_reverse,
+                const char *const s_type)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s %s %s %s %s",
+                           s_owner_label_name, s_path_label_name,
+                           s_path, s_access, s_access_reverse, 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_access_reverse,
+                               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 app_type_t i_permission_type,
+                              const char *const *const pp_permissions_list,
+                              const bool   b_is_volatile)
+{
+       RDB_LOG_ENTRY_PARAM("%s %d %d", s_app_label_name, i_permission_type,(int)b_is_volatile);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+       char *s_permission_name = NULL;
+       int i;
+       int i_app_id = 0;
+
+       const char* s_permission_type_name = app_type_name(i_permission_type);
+       const char* s_permission_group_type_name = app_type_group_name(i_permission_type);
+
+       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 = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               ret = change_app_permission_internal(p_db,
+                                                    i_app_id,
+                                                    s_permission_name,
+                                                    s_permission_group_type_name,
+                                                    b_is_volatile,
+                                                    RDB_ENABLE);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+               free(s_permission_name);
+       }
+
+       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 app_type_t i_permission_type,
+                               const char *const *const pp_permissions_list)
+{
+       RDB_LOG_ENTRY_PARAM("%s %d", s_app_label_name, i_permission_type);
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+       char *s_permission_name = NULL;
+       int i, i_app_id;
+       const char* s_permission_group_type_name = app_type_group_name(i_permission_type);
+
+       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 = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               ret = switch_app_permission_internal(p_db,
+                                                    i_app_id,
+                                                    s_permission_name,
+                                                    s_permission_group_type_name,
+                                                    RDB_DISABLE);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               free(s_permission_name);
+       }
+
+       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);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_modified_apps_path_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 rdb_add_additional_rules(const char *const *const pp_smack_rules)
+{
+       RDB_LOG_ENTRY;
+
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = add_additional_rules_internal(p_db,
+                                           pp_smack_rules);
+
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
+}