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")
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}")
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")
${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)
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)
# 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
#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
${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
--- /dev/null
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+* @file api_feature_loader.c
+* @author Jan Olszak (j.olszak@samsung.com)
+* @version 1.0
+* @brief Binary file for loading predefined API features to the database.
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h> // For file manipulation
+#include <stdlib.h> // For malloc and free
+#include <dirent.h> // For iterating directories
+#include <obstack.h> // For obstack implementation
+#include <privilege-control.h> // For app_type
+#include <sys/smack.h> // For SMACK_LABEL_LEN
+#include <getopt.h> // For getopt
+
+
+#define API_FEATURE_LOADER_VERSION "1.0"
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+#define vector_init(V) obstack_init(&(V))
+#define vector_push_back_ptr(V, I) obstack_ptr_grow(&(V), (I))
+#define vector_finish(V) obstack_finish(&(V))
+#define vector_free(V) obstack_free(&(V), NULL)
+
+#define ACC_LEN 6
+
+#define API_FEATURES_DIR "/usr/share/privilege-control/"
+
+#define API_FEATURE_LOADER_LOG(format, ...) if(i_verbose_flag__) printf(format, ##__VA_ARGS__)
+
+typedef struct obstack vector_t;
+static int i_verbose_flag__ = 0;
+static const size_t ui_smack_ext_len__ = 6; // = strlen(".smack");
+
+bool has_prefix(const char *const s_str, const char *const s_prefix)
+{
+ return !strncmp(s_str, s_prefix, strlen(s_prefix));
+}
+
+bool has_smack_ext(const char *const s_str)
+{
+ return strlen(s_str) > ui_smack_ext_len__ &&
+ !strncmp(&s_str[strlen(s_str) - ui_smack_ext_len__], ".smack", ui_smack_ext_len__);
+}
+
+int wrt_filter(const struct dirent *entry)
+{
+ return !strcmp(entry->d_name, "WRT.smack");
+}
+
+int wrt_partner_filter(const struct dirent *entry)
+{
+ return !strcmp(entry->d_name, "WRT_partner.smack");
+}
+
+int wrt_platform_filter(const struct dirent *entry)
+{
+ return !strcmp(entry->d_name, "WRT_platform.smack");
+}
+
+int wrt_family_filter(const struct dirent *entry)
+{
+ return has_prefix(entry->d_name, "WRT_") &&
+ !has_prefix(entry->d_name, "WRT_partner") &&
+ !has_prefix(entry->d_name, "WRT_platform") &&
+ has_smack_ext(entry->d_name);
+}
+
+int osp_filter(const struct dirent *entry)
+{
+ return !strcmp(entry->d_name, "OSP.smack");
+}
+
+int osp_partner_filter(const struct dirent *entry)
+{
+ return !strcmp(entry->d_name, "OSP_partner.smack");
+}
+
+int osp_platform_filter(const struct dirent *entry)
+{
+ return !strcmp(entry->d_name, "OSP_platform.smack");
+}
+
+int osp_family_filter(const struct dirent *entry)
+{
+ return has_prefix(entry->d_name, "OSP_") &&
+ !has_prefix(entry->d_name, "OSP_partner") &&
+ !has_prefix(entry->d_name, "OSP_platform") &&
+ has_smack_ext(entry->d_name);
+}
+
+int efl_filter(const struct dirent *entry)
+{
+ return !strcmp(entry->d_name, "EFL.smack");
+}
+
+int efl_family_filter(const struct dirent *entry)
+{
+ return has_prefix(entry->d_name, "EFL_") &&
+ has_smack_ext(entry->d_name);
+}
+
+void load_rules_from_file(const char *s_rules_file_path,
+ const char *s_permission_name,
+ const app_type_t app_type)
+{
+ FILE *p_file = NULL;
+ char *s_rule = NULL;
+ char **rules_array = NULL;
+ size_t i_num_rules = 0;
+ size_t i = 0;
+ int ret;
+ vector_t rules_vector;
+
+ p_file = fopen(s_rules_file_path, "r");
+ if(!p_file) goto finish;
+
+ API_FEATURE_LOADER_LOG("Loading permission: %s \n", s_permission_name);
+
+ vector_init(rules_vector);
+ while(getline(&s_rule, &i, p_file) > 0) {
+ vector_push_back_ptr(rules_vector, s_rule);
+ ++i_num_rules;
+ s_rule = NULL;
+ }
+ vector_push_back_ptr(rules_vector, NULL);
+
+ rules_array = vector_finish(rules_vector);
+
+ ret = perm_add_api_feature(app_type,
+ s_permission_name,
+ (const char **)rules_array,
+ NULL,
+ i_num_rules);
+ if(ret != PC_OPERATION_SUCCESS)
+ API_FEATURE_LOADER_LOG("Error %d\n", ret);
+
+finish:
+ if(p_file != NULL) fclose(p_file);
+ if(rules_array != NULL) {
+ for(i = 0; i < i_num_rules; ++i) {
+ free(rules_array[i]);
+ }
+ vector_free(rules_vector);
+ }
+}
+
+void load_permission_family(int (*filter)(const struct dirent *),
+ int i_prefix_len,
+ const app_type_t app_type,
+ const char const *s_dir)
+{
+ int i, num_files = 0;
+ struct dirent **file_list = NULL;
+ char *s_path = NULL;
+ char *s_permission_name = NULL;
+ int i_perm_name_len;
+
+ num_files = scandir(s_dir, &file_list, filter, alphasort);
+ for(i = 0; i < num_files; ++i) {
+ if(asprintf(&s_path, "%s%s", s_dir, file_list[i]->d_name) <= 0) continue;
+
+ i_perm_name_len = strlen(file_list[i]->d_name);
+ s_permission_name = (char *) malloc(i_perm_name_len);
+ if(!s_permission_name) {
+ API_FEATURE_LOADER_LOG("Error during allocating memory.\n");
+ return;
+ }
+ strncpy(s_permission_name,
+ &(file_list[i]->d_name[i_prefix_len]),
+ i_perm_name_len - i_prefix_len - ui_smack_ext_len__);
+ s_permission_name[i_perm_name_len - i_prefix_len - ui_smack_ext_len__ ] = '\0';
+ load_rules_from_file(s_path, s_permission_name, app_type);
+
+ free(file_list[i]);
+ free(s_path);
+ free(s_permission_name);
+ s_path = NULL;
+ s_permission_name = NULL;
+ }
+ free(file_list);
+}
+
+void load_pemission_type_rules(int (*filter)(const struct dirent *),
+ const char const *s_permission_name,
+ const app_type_t app_type,
+ const char const *s_dir)
+{
+ char *s_path = NULL;
+ struct dirent **file_list = NULL;
+ int i, num_files;
+
+ num_files = scandir(s_dir, &file_list, filter, alphasort);
+ for(i = 0; i < num_files; ++i) {
+ if(asprintf(&s_path, "%s%s", API_FEATURES_DIR, file_list[i]->d_name) <= 0) continue;
+
+ load_rules_from_file(s_path, s_permission_name, app_type);
+
+ if(file_list[i]) free(file_list[i]);
+ if(s_path) free(s_path);
+ s_path = NULL;
+ }
+ free(file_list);
+}
+
+
+void load_from_dir(const char *const s_dir)
+{
+
+ API_FEATURE_LOADER_LOG("Loading rules from directory...\n");
+ if(perm_modification_start()) return;
+
+ // Load rules specific to permission's types:
+ load_pemission_type_rules(wrt_filter, "WRT", APP_TYPE_WGT, s_dir);
+ load_pemission_type_rules(wrt_partner_filter, "WRT_partner", APP_TYPE_WGT_PARTNER, s_dir);
+ load_pemission_type_rules(wrt_platform_filter, "WRT_platform", APP_TYPE_WGT_PLATFORM, s_dir);
+ load_pemission_type_rules(osp_filter, "OSP", APP_TYPE_OSP, s_dir);
+ load_pemission_type_rules(osp_partner_filter, "OSP_partner" , APP_TYPE_OSP_PARTNER, s_dir);
+ load_pemission_type_rules(osp_platform_filter, "OSP_platform", APP_TYPE_OSP_PLATFORM, s_dir);
+ load_pemission_type_rules(efl_filter, "EFL", APP_TYPE_EFL, s_dir);
+
+ // Load rules for each permission type:
+ load_permission_family(wrt_family_filter, strlen("WRT_"), APP_TYPE_WGT, s_dir);
+ load_permission_family(osp_family_filter, strlen("OSP_"), APP_TYPE_OSP, s_dir);
+ load_permission_family(efl_family_filter, strlen("EFL_"), APP_TYPE_EFL, s_dir);
+
+ perm_modification_finish();
+ API_FEATURE_LOADER_LOG("Done.\n");
+
+}
+
+int main(int argc, char *argv[])
+{
+ int c;
+ int i_option_index = 0;
+
+ bool b_load_from_file = false;
+ const char *s_file;
+
+ bool b_load_from_dir = false;
+ const char *s_dir;
+
+ static struct option long_options[] = {
+ {"verbose", no_argument, &i_verbose_flag__, 1},
+ {"file", required_argument, 0, 'f'},
+ {"dir", required_argument, 0, 'd'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+ while((c = getopt_long(argc, argv,
+ "f:d:hav",
+ long_options,
+ &i_option_index)) != -1) {
+ switch(c) {
+ case 0:
+ // If this option set a flag, do nothing.
+ break;
+ case '?':
+ // No such command.
+ // getopt_long already printed an error message.
+ return 0;
+ case 'f':
+ b_load_from_file = true;
+ s_file = optarg;
+ break;
+
+ case 'd':
+ b_load_from_dir = false;
+ s_dir = optarg;
+ break;
+
+ case 'h':
+ printf("Api feature loader v." API_FEATURE_LOADER_VERSION "\n\n");
+ printf(" Options:\n");
+ printf(" -d,--dir=path load api-features from the directory\n");
+ printf(" -f,--file=file_name load api-feature from the file\n");
+ printf(" -h,--help print this help\n");
+ printf(" --verbose verbose output\n");
+ printf(" -v,--version show applcation version\n");
+
+ return 0;
+
+ case 'v':
+ printf("Api feature loader v." API_FEATURE_LOADER_VERSION "\n");
+ return 0;
+
+ default:
+ break;
+ }
+ }
+
+ // Print unknown remaining command line arguments
+ if(optind < argc) {
+ printf("Unknown options: ");
+ while(optind < argc)
+ printf("%s ", argv[optind++]);
+ putchar('\n');
+ return 0;
+ }
+
+
+ if(b_load_from_dir) load_from_dir(s_dir);
+
+ if(b_load_from_file) {
+ // TODO: Call the function that loads the permission from a file.
+ }
+
+ // By default we load from API_FEATURES_DIR
+ load_from_dir(API_FEATURES_DIR);
+
+ return 0;
+
+}
+
+
--- /dev/null
+.load librules-db-sql-udf.so
+.separator " "
+
+PRAGMA journal_mode = DELETE;
+
+.output "/opt/etc/smack/boot-rules.smack"
+
+SELECT subject, object, access_to_str(access)
+FROM all_smack_binary_rules
+WHERE all_smack_binary_rules.is_volatile = 0;
+
--- /dev/null
+-- !!! CAUTION !!!
+-- Beware of updating!
+-- Remember that you might insert things to a filled database.
+
+
+.load librules-db-sql-udf.so
+PRAGMA foreign_keys = ON;
+
+BEGIN TRANSACTION;
+
+-- PERMISSION TYPES --------------------------------------------------------------------------------
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("ALL_APPS"); -- Automatically added to all apps.
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("WRT");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("OSP");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("EFL");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("WRT_partner");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("WRT_platform");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("OSP_partner");
+INSERT OR IGNORE INTO permission_type(type_name) VALUES("OSP_platform");
+
+-- APP PATH TYPES ----------------------------------------------------------------------------------
+INSERT OR IGNORE INTO app_path_type(name) VALUES("PRIVATE");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("GROUP_RW");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("PUBLIC_RO");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("SETTINGS_RW");
+INSERT OR IGNORE INTO app_path_type(name) VALUES("ANY_LABEL");
+
+INSERT OR IGNORE INTO permission_view(name, type_name) VALUES
+ ("ALL_APPS", "ALL_APPS"),
+ ("WRT", "WRT"),
+ ("WRT_partner", "WRT_partner"),
+ ("WRT_platform","WRT_platform"),
+ ("OSP", "OSP"),
+ ("OSP_partner", "OSP_partner"),
+ ("OSP_platform","OSP_platform"),
+ ("EFL", "EFL");
+
+-- PUBLIC FOLDERS ----------------------------------------------------------------------------------
+-- PUBLIC_RO
+INSERT OR IGNORE INTO permission_app_path_type_rule_view(permission_name,
+ permission_type_name,
+ app_path_type_name,
+ access,
+ is_reverse) VALUES
+ ("ALL_APPS", "ALL_APPS", "PUBLIC_RO", "rx", 0);
+
+
+-- SETTINGS ----------------------------------------------------------------------------------------
+-- Permission name == TIZEN_PRIVILEGE_APPSETTING
+-- SETTINGS_RW
+INSERT OR IGNORE INTO permission_view(name, type_name) VALUES
+ ("org.tizen.privilege.appsetting", "WRT"),
+ ("org.tizen.privilege.appsetting", "OSP"),
+ ("org.tizen.privilege.appsetting", "EFL");
+
+INSERT OR IGNORE INTO permission_app_path_type_rule_view(permission_name,
+ permission_type_name,
+ app_path_type_name,
+ access,
+ is_reverse) VALUES
+ ("org.tizen.privilege.appsetting","WRT", "SETTINGS_RW", "rwx", 0),
+ ("org.tizen.privilege.appsetting","OSP", "SETTINGS_RW", "rwx", 0),
+ ("org.tizen.privilege.appsetting","EFL", "SETTINGS_RW", "rwx", 0);
+
+INSERT OR IGNORE INTO permission_permission_rule_view(permission_name,
+ permission_type_name,
+ target_permission_name,
+ target_permission_type_name,
+ access,
+ is_reverse) VALUES
+ ("org.tizen.privilege.appsetting","WRT", "ALL_APPS", "ALL_APPS", "rx", 0),
+ ("org.tizen.privilege.appsetting","OSP", "ALL_APPS", "ALL_APPS", "rx", 0),
+ ("org.tizen.privilege.appsetting","EFL", "ALL_APPS", "ALL_APPS", "rx", 0);
+
+
+-- ANTIVIRUS ---------------------------------------------------------------------------------------
+-- Permission name == TIZEN_PRIVILEGE_ANTIVIRUS
+INSERT OR IGNORE INTO permission_view(name, type_name) VALUES
+ ("org.tizen.privilege.antivirus", "WRT"),
+ ("org.tizen.privilege.antivirus", "OSP"),
+ ("org.tizen.privilege.antivirus", "EFL");
+
+INSERT OR IGNORE INTO permission_permission_rule_view(permission_name,
+ permission_type_name,
+ target_permission_name,
+ target_permission_type_name,
+ access,
+ is_reverse) VALUES
+ ("org.tizen.privilege.antivirus","WRT", "ALL_APPS", "ALL_APPS", "rwx", 0),
+ ("org.tizen.privilege.antivirus","OSP", "ALL_APPS", "ALL_APPS", "rwx", 0),
+ ("org.tizen.privilege.antivirus","EFL", "ALL_APPS", "ALL_APPS", "rwx", 0);
+
+INSERT OR IGNORE INTO permission_app_path_type_rule_view(permission_name,
+ permission_type_name,
+ app_path_type_name,
+ access,
+ is_reverse) VALUES
+ ("org.tizen.privilege.antivirus","WRT", "GROUP_RW", "rwx", 0),
+ ("org.tizen.privilege.antivirus","OSP", "GROUP_RW", "rwx", 0),
+ ("org.tizen.privilege.antivirus","EFL", "GROUP_RW", "rwx", 0),
+ ("org.tizen.privilege.antivirus","WRT", "SETTINGS_RW", "rwx", 0),
+ ("org.tizen.privilege.antivirus","OSP", "SETTINGS_RW", "rwx", 0),
+ ("org.tizen.privilege.antivirus","EFL", "SETTINGS_RW", "rwx", 0),
+ ("org.tizen.privilege.antivirus","WRT", "PUBLIC_RO", "rwx", 0),
+ ("org.tizen.privilege.antivirus","OSP", "PUBLIC_RO", "rwx", 0),
+ ("org.tizen.privilege.antivirus","EFL", "PUBLIC_RO", "rwx", 0),
+ ("org.tizen.privilege.antivirus","WRT", "ANY_LABEL", "rwx", 0),
+ ("org.tizen.privilege.antivirus","OSP", "ANY_LABEL", "rwx", 0),
+ ("org.tizen.privilege.antivirus","EFL", "ANY_LABEL", "rwx", 0);
+
+
+-- Initial fill of all_smack_binary_rules table
+DELETE FROM all_smack_binary_rules;
+INSERT INTO all_smack_binary_rules
+SELECT subject, object, access, is_volatile
+FROM all_smack_binary_rules_view;
+
+COMMIT TRANSACTION;
\ No newline at end of file
--- /dev/null
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+* @file rules-db-sql-udf.c
+* @author Jan Olszak (j.olszak@samsung.com)
+* @version 1.0
+* @brief This file contains implementation of a SQLite module used in rules-db.
+*/
+
+#include <sqlite3ext.h>
+
+#define UNUSED __attribute__((unused))
+
+// Access rights:
+#define RDB_ACCESS_READ 1
+#define RDB_ACCESS_WRITE 2
+#define RDB_ACCESS_EXEC 4
+#define RDB_ACCESS_APPEND 8
+#define RDB_ACCESS_TRANSMUTE 16
+#define RDB_ACCESS_LOCK 32
+#define RDB_ACCESS_FULL (RDB_ACCESS_READ | \
+ RDB_ACCESS_WRITE | \
+ RDB_ACCESS_EXEC | \
+ RDB_ACCESS_APPEND | \
+ RDB_ACCESS_TRANSMUTE | \
+ RDB_ACCESS_LOCK)
+
+
+SQLITE_EXTENSION_INIT1
+
+/**
+* Convert access to a string representation.
+*
+* @ingroup SQLite User Defined Functions
+*
+*/
+static void access_to_str(sqlite3_context *context,
+ int argc UNUSED,
+ sqlite3_value **argv)
+{
+ int access = sqlite3_value_int(argv[0]);
+ int i = 0;
+ char string[7];
+ if (access & RDB_ACCESS_READ)
+ string[i++] = 'r';
+ if (access & RDB_ACCESS_WRITE)
+ string[i++] = 'w';
+ if (access & RDB_ACCESS_EXEC)
+ string[i++] = 'x';
+ if (access & RDB_ACCESS_APPEND)
+ string[i++] = 'a';
+ if (access & RDB_ACCESS_TRANSMUTE)
+ string[i++] = 't';
+ if (access & RDB_ACCESS_LOCK)
+ string[i++] = 'l';
+ string[i] = '\0';
+ sqlite3_result_text(context, string, -1, SQLITE_TRANSIENT);
+}
+
+
+/**
+* Convert a string to access representation.
+* Takes ONE input string like "rwxat" and converts it into access representation.
+* The order of rwxat letters does not matter.
+*
+* @ingroup SQLite User Defined Functions
+*
+*/
+static void str_to_access(sqlite3_context *context,
+ int argc UNUSED,
+ sqlite3_value **argv)
+{
+ const unsigned char *string = sqlite3_value_text(argv[0]);
+ int access = 0;
+ int i;
+
+ if (!string) {
+ sqlite3_result_null(context);
+ return;
+ }
+
+ for (i = 0; string[i] != '\0'; ++i) {
+ switch (string[i]) {
+ case 'R':
+ case 'r': access |= RDB_ACCESS_READ; break;
+
+ case 'W':
+ case 'w': access |= RDB_ACCESS_WRITE; break;
+
+ case 'X':
+ case 'x': access |= RDB_ACCESS_EXEC; break;
+
+ case 'A':
+ case 'a': access |= RDB_ACCESS_APPEND; break;
+
+ case 'T':
+ case 't': access |= RDB_ACCESS_TRANSMUTE; break;
+
+ case 'L':
+ case 'l': access |= RDB_ACCESS_LOCK; break;
+
+ case '-': break;
+
+ default: // He got an unknown permission
+ sqlite3_result_null(context);
+ return;
+ }
+ }
+ sqlite3_result_int(context, access);
+}
+
+
+/**
+* An bitwise or aggregating function. We assume, that all arguments are ints.
+*
+* @ingroup SQLite User Defined Functions
+*
+* @return bitwise or of all given values.
+*/
+static void bitwise_or_step(sqlite3_context *context,
+ int argc UNUSED,
+ sqlite3_value **argv)
+{
+ int *result_buffer = (int *)sqlite3_aggregate_context(context, sizeof(int));
+ *result_buffer |= sqlite3_value_int(argv[0]);
+}
+
+
+void bitwise_or_final(sqlite3_context *context)
+{
+ int *result_buffer = (int *)sqlite3_aggregate_context(context, sizeof(int));
+ sqlite3_result_int(context, *result_buffer );
+}
+
+/**
+* Entry point for SQLite.
+*/
+__attribute__((visibility("default")))
+int sqlite3_extension_init( sqlite3 *p_db,
+ char **ps_err_msg UNUSED,
+ const sqlite3_api_routines *p_api)
+{
+ SQLITE_EXTENSION_INIT2(p_api)
+ sqlite3_create_function(p_db, "access_to_str", 1, SQLITE_ANY, 0, access_to_str, 0, 0);
+ sqlite3_create_function(p_db, "str_to_access", 1, SQLITE_ANY, 0, str_to_access, 0, 0);
+ sqlite3_create_function(p_db, "bitwise_or", 1, SQLITE_ANY, 0, 0,
+ bitwise_or_step, bitwise_or_final);
+
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+-- !!! CAUTION !!!
+-- 1. Beware of updating schema!
+-- We can drop views and triggers,
+-- but we should copy data from tables
+-- according to the schema version!
+-- 2. If you change definition of tables
+-- update the schema counter at the bottom!!
+
+-- TODO: Use "USING" in joins whenever possible
+
+.load librules-db-sql-udf.so
+PRAGMA foreign_keys = ON;
+
+BEGIN EXCLUSIVE TRANSACTION;
+
+-- PRAGMA cache_size = 2000;
+
+CREATE TABLE IF NOT EXISTS app (
+ app_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ label_id INTEGER NOT NULL,
+ UNIQUE(label_id),
+
+ FOREIGN KEY(label_id) REFERENCES label(label_id)
+);
+CREATE INDEX IF NOT EXISTS app_index ON app(app_id, label_id);
+
+
+CREATE TABLE IF NOT EXISTS app_permission (
+ app_id INTEGER NOT NULL,
+ permission_id INTEGER NOT NULL,
+ is_volatile INTEGER NOT NULL DEFAULT 0,
+ is_enabled INTEGER NOT NULL DEFAULT 1,
+
+ PRIMARY KEY(app_id, permission_id),
+
+ FOREIGN KEY(app_id) REFERENCES app(app_id),
+ FOREIGN KEY(permission_id) REFERENCES permission(permission_id)
+);
+
+CREATE TABLE IF NOT EXISTS app_path (
+ app_id INTEGER NOT NULL,
+ path TEXT NOT NULL,
+ label_id INTEGER NOT NULL,
+ access INTEGER NOT NULL,
+ app_path_type_id INTEGER NOT NULL ,
+
+ -- TODO:
+ -- Desired behavior should be:
+ -- allow one app to register a path only once (already implemented by the primary key)
+ -- prohibit two apps registering the same path with different labels (probably cannot be done by SQL constraints)
+ -- allow two apps to register the same path if label is also same
+
+ PRIMARY KEY (app_id, path),
+
+ FOREIGN KEY(app_id) REFERENCES app(app_id),
+ FOREIGN KEY(label_id) REFERENCES label(label_id),
+ FOREIGN KEY(app_path_type_id) REFERENCES app_path_type(app_path_type_id)
+);
+
+CREATE TABLE IF NOT EXISTS app_path_type (
+ app_path_type_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL ,
+
+ UNIQUE (name)
+);
+-- CREATE INDEX IF NOT EXISTS app_path_type_index ON app_path_type(app_path_type_id, name);
+
+
+CREATE TABLE IF NOT EXISTS permission_permission_rule (
+ permission_id INTEGER NOT NULL,
+ target_permission_id INTEGER NOT NULL,
+ access INTEGER NOT NULL DEFAULT 0,
+ is_reverse INTEGER NOT NULL DEFAULT 0,
+
+ PRIMARY KEY (permission_id, target_permission_id, is_reverse),
+
+ FOREIGN KEY(permission_id) REFERENCES permission(permission_id),
+ FOREIGN KEY(target_permission_id) REFERENCES permission(permission_id)
+);
+
+CREATE TABLE IF NOT EXISTS permission_label_rule (
+ permission_id INTEGER NOT NULL,
+ label_id INTEGER NOT NULL,
+ access INTEGER NOT NULL DEFAULT 0,
+ is_reverse INTEGER NOT NULL DEFAULT 0,
+
+ PRIMARY KEY (permission_id,label_id, is_reverse),
+
+ FOREIGN KEY(permission_id) REFERENCES permission(permission_id),
+ FOREIGN KEY(label_id) REFERENCES label(label_id)
+);
+
+CREATE TABLE IF NOT EXISTS permission_app_path_type_rule (
+ permission_id INTEGER NOT NULL,
+ app_path_type_id INTEGER NOT NULL,
+ access INTEGER NOT NULL DEFAULT 0,
+ is_reverse INTEGER NOT NULL DEFAULT 0,
+
+ PRIMARY KEY (permission_id, app_path_type_id, is_reverse),
+
+ FOREIGN KEY(permission_id) REFERENCES permission(permission_id),
+ FOREIGN KEY(app_path_type_id) REFERENCES app_path_type(app_path_type_id)
+);
+
+
+CREATE TABLE IF NOT EXISTS label (
+ label_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ name TEXT NOT NULL,
+
+ UNIQUE(name)
+);
+
+CREATE TABLE IF NOT EXISTS permission_type (
+ permission_type_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ type_name TEXT NOT NULL,
+
+ UNIQUE(type_name)
+);
+
+CREATE TABLE IF NOT EXISTS permission (
+ permission_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT ,
+ permission_type_id INTEGER NOT NULL,
+ name TEXT NOT NULL,
+
+ UNIQUE (name, permission_type_id),
+
+ FOREIGN KEY(permission_type_id) REFERENCES permission_type(permission_type_id)
+);
+
+
+CREATE TABLE IF NOT EXISTS all_smack_binary_rules(
+ subject TEXT NOT NULL,
+ object TEXT NOT NULL,
+ access INTEGER NOT NULL,
+ is_volatile INTEGER NOT NULL
+);
+
+-- TEMPORARY TABLES ------------------------------------------------------------
+-- Definitions are repeated in code.
+
+CREATE TEMPORARY TABLE history_smack_rule(
+ subject TEXT NOT NULL,
+ object TEXT NOT NULL,
+ access INTEGER NOT NULL
+);
+
+
+CREATE TEMPORARY TABLE modified_label(
+ name TEXT NOT NULL,
+ UNIQUE (name)
+);
+
+
+CREATE TEMPORARY TABLE all_smack_binary_rules_modified(
+ subject TEXT NOT NULL,
+ object TEXT NOT NULL,
+ access INTEGER NOT NULL
+);
+
+
+CREATE TEMPORARY TABLE history_smack_rule_modified(
+ subject TEXT NOT NULL,
+ object TEXT NOT NULL,
+ access INTEGER NOT NULL
+);
+
+
+-- PERMISSION VIEW -------------------------------------------------------------
+DROP VIEW IF EXISTS permission_view;
+CREATE VIEW permission_view AS
+SELECT permission.permission_id, permission.name, permission_type.type_name
+FROM permission
+INNER JOIN permission_type
+ON permission.permission_type_id = permission_type.permission_type_id;
+
+DROP TRIGGER IF EXISTS permission_view_insert_trigger;
+CREATE TRIGGER permission_view_insert_trigger
+INSTEAD OF INSERT ON permission_view
+BEGIN
+ INSERT OR IGNORE INTO permission(name,permission_type_id)
+ SELECT NEW.name, permission_type.permission_type_id
+ FROM permission_type
+ WHERE permission_type.type_name = NEW.type_name;
+
+ -- TODO:
+ -- Once the files provide other types of rules,
+ -- this trigger will have to delete also from permission_path_type_rule
+ -- and maybe permission_permission_rule
+ DELETE FROM permission_label_rule_view
+ WHERE permission_label_rule_view.permission_name = NEW.name AND
+ permission_label_rule_view.permission_type_name = NEW.type_name;
+END;
+
+-- PERMISSION TO LABEL RULE VIEW -----------------------------------------------
+DROP VIEW IF EXISTS permission_label_rule_view;
+CREATE VIEW permission_label_rule_view AS
+SELECT
+ permission_view.permission_id AS permission_id,
+ permission_view.name AS permission_name,
+ permission_view.type_name AS permission_type_name,
+ label.name AS label_name,
+ permission_label_rule.access AS access,
+ permission_label_rule.is_reverse AS is_reverse
+FROM permission_label_rule
+LEFT JOIN permission_view
+ON permission_label_rule.permission_id = permission_view.permission_id
+
+LEFT JOIN label
+ON permission_label_rule.label_id = label.label_id;
+
+
+-- Preferred way of adding permission rules would be to use these ONE, multi-row
+-- insert statement, with one check of a condition
+-- that there is such permission id. It's impossible to make those inserts in C,
+-- so the programmer has to secure, that there is a permission with a given id.
+-- (Check it and insert in the same transaction)
+-- In runtime we accept ONLY inserts with label.
+-- All other kinds of permissions are filled during the database creation.
+DROP TRIGGER IF EXISTS permission_label_rule_view_insert_trigger;
+CREATE TRIGGER permission_label_rule_view_insert_trigger
+INSTEAD OF INSERT ON permission_label_rule_view
+BEGIN
+ -- Adding api features adds a label it it's not present.
+ INSERT OR IGNORE INTO label(name) VALUES (NEW.label_name);
+
+ INSERT INTO permission_label_rule(permission_id, label_id, access, is_reverse)
+ SELECT NEW.permission_id,
+ label.label_id,
+ str_to_access(NEW.access),
+ NEW.is_reverse
+ FROM label
+ WHERE label.name = NEW.label_name;
+END;
+
+
+-- TODO: Potential problem - undeleted labels.
+DROP TRIGGER IF EXISTS permission_label_rule_view_delete_trigger;
+CREATE TRIGGER permission_label_rule_view_delete_trigger
+INSTEAD OF DELETE ON permission_label_rule_view
+BEGIN
+ DELETE FROM permission_label_rule
+ WHERE permission_label_rule.permission_id IN (SELECT permission_view.permission_id
+ FROM permission_view
+ WHERE permission_view.name = OLD.permission_name AND
+ permission_view.type_name = OLD.permission_type_name);
+END;
+
+
+-- PERMISSION TO APP PATH TYPE RULE VIEW ---------------------------------------
+DROP VIEW IF EXISTS permission_app_path_type_rule_view;
+CREATE VIEW permission_app_path_type_rule_view AS
+SELECT
+ permission_view.permission_id AS permission_id,
+ permission_view.name AS permission_name,
+ permission_view.type_name AS permission_type_name,
+ app_path_type.name AS app_path_type_name,
+ permission_app_path_type_rule.access AS access,
+ permission_app_path_type_rule.is_reverse AS is_reverse
+FROM permission_app_path_type_rule
+LEFT JOIN permission_view
+ON permission_app_path_type_rule.permission_id = permission_view.permission_id
+LEFT JOIN app_path_type
+ON permission_app_path_type_rule.app_path_type_id = app_path_type.app_path_type_id;
+
+DROP TRIGGER IF EXISTS permission_app_path_type_rule_view_insert_trigger;
+CREATE TRIGGER permission_app_path_type_rule_view_insert_trigger
+INSTEAD OF INSERT
+ON permission_app_path_type_rule_view
+BEGIN
+ INSERT INTO permission_app_path_type_rule(permission_id,
+ app_path_type_id,
+ access,
+ is_reverse)
+ SELECT permission_view.permission_id,
+ app_path_type.app_path_type_id,
+ str_to_access(NEW.access),
+ NEW.is_reverse
+ FROM permission_view, app_path_type
+ WHERE permission_view.name = NEW.permission_name AND
+ permission_view.type_name = NEW.permission_type_name AND
+ app_path_type.name = NEW.app_path_type_name;
+END;
+
+
+-- PERMISSION TO PERMISSION RULE VIEW ------------------------------------------
+DROP VIEW IF EXISTS permission_permission_rule_view;
+CREATE VIEW permission_permission_rule_view AS
+SELECT
+ tmp_permission_view.permission_id AS permission_id,
+ tmp_permission_view.name AS permission_name,
+ tmp_permission_view.type_name AS permission_type_name,
+ tmp_target_permission_view.name AS target_permission_name,
+ tmp_target_permission_view.type_name AS target_permission_type_name,
+ permission_permission_rule.access AS access,
+ permission_permission_rule.is_reverse AS is_reverse
+FROM permission_permission_rule
+LEFT JOIN permission_view AS tmp_permission_view
+ON permission_permission_rule.permission_id = tmp_permission_view.permission_id
+LEFT JOIN permission_view AS tmp_target_permission_view
+ON permission_permission_rule.target_permission_id = tmp_target_permission_view.permission_id;
+
+
+-- Trigger for manual addition of rules.
+DROP TRIGGER IF EXISTS permission_permission_rule_view_insert_trigger;
+CREATE TRIGGER permission_permission_rule_view_insert_trigger
+INSTEAD OF INSERT ON permission_permission_rule_view
+BEGIN
+ INSERT INTO permission_permission_rule(permission_id,
+ target_permission_id,
+ access,
+ is_reverse)
+ SELECT tmp_permission_view.permission_id,
+ tmp_target_permission_view.permission_id,
+ str_to_access(NEW.access),
+ NEW.is_reverse
+ FROM permission_view AS tmp_permission_view,
+ permission_view AS tmp_target_permission_view
+ WHERE tmp_permission_view.name = NEW.permission_name AND
+ tmp_permission_view.type_name = NEW.permission_type_name AND
+ tmp_target_permission_view.name = NEW.target_permission_name AND
+ tmp_target_permission_view.type_name = NEW.target_permission_type_name;
+END;
+
+
+
+-- LABEL VIEW ------------------------------------------------------------------
+-- There are no INSTEAD OF triggers on regular tables.
+-- We use a view to delete unreferenced labels:
+DROP VIEW IF EXISTS label_view;
+CREATE VIEW label_view AS SELECT * FROM label;
+
+DROP TRIGGER IF EXISTS label_view_delete_trigger;
+CREATE TRIGGER label_view_delete_trigger
+INSTEAD OF DELETE ON label_view
+WHEN OLD.label_id NOT IN (SELECT app.label_id
+ FROM app) AND
+ OLD.label_id NOT IN (SELECT permission_label_rule.label_id
+ FROM permission_label_rule) AND
+ OLD.label_id NOT IN (SELECT app_path.label_id
+ FROM app_path)
+BEGIN
+ DELETE FROM label WHERE label.name = OLD.name;
+END;
+
+
+-- APPLICATION VIEW ------------------------------------------------------------
+DROP VIEW IF EXISTS application_view;
+CREATE VIEW application_view AS
+SELECT app.app_id, label.name
+FROM label
+INNER JOIN app
+ON label.label_id = app.label_id ;
+
+DROP TRIGGER IF EXISTS application_view_insert_trigger;
+CREATE TRIGGER application_view_insert_trigger
+INSTEAD OF INSERT ON application_view
+BEGIN
+ INSERT OR IGNORE INTO label(name) VALUES (NEW.name);
+ INSERT INTO app(label_id) SELECT label_id FROM label WHERE label.name = NEW.name;
+ INSERT INTO app_permission_view(app_id,
+ name,
+ type_name,
+ is_volatile,
+ is_enabled)
+ VALUES(last_insert_rowid(),
+ "ALL_APPS",
+ "ALL_APPS",
+ 0,1);
+END;
+
+
+DROP TRIGGER IF EXISTS application_view_delete_trigger;
+CREATE TRIGGER application_view_delete_trigger
+INSTEAD OF DELETE ON application_view
+BEGIN
+ -- Delete rules that correspond to app's paths:
+ DELETE FROM permission_label_rule
+ WHERE permission_label_rule.label_id IN
+ (SELECT app_path.label_id
+ FROM app_path
+ INNER JOIN application_view
+ ON app_path.app_id = application_view.app_id
+ WHERE application_view.name = OLD.name);
+
+ -- Delete path
+ DELETE FROM path_view
+ WHERE path_view.owner_app_label_name=OLD.name;
+
+ -- Delete apps permissions:
+ DELETE FROM app_permission
+ WHERE app_permission.app_id
+ IN (SELECT application_view.app_id
+ FROM application_view
+ WHERE application_view.name = OLD.name
+ LIMIT 1);
+
+ -- Delete application
+ DELETE FROM app
+ WHERE app.app_id IN (SELECT application_view.app_id
+ FROM application_view
+ WHERE application_view.name = OLD.name
+ LIMIT 1);
+
+ -- Delete label
+ DELETE FROM label_view
+ WHERE label_view.name = OLD.name;
+END;
+
+
+-- PATH VIEW -------------------------------------------------------------------
+DROP VIEW IF EXISTS path_view;
+CREATE VIEW path_view AS
+SELECT application_view.name AS owner_app_label_name,
+ app_path.path AS path,
+ label.name AS path_label_name,
+ app_path.access AS access,
+ app_path_type.name AS path_type_name
+
+FROM app_path
+LEFT JOIN app_path_type USING (app_path_type_id)
+LEFT JOIN application_view USING (app_id)
+LEFT JOIN label USING (label_id);
+
+
+-- For an existing application we add a path.
+DROP TRIGGER IF EXISTS path_view_insert_trigger;
+CREATE TRIGGER path_view_insert_trigger
+INSTEAD OF INSERT ON path_view
+WHEN NEW.owner_app_label_name IN (SELECT application_view.name
+ FROM application_view)
+BEGIN
+ INSERT OR IGNORE INTO label(name) VALUES (NEW.path_label_name);
+
+ INSERT INTO app_path(app_id, path, label_id, access, app_path_type_id)
+ SELECT application_view.app_id,
+ NEW.path,
+ label.label_id,
+ str_to_access(NEW.access),
+ app_path_type.app_path_type_id
+
+ FROM application_view, app_path_type, label
+ WHERE application_view.name = NEW.owner_app_label_name AND
+ app_path_type.name = NEW.path_type_name AND
+ label.name = NEW.path_label_name;
+
+END;
+
+DROP TRIGGER IF EXISTS path_view_delete_trigger;
+CREATE TRIGGER path_view_delete_trigger
+INSTEAD OF DELETE ON path_view
+BEGIN
+ DELETE FROM app_path
+ WHERE app_path.app_id IN (SELECT app.app_id
+ FROM app, label
+ WHERE label.name = OLD.owner_app_label_name AND
+ app.label_id = label.label_id);
+
+ DELETE FROM label_view WHERE label_view.name = OLD.path_label_name;
+END;
+
+-- APP PERMISSION LIST VIEW ----------------------------------------------------
+-- Used in check_app_permission_internal to check if permissions are present
+-- TODO: Check if SQLite optimizer doesn't change app_permission_view to the same code.
+DROP VIEW IF EXISTS app_permission_list_view;
+CREATE VIEW app_permission_list_view AS
+SELECT app_permission.app_id AS app_id,
+ app_permission.permission_id AS permission_id,
+ permission_view.name AS permission_name,
+ permission_view.type_name AS permission_type_name,
+ app_permission.is_volatile AS is_volatile,
+ app_permission.is_enabled AS is_enabled
+FROM app_permission
+INNER JOIN permission_view
+ON permission_view.permission_id = app_permission.permission_id;
+
+
+
+-- APP PERMISSION VIEW ---------------------------------------------------------
+DROP VIEW IF EXISTS app_permission_view;
+CREATE VIEW app_permission_view AS
+SELECT application_view.app_id,
+ application_view.name AS app_name,
+ permission_view.permission_id,
+ permission_view.name,
+ permission_view.type_name,
+ app_permission.is_volatile,
+ app_permission.is_enabled
+FROM app_permission
+INNER JOIN application_view
+ON application_view.app_id = app_permission.app_id
+INNER JOIN permission_view
+ON permission_view.permission_id = app_permission.permission_id;
+
+
+DROP TRIGGER IF EXISTS app_permission_view_insert_trigger;
+CREATE TRIGGER app_permission_view_insert_trigger
+INSTEAD OF INSERT ON app_permission_view
+BEGIN
+ INSERT INTO app_permission(app_id, permission_id, is_volatile, is_enabled)
+ SELECT NEW.app_id,
+ permission_view.permission_id,
+ NEW.is_volatile,
+ NEW.is_enabled
+ FROM permission_view
+ WHERE permission_view.name = NEW.name AND
+ permission_view.type_name = NEW.type_name;
+END;
+
+
+
+
+-- It's forbidden do change permission from not volatile to volatile.
+-- We have to check it before inserting anything.
+-- Used in updating permissions
+DROP TRIGGER IF EXISTS app_permission_view_update_trigger;
+CREATE TRIGGER app_permission_view_update_trigger
+INSTEAD OF UPDATE ON app_permission_view
+BEGIN
+ UPDATE OR IGNORE app_permission
+ SET is_enabled = NEW.is_enabled
+ WHERE app_permission.app_id = OLD.app_id AND
+ app_permission.permission_id
+ IN (SELECT permission_view.permission_id
+ FROM permission_view
+ WHERE permission_view.name = OLD.name AND
+ permission_view.type_name = OLD.type_name
+ LIMIT 1);
+END;
+
+
+DROP TRIGGER IF EXISTS app_permission_view_delete_trigger;
+CREATE TRIGGER app_permission_view_delete_trigger
+INSTEAD OF DELETE ON app_permission_view
+BEGIN
+ DELETE FROM app_permission
+ WHERE app_permission.app_id
+ IN (SELECT application_view.app_id
+ FROM application_view
+ WHERE application_view.name = OLD.app_name
+ LIMIT 1)
+ AND
+ app_permission.permission_id NOT IN (SELECT permission_view.permission_id
+ FROM permission_view
+ WHERE permission_view.name = "ALL_APPS" AND
+ permission_view.type_name = "ALL_APPS");
+END;
+
+-- APP PERMISSION VOLATILE VIEW ------------------------------------------------
+DROP VIEW IF EXISTS app_permission_volatile_view;
+CREATE VIEW app_permission_volatile_view AS
+SELECT *
+FROM app_permission_view
+WHERE app_permission_view.is_volatile = 1;
+
+
+DROP TRIGGER IF EXISTS app_permission_volatile_view_delete_trigger;
+CREATE TRIGGER app_permission_volatile_view_delete_trigger
+INSTEAD OF DELETE ON app_permission_volatile_view
+BEGIN
+ DELETE FROM app_permission
+ WHERE app_permission.is_volatile = 1 AND
+ app_permission.app_id
+ IN (SELECT application_view.app_id
+ FROM application_view
+ WHERE application_view.name = OLD.app_name
+ LIMIT 1);
+END;
+
+
+-- APPLICATIONS PERMISSIONS ID -------------------------------------------------
+-- All applications and their permissions
+DROP VIEW IF EXISTS app_label_with_permission_view;
+CREATE VIEW app_label_with_permission_view AS
+SELECT app_permission.permission_id,
+ application_view.name,
+ application_view.app_id,
+ app_permission.is_volatile
+FROM app_permission
+INNER JOIN application_view
+ ON application_view.app_id = app_permission.app_id AND
+ app_permission.is_enabled = 1;
+
+
+
+-- PERMISSION TO PERMISSION RULE VIEW ------------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_permission_permission_rule_view;
+CREATE VIEW ltl_permission_permission_rule_view AS
+SELECT (CASE WHEN is_reverse = 0 THEN app1.name ELSE app2.name END) AS subject,
+ (CASE WHEN is_reverse = 1 THEN app1.name ELSE app2.name END) AS object,
+ p.access,
+ app1.is_volatile OR app2.is_volatile AS is_volatile
+FROM permission_permission_rule AS p
+INNER JOIN app_label_with_permission_view AS app1
+ ON app1.permission_id = p.permission_id
+INNER JOIN app_label_with_permission_view AS app2
+ ON app2.permission_id = p.target_permission_id AND
+ app1.app_id != app2.app_id;
+
+-- PERMISSION TO LABEL RULE VIEW -----------------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_permission_label_rule_view;
+CREATE VIEW ltl_permission_label_rule_view AS
+SELECT (CASE WHEN is_reverse = 0 THEN app.name ELSE label.name END) AS subject,
+ (CASE WHEN is_reverse = 1 THEN app.name ELSE label.name END) AS object,
+ p.access,
+ app.is_volatile
+FROM permission_label_rule AS p
+INNER JOIN app_label_with_permission_view AS app
+ ON app.permission_id = p.permission_id
+INNER JOIN label
+ ON label.label_id = p.label_id AND
+ app.name != label.name;
+
+
+
+-- PERMISSION TO PATH TYPE RULE VIEW -------------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_permission_app_path_type_rule_view;
+CREATE VIEW ltl_permission_app_path_type_rule_view AS
+SELECT (CASE WHEN is_reverse = 0 THEN app.name ELSE label.name END) AS subject,
+ (CASE WHEN is_reverse = 1 THEN app.name ELSE label.name END) AS object,
+ p.access,
+ app.is_volatile
+FROM permission_app_path_type_rule AS p
+INNER JOIN app_label_with_permission_view AS app
+ ON app.permission_id = p.permission_id
+INNER JOIN app_path
+ ON app_path.app_path_type_id = p.app_path_type_id
+INNER JOIN label
+ ON label.label_id = app_path.label_id AND
+ app.name != label.name;
+
+
+-- PERMISSION TO APPLICATION'S OWN PATHS ---------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_app_path_view;
+CREATE VIEW ltl_app_path_view AS
+SELECT application_view.name AS subject,
+ label.name AS object,
+ app_path.access AS access
+FROM app_path
+INNER JOIN application_view ON application_view.app_id = app_path.app_id
+INNER JOIN label ON label.label_id = app_path.label_id;
+
+
+-- SMACK RULES VIEWS -----------------------------------------------------------
+DROP VIEW IF EXISTS all_smack_binary_rules_view;
+CREATE VIEW all_smack_binary_rules_view AS
+SELECT subject,
+ object,
+ bitwise_or(access) AS access,
+ MIN(is_volatile) AS is_volatile
+FROM (SELECT subject, object, access, is_volatile
+ FROM ltl_permission_permission_rule_view
+ UNION ALL
+ SELECT subject, object, access, is_volatile
+ FROM ltl_permission_label_rule_view
+ UNION ALL
+ SELECT subject, object, access, is_volatile
+ FROM ltl_permission_app_path_type_rule_view
+ UNION ALL
+ SELECT subject, object, access, 0
+ FROM ltl_app_path_view
+ )
+GROUP BY subject, object
+ORDER BY subject, object ASC;
+
+-- ALL INSERTED DATA VIEW ------------------------------------------------------
+-- This view is used to clear the database from inserted rules.
+-- We loose all information about installed applications
+-- and folders.
+DROP VIEW IF EXISTS all_inserted_data;
+CREATE VIEW all_inserted_data AS
+SELECT *
+FROM label;
+
+DROP TRIGGER IF EXISTS all_inserted_data_delete_trigger;
+CREATE TRIGGER all_inserted_data_delete_trigger INSTEAD OF
+DELETE ON all_inserted_data
+BEGIN
+ DELETE FROM permission_label_rule;
+ DELETE FROM permission_permission_rule;
+ DELETE FROM permission_app_path_type_rule;
+
+ DELETE FROM app_permission;
+
+ DELETE FROM permission;
+ DELETE FROM permission_type;
+
+ DELETE FROM app_path;
+ DELETE FROM app_path_type;
+ DELETE FROM app;
+
+ DELETE FROM label;
+END;
+
+
+
+-- SMACK RULES MODIFICATIONS VIEW ----------------------------------------------
+-- This definition is repeated during opening a connection with the database.
+-- Used to get all smack rules, even volatile.
+-- Ensure it's the same!
+CREATE TEMPORARY VIEW modified_smack_rules AS
+SELECT subject, object,
+ access_to_str(access_add) AS access_add,
+ access_to_str(access_del) AS access_del
+FROM (
+ SELECT subject, object,
+ s1.access & ~s2.access AS access_add,
+ s2.access & ~s1.access AS access_del
+ FROM all_smack_binary_rules AS s1
+ INNER JOIN history_smack_rule AS s2
+ USING (subject, object)
+ WHERE s1.access != s2.access
+
+ UNION
+
+ SELECT subject, object,
+ s1.access AS access_add,
+ 0 AS access_del
+ FROM all_smack_binary_rules AS s1
+ LEFT JOIN history_smack_rule s2
+ USING (subject, object)
+ WHERE s2.subject IS NULL AND
+ s2.object IS NULL
+
+ UNION
+
+ SELECT subject, object,
+ 0 AS access_add,
+ s1.access AS access_del
+ FROM history_smack_rule s1
+ LEFT JOIN all_smack_binary_rules AS s2
+ USING (subject, object)
+ WHERE s2.subject IS NULL AND
+ s2.object IS NULL
+ )
+ORDER BY subject, object ASC;
+
+
+-- Update here!
+PRAGMA schema_version = 1;
+
+COMMIT TRANSACTION;
+
--- /dev/null
+<?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 & Time" color="rgb(200,255,200)">
+ <type label="Date" length="0" sql="DATE" quote="'"/>
+ <type label="Time" length="0" sql="TIME" quote="'"/>
+ <type label="Datetime" length="0" sql="DATETIME" quote="'"/>
+ <type label="Year" length="0" sql="YEAR" quote=""/>
+ <type label="Timestamp" length="0" sql="TIMESTAMP" quote="'"/>
+ </group>
+
+ <group label="Miscellaneous" color="rgb(200,200,255)">
+ <type label="ENUM" length="1" sql="ENUM" quote=""/>
+ <type label="SET" length="1" sql="SET" quote=""/>
+ <type label="Bit" length="0" sql="bit" quote=""/>
+ </group>
+</datatypes><table x="31" y="298" name="app">
+<row name="app_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="app_permission" row="app_id" />
+<relation table="app_path" row="app_id" />
+</row>
+<row name="label_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>app_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>label_id</part>
+</key>
+</table>
+<table x="241" y="43" name="app_permission">
+<row name="app_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="permission_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="is_volatile" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+<default>0</default></row>
+<row name="is_enabled" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+<default>1</default></row>
+<key type="PRIMARY" name="">
+<part>app_id</part>
+<part>permission_id</part>
+</key>
+</table>
+<table x="215" y="490" name="app_path">
+<row name="app_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="path" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<row name="label_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+</row>
+<row name="app_path_type_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>app_id</part>
+<part>path</part>
+</key>
+</table>
+<table x="450" y="577" name="app_path_type">
+<row name="app_path_type_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="app_path" row="app_path_type_id" />
+<relation table="permission_app_path_type_rule" row="app_path_type_id" />
+</row>
+<row name="name" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>app_path_type_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>name</part>
+</key>
+</table>
+<table x="472" y="457" name="label">
+<row name="label_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="app" row="label_id" />
+<relation table="app_path" row="label_id" />
+<relation table="permission_label_rule" row="label_id" />
+</row>
+<row name="name" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>label_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>name</part>
+</key>
+</table>
+<table x="510" y="182" name="permission_type">
+<row name="permission_type_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="permission" row="permission_type_id" />
+</row>
+<row name="type_name" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>permission_type_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>type_name</part>
+</key>
+</table>
+<table x="517" y="65" name="permission">
+<row name="permission_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+<relation table="app_permission" row="permission_id" />
+<relation table="permission_permission_rule" row="permission_id" />
+<relation table="permission_permission_rule" row="target_permission_id" />
+<relation table="permission_label_rule" row="permission_id" />
+<relation table="permission_app_path_type_rule" row="permission_id" />
+</row>
+<row name="permission_type_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="name" null="0" autoincrement="0">
+<datatype>MEDIUMTEXT</datatype>
+</row>
+<key type="PRIMARY" name="">
+<part>permission_id</part>
+</key>
+<key type="UNIQUE" name="">
+<part>permission_type_id</part>
+<part>name</part>
+</key>
+</table>
+<table x="855" y="133" name="permission_permission_rule">
+<row name="permission_id" null="0" autoincrement="1">
+<datatype>INTEGER</datatype>
+</row>
+<row name="target_permission_id" null="1" autoincrement="0">
+<datatype>TINYINT</datatype>
+<default>NULL</default></row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<row name="is_reverse" null="1" autoincrement="0">
+<datatype>INTEGER</datatype>
+<default>NULL</default></row>
+<key type="PRIMARY" name="">
+<part>permission_id</part>
+<part>target_permission_id</part>
+<part>is_reverse</part>
+</key>
+</table>
+<table x="852" y="300" name="permission_label_rule">
+<row name="permission_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="label_id" null="1" autoincrement="0">
+<datatype>TINYINT</datatype>
+<default>NULL</default></row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<row name="is_reverse" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<key type="PRIMARY" name="">
+<part>permission_id</part>
+<part>label_id</part>
+<part>is_reverse</part>
+</key>
+</table>
+<table x="849" y="477" name="permission_app_path_type_rule">
+<row name="permission_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="app_path_type_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<row name="is_reverse" null="0" autoincrement="0">
+<datatype>INTEGER(1)</datatype>
+<default>0</default></row>
+<key type="PRIMARY" name="">
+<part>permission_id</part>
+<part>app_path_type_id</part>
+<part>is_reverse</part>
+</key>
+</table>
+</sql>
#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.
*/
int get_app_gids(const char *app_id, unsigned **gids, int *len);
-/**
- * This functions add public RO path to the database.
- */
-int db_add_public_dir(const char *dir_label);
-
-/**
- * This function returns (in params) list of public RO paths
- * dir_labels should be freed by caller.
- */
-int db_get_public_dirs(char ***dir_labels, int *len);
-
-/**
- * This functions add group RW path to the database.
- */
-int db_add_groups_dir(const char *dir_label);
-
-/**
- * This function returns (in params) list of group RW paths
- * dir_labels should be freed by caller.
- */
-int db_get_groups_dirs(char ***dir_labels, int *len);
-
#endif // _ACCESS_DB_H_
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);
#endif // API
#define DEPRECATED __attribute__((deprecated));
+#define UNUSED __attribute__((unused))
/* error codes */
#define PC_OPERATION_SUCCESS ((int)0)
#define PC_ERR_INVALID_OPERATION -5
#define PC_ERR_DB_OPERATION -6
+/// Label is taken by another application
+#define PC_ERR_DB_LABEL_TAKEN -7
+
+/// Label is forbidden
+#define PC_ERR_DB_LABEL_FORBIDDEN -8
+
+/// Query fails during preparing a SQL statement
+#define PC_ERR_DB_QUERY_PREP -9
+
+/// Query fails during binding to a SQL statement
+#define PC_ERR_DB_QUERY_BIND -10
+
+/// Query fails during stepping a SQL statement
+#define PC_ERR_DB_QUERY_STEP -11
+
+/// Query is too long
+#define PC_ERR_DB_QUERY_TOO_LONG -12
+
+/// Returned value is unexpected,
+/// e.g an int that stores bool is not 0 or 1.
+#define PC_ERR_DB_UNEXPECTED_VALUE -13
+
+/// Constraint violated
+#define PC_ERR_DB_CONSTRAINT -14
+
+// Unable to establish a connection with the database
+#define PC_ERR_DB_CONNECTION -15
+
+// Error when creating boot file with rules
+#define PC_ERR_BOOT_FILE -16
+
+// There is no application with such app_id
+#define PC_ERR_DB_NO_SUCH_APP -17
+
+// There already exists a permission with this name and type
+#define PC_ERR_DB_PERM_FORBIDDEN -18
+
+// There is no permission with a this name
+#define PC_ERR_DB_UNKNOWN_PERMISSION -19
+
+// There is no application with this label
+#define PC_ERR_DB_UNKNOWN_APPLICATION -20
+
+// This permission already exists
+#define PC_PERMISSION_EXISTS -21
+
+
typedef enum {
APP_TYPE_WGT,
APP_TYPE_OSP,
APP_PATH_ANY_LABEL,
} app_path_type_t;
+
/* APIs - used by applications */
int control_privilege(void) DEPRECATED;
const gid_t* list_of_db_gids,
size_t list_size) DEPRECATED;
+
+/**
+ * Run before any privilege modification.
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int perm_modification_start(void);
+
+/**
+ * Run after any privilege modification.
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int perm_modification_finish(void);
+
+
#ifdef __cplusplus
}
#endif // __cplusplus
--- /dev/null
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * @file rules-db-internals.h
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @version 1.0
+ * @brief This file contains definition of rules database API.
+ */
+
+#include <sqlite3.h>
+#include "rules-db.h"
+
+#ifndef _RULES_DB_INTERNALS_H_
+#define _RULES_DB_INTERNALS_H_
+
+#define ACC_LEN 6
+
+// Templates:
+#define SMACK_APP_LABEL_TEMPLATE "~APP~"
+
+// Open database flags:
+#define RDB_READWRITE_FLAG SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_PRIVATECACHE
+#define RDB_READONLY_FLAG SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_PRIVATECACHE
+
+// Bind function defines:
+#define RDB_FIRST_PARAM 1 /// Bind to the first parameter
+#define RDB_SECOND_PARAM 2 /// Bind to the second parameter
+
+#define RDB_AUTO_DETERM_SIZE -1 // Determine the size of the
+
+// Getting values
+#define RDB_FIRST_COLUMN 0
+#define RDB_SECOND_COLUMN 1
+#define RDB_THIRD_COLUMN 2
+#define RDB_FOURTH_COLUMN 3
+
+#define RDB_DISABLE 0
+#define RDB_ENABLE 1
+
+#define RDB_LOG_ENTRY_PARAM(format, ...) C_LOGD("RDB: Entering function %s. Args: " format, __func__, ##__VA_ARGS__)
+#define RDB_LOG_ENTRY C_LOGD("RDB: Entering function %s", __func__)
+
+
+/**
+ * Add the label to the temporary table with modified labels.
+ * We use this table to speed up generating modified smack rules.
+ *
+ * If label is not in this table, but rule changed
+ * Smack will not get the rule in runtime.
+ *
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_label_name label name
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_modified_label_internal(sqlite3 *p_db, const char *const s_label_name);
+
+
+/**
+ * Adds label names of applications with the permission to modified labels.
+ * Used when permission is going to change and we're going to change some
+ * accesses granted by this permission.
+ *
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param i_permission_id id of the permission
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id);
+
+
+/**
+ * Open a connection with the database and perform an initialization.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int open_rdb_connection(sqlite3 **pp_db);
+
+
+/**
+ * Write variables into the query and create a SQLite statement.
+ * One should use the SQLite3 format strings like '%Q'.
+ *
+ * For a lot of generic queries use binding.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param pp_stmt buffer for a pointer to the constructed statement
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int prepare_stmt(sqlite3 *p_db,
+ sqlite3_stmt **pp_stmt,
+ const char *const s_sql,
+ ...);
+
+
+/**
+ * Check if the label is present in the database.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_label_name label's name
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int check_label_internal(sqlite3 *p_db,
+ const char *const s_label_name);
+
+
+/**
+ * Check if the label is available for an application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_label_name application's label name
+ * @return PC_OPERATION_SUCCESS when label free
+ * PC_ERR_DB_LABEL_TAKEN when label taken
+ * error code otherwise
+ */
+int check_app_label_internal(sqlite3 *p_db,
+ const char *const s_label_name);
+
+
+/**
+ * Check if permission with a given name and type is available
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_permission_name permission name
+ * @param s_permission_type_name permission type name
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int check_permission_internal(sqlite3 *p_db,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name);
+
+
+/**
+ * Adds the application to the database.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_label_name application's label name
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_app_internal(sqlite3 *p_db,
+ const char *const s_label_name);
+
+
+/**
+ * Removes the application from the database together with its permissions and paths.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_label_name application's label name
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int remove_app_internal(sqlite3 *p_db,
+ const char *const s_label_name);
+
+
+/**
+ * Add a path to the database
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_owner_label_name label name of the paths owner
+ * @param s_path_label_name path's label name
+ * @param s_path the path
+ * @param access access rights
+ * @param s_type path's type name
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_path_internal(sqlite3 *p_db,
+ const char *const s_owner_label_name,
+ const char *const s_path_label_name,
+ const char *const s_path,
+ const char *const s_access,
+ const char *const s_type);
+
+
+/**
+ * Add a permission with a given name and of a give type
+ * and return its internal permission id.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_permission_name permission name
+ * @param s_permission_type_name permission type name
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_permission_internal(sqlite3 *p_db,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name);
+
+/**
+ * Gets the id of the permission
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_permission_name permission name
+ * @param s_permission_type_name permission type name
+ * @param p_permission_id buffer for the id of the new permission
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int get_permission_id_internal(sqlite3 *p_db,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ sqlite3_int64 *p_permission_id);
+
+/**
+ * Adds a list of smack permissions to the database.
+ * s_permision_name has to appear either in the subject or the object of the rule.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param i_permission_id permission id for which we ad permission rules
+ * @param pp_smack_rules a list of smack rules, that we want to apply. Not empty!
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_permission_rules_internal(sqlite3 *p_db,
+ sqlite3_int64 i_permission_id,
+ const char *const *const pp_smack_rules);
+
+
+
+/**
+ * Gets the internal app id of an application with a given name.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param pi_app_id pointer to where the app is should be returned
+ * @param s_app_label_name label name of the application
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int get_app_id_internal(sqlite3 *p_db,
+ int *pi_app_id,
+ const char *const s_app_label_name);
+
+
+/**
+ * Divides the rule into subject, object and access strings.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param s_rule the string that we parse
+ * @param s_subject buffer for the subject
+ * @param s_object buffer for the object
+ * @param s_access buffer for the access
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int parse_rule(const char *const s_rule,
+ char s_subject[],
+ char s_object[],
+ char s_access[]);
+
+
+/**
+ * Add a new permission to an application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param i_app_id application id
+ * @param s_permission_name permission name
+ * @param s_permission_type_name permission type name
+ * @param b_is_volatile_new is the permission volatile
+ * @param b_is_enabled_new is the permission enabled
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_app_permission_internal(sqlite3 *p_db,
+ int i_app_id,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ const bool b_is_volatile_new,
+ const bool b_is_enabled_new);
+
+
+/**
+ * Enable or disable a permission for a given application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param i_app_id application id
+ * @param s_permission_name permission name
+ * @param s_permission_type_name permission type name
+ * @param b_is_enabled_new is the permission enabled
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int switch_app_permission_internal(sqlite3 *p_db,
+ const int i_app_id,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ const bool b_is_enabled_new);
+
+
+/**
+ * Update an existing permission of an application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param i_app_id application id
+ * @param i_permission_id id of the permission
+ * @param b_is_volatile_new is the permission volatile
+ * @param b_is_enabled_new is the permission enabled
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int update_app_permission_internal(sqlite3 *p_db,
+ const int i_app_id,
+ const int i_permission_id,
+ const bool b_is_volatile_new,
+ const bool b_is_enabled_new);
+
+
+/**
+ * Change a permission for an application.
+ * Function modifies or adds a permission.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param i_app_id application id
+ * @param s_permission_name permission name
+ * @param s_permission_type_name permission type name
+ * @param i_is_volatile_new is the permission volatile
+ * @param i_is_enabled_new is the permission enabled
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int change_app_permission_internal(sqlite3 *p_db,
+ int i_app_id,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ int i_is_volatile_new,
+ int i_is_enabled_new);
+
+
+/**
+ * Delete all permissions of the application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_app_label_name applications label name
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int revoke_app_permissions_internal(sqlite3 *p_db,
+ const char *const s_app_label_name);
+
+
+/**
+ * Delete all volatile permissions of the application.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param s_app_label_name applications label name
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int reset_app_permissions_internal(sqlite3 *p_db,
+ const char *const s_app_label_name);
+
+
+/**
+ * Saves present smack rules in a temporary table: history_smack_rule
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int save_smack_rules(sqlite3 *p_db);
+
+
+/**
+ * Updates smack rules. Only rules that change are refreshed.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int update_smack_rules(sqlite3 *p_db);
+
+
+#endif // _RULES_DB_INTERNALS_H_
\ No newline at end of file
--- /dev/null
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+/*
+ * @file rules-db.h
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @version 1.0
+ * @brief This file contains definition of rules database API.
+ */
+
+#ifndef _RULES_DB_H_
+#define _RULES_DB_H_
+
+#include "privilege-control.h" // For error codes
+#include "common.h"
+
+#define RDB_PATH "/opt/dbspace/.rules-db.db3"
+#define RDB_BOOT_FILE_PATH "/opt/etc/smack/boot-rules.smack"
+#define RDB_BOOT_FILE_PATH_NEW "/opt/etc/smack/boot-rules-new.smack"
+
+
+/**
+ * Starts a session with the database.
+ * Begins transaction.
+ *
+ * @ingroup RDB API functions
+ *
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int rdb_modification_start(void);
+
+
+/**
+ * Finishes the session with the database.
+ * Commits or rollbacks.
+ *
+ * @ingroup RDB API functions
+ *
+ */
+void rdb_modification_finish(void);
+
+
+/**
+ * Add application label to the database.
+ * If label present: do nothing.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param s_label_name s_label_name application label
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int rdb_add_application(const char *const s_label_name);
+
+
+/**
+ * Remove application label from the table.
+ * Used during uninstalling application.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param s_label_name application's label name
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int rdb_remove_application(const char *const s_label_name);
+
+
+/**
+ * Add a path to the database.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param s_owner_label_name owner application's label name
+ * @param s_path_label_name path's label name
+ * @param s_path the path
+ * @param i_access access rights
+ * @param s_type type of path
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int rdb_add_path(const char *const s_owner_label_name,
+ const char *const s_path_label_name,
+ const char *const s_path,
+ const char *const s_access,
+ const char *const s_type);
+
+
+/**
+ * Add permission with the given name and type and add smack rules.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param s_permission_name new permission's name
+ * @param s_permission_type_name new permission's type
+ * @param pp_smack_rules a table of smack accesses to apply
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int rdb_add_permission_rules(const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ const char *const *const pp_smack_rules);
+
+
+/**
+ * Enable permissions from the list.
+ * If there were no such permissions, we adds them.
+ * One can't change permissions from non volatile to volatile,
+ * One can change permissions from volatile to non volatile,
+ * but it's suspicious...
+ *
+ * @ingroup RDB API functions
+ *
+ * @param s_app_label_name application's label name
+ * @param s_permission_type_name permission's type name
+ * @param pp_permissions_list array of permissions to parse
+ * @param b_is_volatile are the new permissions volatile
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int rdb_enable_app_permissions(const char *const s_app_label_name,
+ const char *const s_permission_type_name,
+ const char *const *const pp_permissions_list,
+ const bool b_is_volatile);
+
+
+/**
+ * Disable permissions from the list.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param s_app_label_name application's label name
+ * @param s_permission_type_name permission's type name
+ * @param pp_permissions_list array of permissions to parse
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int rdb_disable_app_permissions(const char *const s_app_label_name,
+ const char *const s_permission_type_name,
+ const char *const *const pp_permissions_list);
+
+
+/**
+ * Validate if all rules in the array can be parsed.
+ *
+ * @param pp_permissions_list array of permissions to check
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int validate_all_rules(const char *const *const pp_permissions_list);
+
+
+/**
+ * Revokes all permissions from the application by.
+ * deleting all permissions from app_permission table.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param s_app_label_name application's label name
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int rdb_revoke_app_permissions(const char *const s_app_label_name);
+
+
+/**
+ * Revokes all volatile permissions from the application by.
+ * deleting all permissions from app_permission table.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param s_app_label_name application's label name
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+int rdb_reset_app_permissions(const char *const s_app_label_name);
+
+#endif /*_RULES_DB_H_*/
\ No newline at end of file
<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>
-* Tue Aug 20 2013 Rafal Krypa <r.krypa@samsung.com> - 0.0.42.TIZEN
-- Changed dlog logging buffer.
+* Mon Sep 16 2013 Bartlomiej Grzelewski - 0.0.57.SLP
+[Jan Olszak]
+- Optimalization of the database operation time.
+
+* Fri Sep 13 2013 Krzysztof Jackiewicz - 0.0.56.SLP
+[Jan Olszak]
+- Corrected behavior when there is no Smack on the target.
+[Jan Olszak]
+- Correct antivirus access rights to public dirs.
+[Jan Olszak]
+- Rules kept in SQLite3 database. Initial commit.
+[Jan Olszak]
+- SQLite3 database for application permissions.
+[Krzysztof Jackiewicz]
+- Fix for ~APP~ label allowance issue
+[Krzysztof Jackiewicz]
+- Unused function smack_get_access_new removed
+[Krzysztof Jackiewicz]
+- Libprivilege API cleanup
+[Lukasz Kostyra]
+- Add missing information about APP_PATH_ANY_LABEL in header
+[Bartlomiej Grzelewski]
+- Takes compilation profile from command line.
+
+* Wed Aug 28 2013 Krzysztof Jackiewicz - 0.0.55.SLP
+[Janusz Kozerski]
+- Add for all anti viruses RWX access to all public-RO and group-RW shared folder
+[Marcin Lis]
+- Simple corrections in api-feature handling.
+
+* Tue Aug 13 2013 Rafal Krypa - 0.0.54.SLP
- Adapt code for new libsmack API
- Rewrite internal function app_uninstall_remove_early_rules()
- Create format strings for scanf statically.
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
%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}
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
mkdir -p /opt/etc/smack-app-early/accesses.d
fi
+if [ ! -e "/opt/dbspace/.rules-db.db3" ]
+then
+ # First installation
+ rm -f /opt/dbspace/.rules-db.db3-journal
+ sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db.sql
+ sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db-data.sql
+
+ api_feature_loader --verbose
+else
+ # There is the rules-db database.
+ sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db.sql
+ sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db-data.sql
+fi
+
+rm -f /opt/dbspace/rules-db.sql
+rm -f /opt/dbspace/rules-db-data.sql
+
%files
%{_libdir}/*.so.*
+%{_libdir}/librules-db-sql-udf.so
%{_bindir}/slp-su
#%{udev_libdir}/rules.d/*
#%attr(755,root,root) %{udev_libdir}/uname_env
%{_datadir}/license/%{name}
#systemd service
-/usr/lib/systemd/system/smack-late-rules.service
-/usr/lib/systemd/system/smack-early-rules.service
-/usr/bin/rule_loader
+/usr/lib/systemd/system/smack-rules.service
+/usr/bin/api_feature_loader
#link to activate systemd service
-/usr/lib/systemd/system/multi-user.target.wants/smack-late-rules.service
-/usr/lib/systemd/system/multi-user.target.wants/smack-early-rules.service
+/usr/lib/systemd/system/multi-user.target.wants/smack-rules.service
+/opt/dbspace/rules-db.sql
+/opt/dbspace/rules-db-data.sql
+/opt/etc/smack/load-rules-db.sql
%files conf
/etc/group
%files devel
%{_includedir}/*.h
-%{_libdir}/*.so
+%{_libdir}/libprivilege-control.so
%{_libdir}/pkgconfig/*.pc
+++ /dev/null
-#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;
-}
+++ /dev/null
-[Unit]
-Description=Late SMACK rules loading
-ConditionSecurity=smack
-Before=starter.service
-
-[Service]
-Type=oneshot
-ExecStart=/usr/bin/smackload /opt/etc/smack-app-early/accesses.d
-
-[Install]
-WantedBy=multi-user.target
+++ /dev/null
-[Unit]
-Description=Late SMACK rules loading
-ConditionSecurity=smack
-After=starter.service
-
-[Service]
-Type=oneshot
-ExecStart=/usr/bin/rule_loader
-
-[Install]
-WantedBy=multi-user.target
--- /dev/null
+[Unit]
+Description=SMACK rules loading
+Before=starter.service
+
+[Service]
+Type=oneshot
+ExecStartPre = /bin/bash -c '/usr/bin/sqlite3 /opt/dbspace/.rules-db.db3 < /opt/etc/smack/load-rules-db.sql'
+ExecStart = /usr/bin/smackload /opt/etc/smack/boot-rules.smack
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
#include "common.h"
typedef enum {
- DB_APP_TYPE_APPLICATION,
- DB_APP_TYPE_ANTIVIRUS,
DB_APP_TYPE_GROUPS,
- DB_APP_TYPE_PUBLIC_DIRS,
- DB_APP_TYPE_GROUPS_DIRS,
- DB_APP_TYPE_APPSETTING,
- DB_APP_TYPE_SETTING_DIR,
DB_APP_TYPE_COUNT /* Dummy enum element to get number of elements */
} db_app_type_t;
const char* db_file_names[DB_APP_TYPE_COUNT] = {
- "/opt/dbspace/.privilege_control_all_apps_id.db",
- "/opt/dbspace/.privilege_control_all_avs_id.db",
- "/opt/dbspace/.privilege_control_app_gids.db",
- "/opt/dbspace/.privilege_control_public_dirs.db",
- "/opt/dbspace/.privilege_control_groups_dirs.db",
- "/opt/dbspace/.privilege_control_app_setting.db",
- "/opt/dbspace/.privilege_control_setting_dir.db",
+ "/opt/dbspace/.privilege_control_app_gids.db"
};
typedef struct element_s {
return new_element;
}
+
static int remove_list(element_t* first_elem)
{
SECURE_C_LOGD("Entering function: %s.", __func__);
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",
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__);
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)
{
return ret;
}
+
int get_app_gids(const char *app_id, unsigned **gids, int *len)
{
SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
}
return ret;
-}
-
-int db_add_public_dir(const char *dir_label)
-{
- SECURE_C_LOGD("Entering function: %s. Params: dir_label=%s",
- __func__, dir_label);
-
- if (add_id_to_database_internal(dir_label, DB_APP_TYPE_PUBLIC_DIRS))
- {
- C_LOGE("add_id_to_database_internal failed.");
- return PC_ERR_DB_OPERATION;
- }
-
- return PC_OPERATION_SUCCESS;
-}
-
-int db_get_public_dirs(char ***dir_labels, int *len)
-{
- SECURE_C_LOGD("Entering function: %s.", __func__);
-
- if (get_all_ids_internal(dir_labels, len, DB_APP_TYPE_PUBLIC_DIRS))
- {
- C_LOGE("get_all_ids_internal failed.");
- return PC_ERR_DB_OPERATION;
- }
-
- return PC_OPERATION_SUCCESS;
-}
-
-int db_add_groups_dir(const char *dir_label)
-{
- SECURE_C_LOGD("Entering function: %s. Params: dir_label=%s",
- __func__, dir_label);
-
- if (add_id_to_database_internal(dir_label, DB_APP_TYPE_GROUPS_DIRS))
- {
- C_LOGE("add_id_to_database_internal failed.");
- return PC_ERR_DB_OPERATION;
- }
-
- return PC_OPERATION_SUCCESS;
-}
-
-int db_get_groups_dirs(char ***dir_labels, int *len)
-{
- SECURE_C_LOGD("Entering function: %s.", __func__);
-
- if (get_all_ids_internal(dir_labels, len, DB_APP_TYPE_GROUPS_DIRS))
- {
- C_LOGE("get_all_ids_internal failed.");
- return PC_ERR_DB_OPERATION;
- }
-
- return PC_OPERATION_SUCCESS;
-}
+}
\ No newline at end of file
}
-/**
- * This function checks if SMACK rules of application were already loaded
- * by checking if specific file exist. This function doesn't create such file.
- * Return values:
- * 0 if rules weren't yet loaded,
- * 1 if rules were loaded
- * -1 if error occurs while checking
- */
-int check_if_rules_were_loaded(const char *app_id)
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
- __func__, app_id);
- int ret;
- char *path AUTO_FREE;
-
- ret = smack_mark_file_name(app_id, &path);
- if(PC_OPERATION_SUCCESS != ret) {
- return -1;
- }
-
- return file_exists(path);
-}
-
-/**
- * This function marks that rules for app were already loaded by creating
- * specific for this app (empty) file.
- */
-void mark_rules_as_loaded(const char *app_id)
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
- __func__, app_id);
-
- struct stat s;
- char *path AUTO_FREE;
- FILE *file = NULL;
-
- if(smack_mark_file_name(app_id, &path)) {
- C_LOGE("smack_mark_file_name failed.");
- return;
- }
-
- if (-1 == stat(SMACK_LOADED_APP_RULES, &s)) {
- if (ENOENT == errno) {
- C_LOGD("Creating dir %s.", SMACK_LOADED_APP_RULES);
- mkdir(SMACK_LOADED_APP_RULES, S_IRWXU | S_IRWXG | S_IRWXO);
- }
- }
-
- SECURE_C_LOGD("Creating file %s.", path);
- file = fopen(path, "w");
- fclose(file);
-}
-
-int add_app_first_run_rules(const char *app_id)
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
- __func__, app_id);
-
- int ret;
- int fd AUTO_CLOSE;
- char *smack_path AUTO_FREE;
- struct smack_accesses* smack AUTO_SMACK_FREE;
-
- ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("Error in load_smack_from_file");
- return ret;
- }
- if (have_smack() && smack_accesses_apply(smack)) {
- C_LOGE("smack_accesses_apply failed.");
- return PC_ERR_INVALID_OPERATION;
- }
-
- return PC_OPERATION_SUCCESS;
-}
-
-
static int load_smack_from_file_generic(const char* app_id, struct smack_accesses** smack, int *fd, char** path, bool is_early)
{
/* Notice that app_id is ignored when flag is_early is set.
}
return have_smack;
-}
+}
\ No newline at end of file
#include "privilege-control.h"
#include "access-db.h"
#include "common.h"
+#include "rules-db.h"
#define APP_GID 5000
#define APP_UID 5000
DECISION_LABEL = 1
};
+
+// __attribute__ ((constructor))
+// static void libprivilege_constructor()
+// {
+// SECURE_C_LOGD("Entering function: %s.", __func__);
+// perm_modification_start();
+// }
+
+__attribute__ ((destructor))
+static void libprivilege_destructor()
+{
+ SECURE_C_LOGD("Entering function: %s.", __func__);
+ perm_modification_finish();
+}
+
+API int perm_modification_start()
+{
+ SECURE_C_LOGD("Entering function: %s.", __func__);
+ return rdb_modification_start();
+}
+
+API int perm_modification_finish()
+{
+ SECURE_C_LOGD("Entering function: %s.", __func__);
+
+ rdb_modification_finish();
+ sync();
+ return PC_OPERATION_SUCCESS;
+}
+
API int control_privilege(void)//deprecated
{
SECURE_C_LOGD("Entering function: %s.", __func__);
//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) {
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)
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",
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__);
}
return PC_OPERATION_SUCCESS;
}
-
API char* app_id_from_socket(int sockfd)//deprecated
{
SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
return app_id;
}
-static int app_add_rule(const char *app_id, const char *object, const char *perm)
+
+static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, object=%s, perm=%s",
- __func__, app_id, object, perm);
+ SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
+ __func__, app_id, app_type, permanent);
- int ret;
+ int i, ret;
+ char* smack_path AUTO_FREE;
+ char* smack_path_early AUTO_FREE;
int fd AUTO_CLOSE;
- char *smack_path AUTO_FREE;
- struct smack_accesses* smack AUTO_SMACK_FREE;
+ int fd_early AUTO_CLOSE;
+ struct smack_accesses *smack AUTO_SMACK_FREE;
+ struct smack_accesses *smack_early AUTO_SMACK_FREE;
- ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("load_smack_from_file failed.");
- return ret;
+ if (!smack_label_is_valid(app_id)) {
+ C_LOGE("Invalid param app_id.");
+ return PC_ERR_INVALID_PARAM;
}
- ret = smack_accesses_add_modify(smack, app_id, object, perm, "");
- if (ret == -1) {
- C_LOGE("smack_accesses_add_modify failed.");
- return PC_ERR_INVALID_OPERATION;
+ if(perm_list == NULL) {
+ C_LOGE("Invalid perm_list (NULL).");
+ return PC_ERR_INVALID_PARAM;
}
- if (have_smack() && smack_accesses_apply(smack)) {
- C_LOGE("smack_accesses_apply failed.");
- return PC_ERR_INVALID_OPERATION;
+ if (app_type_group_name(app_type) == NULL) {
+ C_LOGE("Unknown app type.");
+ return PC_ERR_INVALID_PARAM;
}
- if (smack_accesses_save(smack, fd)) {
- C_LOGE("smack_accesses_save failed.");
- return PC_ERR_INVALID_OPERATION;
+ // Add permission to DAC
+ for (i = 0; perm_list[i] != NULL; ++i) {
+ ret = perm_to_dac(app_id, app_type, perm_list[i]);
+ if (ret != PC_OPERATION_SUCCESS){
+ C_LOGE("perm_to_dac failed");
+ return ret;
+ }
}
+ // Enable the permissions:
+ ret = rdb_enable_app_permissions(app_id,
+ app_type_group_name(app_type),
+ perm_list,
+ !((bool)permanent));
+ if (ret != PC_OPERATION_SUCCESS) {
+ C_LOGE("RDB rdb_enable_app_permissions failed with: %d", ret);
+ return ret;
+ }
+
+
+ SECURE_C_LOGD("Leaving function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
+ __func__, app_id, app_type, permanent);
+
return PC_OPERATION_SUCCESS;
}
+API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
+{
+ SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
+ __func__, app_id);
+
+ return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
+}
-static int
-app_register_appsetting(const char *app_id, struct smack_accesses *smack)
+API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
{
SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
__func__, app_id);
- int ret;
- int i;
+ return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 0);
+}
- char **label_app_list AUTO_FREE;
- char **label_dir_list AUTO_FREE;
- int app_list_len = 0;
- int dir_list_len = 0;
+API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
+{
+ SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
+ __func__, pkg_id, app_type, persistent);
- if (!smack_label_is_valid(app_id)) {
+ return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
+}
+
+API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)
+{
+ SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
+ __func__, pkg_id, app_type, persistent);
+
+ return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
+}
+
+API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
+{
+ SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
+ __func__, pkg_id, app_type);
+
+ return perm_app_disable_permissions(pkg_id, app_type, perm_list);
+}
+
+/* FIXME: this function is only a stub */
+API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
+{
+ SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
+ __func__, pkg_id, app_type);
+
+ int ret;
+ if (!smack_label_is_valid(pkg_id)) {
C_LOGE("Invalid param app_id.");
return PC_ERR_INVALID_PARAM;
}
- /* writing appsetting_id (app_id) to "database"*/
- ret = add_appsetting_id_to_databse(app_id);
- if (ret != PC_OPERATION_SUCCESS)
- goto out;
-
-
- /* Reading labels of all installed apps from "database"*/
- ret = get_all_apps_ids(&label_app_list, &app_list_len);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("Error while getting data from database");
- goto out;
+ if (perm_list == NULL) {
+ C_LOGE("Invalid perm_list (NULL).");
+ return PC_ERR_INVALID_PARAM;
}
- /*Add smack rules with rx access to each app*/
- for (i = 0; i < app_list_len; ++i) {
- C_LOGD("Appsetting: applying rx rule for %s", label_app_list[i]);
- if (smack_accesses_add_modify(smack, app_id,
- label_app_list[i], "rx", "") == -1) {
- C_LOGE("smack_accesses_add_modify failed.");
- ret = PC_ERR_INVALID_OPERATION;
- goto out;
- }
+ if (app_type_group_name(app_type) == NULL) {
+ C_LOGE("Unknown app type.");
+ return PC_ERR_INVALID_PARAM;
}
- /* Reading labels of all registered settings dirs from "database"*/
- ret = get_all_settings_dir_ids(
- &label_dir_list, &dir_list_len);
+ ret = rdb_disable_app_permissions(pkg_id, app_type_group_name(app_type), perm_list);
if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("Error while getting data from database");
- goto out;
- }
- /*Add smack rules with rwx access to each app*/
- for (i = 0; i < dir_list_len; ++i) {
- C_LOGD("Appsetting: applying rwx rule for %s", label_dir_list[i]);
- if (smack_accesses_add_modify(smack, app_id,
- label_dir_list[i], "rwx", "") == -1) {
- C_LOGE("smack_accesses_add_modify failed.");
- ret = PC_ERR_INVALID_OPERATION;
- goto out;
- /* Should we abort adding rules if
- * smack_accesses_add_modify fails once?*/
- }
+ C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
+ return ret;
}
- out:
- for (i = 0; i < app_list_len; ++i) {
- free(label_app_list[i]);
- }
- for (i = 0; i < dir_list_len; ++i) {
- free(label_dir_list[i]);
- }
+ return PC_OPERATION_SUCCESS;
+}
- return ret;
+API int app_revoke_permissions(const char* pkg_id)//deprecated
+{
+ SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
+ return perm_app_revoke_permissions(pkg_id);
}
-static int give_anti_virus_access_to_all_folders(const char *app_av_id, struct smack_accesses* smack, int folder_type)
+API int perm_app_revoke_permissions(const char* pkg_id)
{
+ SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
int ret;
- int i;
- char** smack_label_list AUTO_FREE;
- int smack_label_list_len = 0;
-
- switch (folder_type) {
- case APP_PATH_PUBLIC_RO:
- ret = db_get_public_dirs(&smack_label_list, &smack_label_list_len);
- break;
- case APP_PATH_GROUP_RW:
- ret = db_get_groups_dirs(&smack_label_list, &smack_label_list_len);
- break;
- case APP_PATH_SETTINGS_RW:
- ret = get_all_settings_dir_ids(&smack_label_list, &smack_label_list_len);
- break;
- default:
- return PC_OPERATION_SUCCESS;
- }
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("Error while getting public RO folders from database.");
- goto out;
+ if (!smack_label_is_valid(pkg_id)) {
+ C_LOGE("Invalid param app_id.");
+ return PC_ERR_INVALID_PARAM;
}
- for (i = 0; i < smack_label_list_len; ++i) {
- SECURE_C_LOGD("Applying rwx rule for %s", smack_label_list[i]);
- if (smack_accesses_add_modify(smack, app_av_id, smack_label_list[i], "wrx", "") == -1) {
- C_LOGE("smack_accesses_add_modify failed.");
- ret = PC_ERR_INVALID_OPERATION;
- goto out;
- }
+ ret = rdb_revoke_app_permissions(pkg_id);
+ if (ret != PC_OPERATION_SUCCESS) {
+ C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
+ return ret;
}
-out:
+ return PC_OPERATION_SUCCESS;
+}
- for (i = 0; i < smack_label_list_len; ++i) {
- free(smack_label_list[i]);
- }
+API int app_reset_permissions(const char* pkg_id)//deprecated
+{
+ SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
+ __func__, pkg_id);
- return ret;
+ return perm_app_reset_permissions(pkg_id);
}
-static int app_register_av_internal(const char *app_av_id, struct smack_accesses* smack)
+API int perm_app_reset_permissions(const char* pkg_id)
{
- SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s.",
- __func__, app_av_id);
-
+ SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
+ __func__, pkg_id);
int ret;
- int i;
- char** smack_label_app_list AUTO_FREE;
- int smack_label_app_list_len = 0;
-
- if (!smack_label_is_valid(app_av_id)) {
- C_LOGE("Invalid param app_av_id.");
+ if (!smack_label_is_valid(pkg_id)) {
+ C_LOGE("Invalid param pkg_id.");
return PC_ERR_INVALID_PARAM;
}
- if(smack == NULL) {
- C_LOGE("Invalid param smack (NULL).");
- return PC_ERR_INVALID_PARAM;
+ ret = rdb_reset_app_permissions(pkg_id);
+ if (ret != PC_OPERATION_SUCCESS) {
+ C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
+ return ret;
}
- // writing anti_virus_id (app_av_id) to "database"
- ret = add_av_id_to_databse(app_av_id);
- if (ret != PC_OPERATION_SUCCESS )
- goto out;
+ return PC_OPERATION_SUCCESS;
+}
- // Reading labels of all installed apps from "database"
- ret = get_all_apps_ids(&smack_label_app_list, &smack_label_app_list_len);
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("Error while getting installed apps from database.");
- goto out;
- }
- for (i = 0; i < smack_label_app_list_len; ++i) {
- SECURE_C_LOGD("Applying rwx rule for %s", smack_label_app_list[i]);
- if (smack_accesses_add_modify(smack, app_av_id, smack_label_app_list[i], "wrx", "") == -1) {
- C_LOGE("smack_accesses_add_modify failed.");
- ret = PC_ERR_INVALID_OPERATION;
- goto out;
- // Should we abort adding rules once smack_accesses_add_modify will fail?
- }
- }
+API int app_label_dir(const char* label, const char* path)//deprecated
+{
+ SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
+ __func__, label, path);
- // Giving anti virus RWX access to public RO folders
- ret = give_anti_virus_access_to_all_folders(app_av_id, smack, APP_PATH_PUBLIC_RO);
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("Error while getting public RO folders from database.");
- goto out;
+ int ret = PC_OPERATION_SUCCESS;
+
+ if(path == NULL) {
+ C_LOGE("Invalid argument path (NULL).");
+ return PC_ERR_INVALID_PARAM;
}
- // Giving anti virus RWX access to groups RW folders
- ret = give_anti_virus_access_to_all_folders(app_av_id, smack, APP_PATH_GROUP_RW);
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("Error while getting groups RW folders from database.");
- goto out;
+ if (!smack_label_is_valid(label)) {
+ C_LOGE("Invalid param label.");
+ return PC_ERR_INVALID_PARAM;
}
- // Giving anti virus RWX access to settings RW folders
- ret = give_anti_virus_access_to_all_folders(app_av_id, smack, APP_PATH_SETTINGS_RW);
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("Error while getting settings RW folders from database.");
- goto out;
+ //setting access label on everything in given directory and below
+ ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
+ if (PC_OPERATION_SUCCESS != ret)
+ {
+ C_LOGE("dir_set_smack_r failed.");
+ return ret;
}
-out:
- for (i = 0; i < smack_label_app_list_len; ++i) {
- free(smack_label_app_list[i]);
+ //setting execute label for everything with permission to execute
+ ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
+ if (PC_OPERATION_SUCCESS != ret)
+ {
+ C_LOGE("dir_set_smack_r failed.");
+ return ret;
}
+ //setting execute label for everything with permission to execute
+ ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
return ret;
}
-/**
- * This function will find labels of all anti viruses in database
- * and for all of them will add a rule "anti_virus_label app_id rwx".
- * This should be called in app_install function.
- */
-static int register_app_for_av(const char * app_id)
+
+API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s.",
- __func__, app_id);
+ SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
+ __func__, app_label, shared_label, path);
+ int ret;
- int ret, i;
- char** smack_label_av_list AUTO_FREE;
- int smack_label_av_list_len = 0;
-
- // Reading labels of all installed anti viruses from "database"
- ret = get_all_avs_ids(&smack_label_av_list, &smack_label_av_list_len);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("Error while geting data from database.");
- return ret;
- }
-
- // for each anti-virus label put rule: "anti_virus_label app_id rwx"
- for (i = 0; i < smack_label_av_list_len; ++i) {
- SECURE_C_LOGD("Antivirus: app_add_rule (%s, %s rx)", smack_label_av_list[i], app_id);
- if (strcmp(app_id, smack_label_av_list[i])==0) {
- SECURE_C_LOGW("Trying to add antivirus rule for self. Skipping");
- continue;
- }
- ret = app_add_rule(smack_label_av_list[i], app_id, "wrx");
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_add_rule failed.");
- goto out;
- }
-
- free(smack_label_av_list[i]);
- }
-
- ret = PC_OPERATION_SUCCESS;
-
-out:
- // If something failed, then no entry of smack_label_av_list[i]
- // was deallocated. They all must be freed.
- for(; i<smack_label_av_list_len; ++i) {
- free(smack_label_av_list[i]);
- }
-
- return ret;
-}
-
-/**
- * This function will find labels of all setting applications in database
- * and for all of them will add a rule "appsetting_id app_id rwx".
- * This should be called in app_install function.
- */
-static int register_app_for_appsetting(const char *app_id)
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
- __func__, app_id);
-
- int ret, i;
- char **smack_label_list AUTO_FREE;
- int smack_label_list_len = 0;
-
- /* Reading labels of all installed setting managers from "database"*/
- ret = get_all_appsetting_ids(&smack_label_list, &smack_label_list_len);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("Error while geting data from database.");
- return ret;
- }
-
- /* for each appsetting put rule: "appsetting_id app_id rx"*/
- for (i = 0; i < smack_label_list_len; ++i) {
- SECURE_C_LOGD("Appsetting: app_add_rule (%s, %s rx)", smack_label_list[i], app_id);
- if (strcmp(app_id, smack_label_list[i])==0) {
- SECURE_C_LOGW("Trying to add setting rule for self. Skipping");
- continue;
- }
-
- ret = app_add_rule(smack_label_list[i], app_id, "rx");
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_add_rule failed");
- goto out;
- }
-
- free(smack_label_list[i]);
- }
-
- ret = PC_OPERATION_SUCCESS;
-
-out:
- /* If something failed, then no entry of smack_label_list[i]
- was deallocated. They all must be freed.*/
- for (; i < smack_label_list_len; ++i) {
- free(smack_label_list[i]);
- }
-
- return ret;
-}
-
-
-/**
- * This function will grant app_id rx access to all public directories and
- * files previously designated by app_setup_path(APP_PATH_PUBLIC_RO)
- * This should be called in app_install function.
- */
-static int register_app_for_public_dirs(const char *app_id, struct smack_accesses *smack)
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
- __func__, app_id);
- int ret, i;
- char **public_dirs AUTO_FREE;
- int public_dirs_cnt = 0;
-
- ret = db_get_public_dirs(&public_dirs, &public_dirs_cnt);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("Error while getting data from database");
- return ret;
- }
-
- for (i = 0; i < public_dirs_cnt; ++i) {
- SECURE_C_LOGD("Allowing app %s to access public path %s", app_id, public_dirs[i]);
- if (smack_accesses_add_modify(smack, app_id, public_dirs[i], "rx", "")) {
- C_LOGE("app_add_rule_modify failed");
- while (i < public_dirs_cnt)
- free(public_dirs[i++]);
- return PC_ERR_INVALID_OPERATION;
- }
- free(public_dirs[i]);
- }
-
- return PC_OPERATION_SUCCESS;
-}
-
-static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
- __func__, app_id, app_type, permanent);
-
- int i, ret;
- char* smack_path AUTO_FREE;
- char* smack_path_early AUTO_FREE;
- int fd AUTO_CLOSE;
- int fd_early AUTO_CLOSE;
- struct smack_accesses *smack AUTO_SMACK_FREE;
- struct smack_accesses *smack_early AUTO_SMACK_FREE;
- const char* base_perm = NULL;
-
- if (!smack_label_is_valid(app_id)) {
- C_LOGE("Invalid param app_id.");
- return PC_ERR_INVALID_PARAM;
- }
-
- if(perm_list == NULL) {
- C_LOGE("Invalid perm_list (NULL).");
- return PC_ERR_INVALID_PARAM;
- }
-
- ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("load_smack_from_file failed");
- return ret;
- }
-
- ret = load_smack_from_file_early(app_id, &smack_early, &fd_early, &smack_path_early);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("load_smack_from_file failed");
- return ret;
- }
-
- /* Implicitly enable base permission for an app_type */
- base_perm = app_type_name(app_type);
- if (base_perm) {
- SECURE_C_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
- ret = perm_to_smack(smack, app_id, APP_TYPE_OTHER, base_perm);
- if (ret != PC_OPERATION_SUCCESS){
- C_LOGE("perm_to_smack failed");
- return ret;
- }
-
- // Add early permission - such permissions should be enabled right after system boot
- SECURE_C_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
- ret = perm_to_smack_early(smack_early, app_id, APP_TYPE_OTHER, base_perm);
- if (ret != PC_OPERATION_SUCCESS){
- C_LOGE("perm_to_smack failed");
- return ret;
- }
-
- }
- for (i = 0; perm_list[i] != NULL; ++i) {
- SECURE_C_LOGD("perm_to_smack params: app_id: %s, perm_list[%d]: %s", app_id, i, perm_list[i]);
- if (strcmp(perm_list[i], TIZEN_PRIVILEGE_ANTIVIRUS) == 0) {
- ret = app_register_av_internal(app_id, smack);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_register_av_internal failed");
- return ret;
- }
- }
- if (strcmp(perm_list[i], TIZEN_PRIVILEGE_APPSETTING) == 0) {
- ret = app_register_appsetting(app_id, smack);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_register_appsetting failed");
- return ret;
- }
- }
-
- ret = perm_to_smack(smack, app_id, app_type, perm_list[i]);
- if (ret != PC_OPERATION_SUCCESS){
- C_LOGE("perm_to_smack failed");
- return ret;
- }
-
- ret = perm_to_smack_early(smack_early, app_id, app_type, perm_list[i]);
- if (ret != PC_OPERATION_SUCCESS){
- C_LOGE("perm_to_smack_early failed");
- return ret;
- }
-
- ret = perm_to_dac(app_id, app_type, perm_list[i]);
- if (ret != PC_OPERATION_SUCCESS){
- C_LOGE("perm_to_dac failed");
- return ret;
- }
- }
-
- if (have_smack() && smack_accesses_apply(smack)) {
- C_LOGE("smack_accesses_apply failed");
- return PC_ERR_INVALID_OPERATION;
- }
-
- if (have_smack() && smack_accesses_apply(smack_early)) {
- C_LOGE("smack_accesses_apply (early) failed");
- return PC_ERR_INVALID_OPERATION;
- }
-
- if (permanent && smack_accesses_save(smack, fd)) {
- C_LOGE("smack_accesses_save failed");
- return PC_ERR_INVALID_OPERATION;
- }
-
- if (permanent && smack_accesses_save(smack_early, fd_early)) {
- C_LOGE("smack_accesses_save (early) failed");
- return PC_ERR_INVALID_OPERATION;
- }
-
- return PC_OPERATION_SUCCESS;
-}
-
-API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
- __func__, app_id);
-
- return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
-}
-
-API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
- __func__, app_id);
-
- return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 0);
-}
-
-API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
-{
- SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
- __func__, pkg_id, app_type, persistent);
-
- return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
-}
-
-API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)
-{
- SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
- __func__, pkg_id, app_type, persistent);
-
- return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
-}
-
-API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
-{
- SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
- __func__, pkg_id, app_type);
-
- return perm_app_disable_permissions(pkg_id, app_type, perm_list);
-}
-
-/* FIXME: this function is only a stub */
-API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
-{
- SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
- __func__, pkg_id, app_type);
-
- return PC_OPERATION_SUCCESS;
-}
-
-static int app_revoke_permissions_internal(const char* app_id, bool persistent)
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, persistent=%d",
- __func__, app_id, persistent);
-
- char* smack_path AUTO_FREE;
- int ret;
- int fd AUTO_CLOSE;
- struct smack_accesses *smack AUTO_SMACK_FREE;
-
- if (!smack_label_is_valid(app_id)) {
- C_LOGE("Invalid param app_id.");
- return PC_ERR_INVALID_PARAM;
- }
-
- ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("load_smack_from_file failed.");
- return ret;
- }
-
- if (have_smack() && smack_accesses_clear(smack)) {
- ret = PC_ERR_INVALID_OPERATION;
- C_LOGE("smack_accesses_clear failed.");
- return ret;
- }
-
- if (have_smack() && smack_revoke_subject(app_id)) {
- ret = PC_ERR_INVALID_OPERATION;
- C_LOGE("smack_revoke_subject failed.");
- return ret;
- }
-
- if (persistent && ftruncate(fd, 0) == -1)
- C_LOGW("file truncation failed");
-
- return PC_OPERATION_SUCCESS;
-}
-
-API int app_revoke_permissions(const char* pkg_id)//deprecated
-{
- SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
- return perm_app_revoke_permissions(pkg_id);
-}
-
-API int perm_app_revoke_permissions(const char* pkg_id)
-{
- SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
- int ret;
-
- if (!smack_label_is_valid(pkg_id)) {
- C_LOGE("Invalid param app_id.");
- return PC_ERR_INVALID_PARAM;
- }
-
- ret = app_revoke_permissions_internal(pkg_id, true);
- if (ret) {
- C_LOGE("Revoking permissions failed.");
- return ret;
- }
-
- return PC_OPERATION_SUCCESS;
-}
-
-API int app_reset_permissions(const char* pkg_id)//deprecated
-{
- SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
- __func__, pkg_id);
-
- return perm_app_reset_permissions(pkg_id);
-}
-
-API int perm_app_reset_permissions(const char* pkg_id)
-{
- SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
- __func__, pkg_id);
-
- int ret;
-
- if (!smack_label_is_valid(pkg_id)) {
- C_LOGE("Invalid param pkg_id.");
- return PC_ERR_INVALID_PARAM;
- }
-
- ret = app_revoke_permissions_internal(pkg_id, false);
- if (ret) {
- C_LOGE("Revoking permissions failed.");
- return ret;
- }
-
- /* Add empty permissions set to trigger re-read of rules */
- return perm_app_enable_permissions(pkg_id, APP_TYPE_OTHER, (const char*[]){NULL}, 0);
-}
-
-API int app_label_dir(const char* label, const char* path)//deprecated
-{
- SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
- __func__, label, path);
-
- int ret = PC_OPERATION_SUCCESS;
-
- if(path == NULL) {
- C_LOGE("Invalid argument path (NULL).");
- return PC_ERR_INVALID_PARAM;
- }
-
- if (!smack_label_is_valid(label)) {
- C_LOGE("Invalid param label.");
- return PC_ERR_INVALID_PARAM;
- }
-
- //setting access label on everything in given directory and below
- ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
- if (PC_OPERATION_SUCCESS != ret)
- {
- C_LOGE("dir_set_smack_r failed.");
- return ret;
- }
-
- //setting execute label for everything with permission to execute
- ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
- if (PC_OPERATION_SUCCESS != ret)
- {
- C_LOGE("dir_set_smack_r failed.");
- return ret;
- }
-
- //setting execute label for everything with permission to execute
- ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
- return ret;
-}
-
-static int app_uninstall_remove_early_rules(const char *app_id)
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
- __func__, app_id);
-
- int ret;
- int fd AUTO_CLOSE;
- int size;
- char tmp;
- char *data, *data_end;
- char *line_begin, *line_end, *write_pos;
- char subject[SMACK_LABEL_LEN + 1];
- char object[SMACK_LABEL_LEN + 1];
-
- SECURE_C_LOGD("Opening file %s.", SMACK_STARTUP_RULES_FILE);
- fd = open(SMACK_STARTUP_RULES_FILE, O_RDWR);
- if (fd < 0) {
- SECURE_C_LOGE("Unable to open file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
- return PC_ERR_FILE_OPERATION;
- }
-
- if (flock(fd, LOCK_EX)) {
- SECURE_C_LOGE("flock failed, error %s", strerror(errno));
- return PC_ERR_FILE_OPERATION;
- }
-
- size = lseek(fd, 0, SEEK_END);
- if (size < 0) {
- SECURE_C_LOGE("Unable to read file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
- return PC_ERR_FILE_OPERATION;
- }
-
- if (size == 0)
- return PC_OPERATION_SUCCESS;
-
- data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (data == MAP_FAILED) {
- SECURE_C_LOGE("Unable to read file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
- return PC_ERR_FILE_OPERATION;
- }
- data_end = data + size;
-
- line_begin = write_pos = data;
- while (line_begin < data_end) {
- line_end = memchr(line_begin, '\n', data_end - line_begin);
- if (line_end == NULL)
- line_end = data_end - 1;
-
- tmp = *line_end;
- *line_end = '\0';
- SECURE_C_LOGD("Considering early rule: %s", line_begin);
-
- ret = sscanf(line_begin, "%" TOSTRING(SMACK_LABEL_LEN) "s %" TOSTRING(SMACK_LABEL_LEN) "s", subject, object);
- if (ret != 2) {
- C_LOGD("Rule format is invalid, skipping it.");
- goto loop_next;
- }
-
- if (!strcmp(subject, app_id) || !strcmp(object, app_id)) {
- C_LOGD("Rule belongs to an app being removed, skipping it.");
- goto loop_next;
- }
-
- C_LOGD("Rule still needed, keeping it.");
- *line_end = tmp;
- if (write_pos != line_begin)
- memcpy(write_pos, line_begin, line_end - line_begin + 1);
- write_pos += (line_end - line_begin + 1);
-
- loop_next:
- *line_end = tmp;
- line_begin = line_end + 1;
- }
-
- munmap(data, size);
- ret = ftruncate(fd, write_pos - data);
- if (ret < 0) {
- SECURE_C_LOGE("Unable to truncate file %s to %d bytes: %s", SMACK_STARTUP_RULES_FILE, write_pos, strerror(errno));
-
- return PC_ERR_FILE_OPERATION;
- }
-
- return PC_OPERATION_SUCCESS;
-}
-
-API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
-{
- SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
- __func__, app_label, shared_label, path);
- int ret;
-
- if(path == NULL) {
- C_LOGE("Invalid param path.");
- return PC_ERR_INVALID_PARAM;
- }
+ if(path == NULL) {
+ C_LOGE("Invalid param path.");
+ return PC_ERR_INVALID_PARAM;
+ }
if(!smack_label_is_valid(app_label)) {
C_LOGE("Invalid param app_label");
return ret;
}
- ret = app_add_rule(app_label, shared_label, "rwxat");
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_add_rule failed");
- return ret;
- }
-
return PC_OPERATION_SUCCESS;
}
-API int add_shared_dir_readers(const char* shared_label, const char** app_list)//deprecated
+API int add_shared_dir_readers(const char* shared_label UNUSED, const char** app_list UNUSED)//deprecated
{
SECURE_C_LOGD("Entering function: %s. Params: shared_label=%s",
__func__, shared_label);
- int ret;
- int i;
-
- if(app_list == NULL) {
- C_LOGE("Invalid param app_list.");
- return PC_ERR_INVALID_PARAM;
- }
-
- if (!smack_label_is_valid(shared_label)) {
- C_LOGE("Invalid param shared_label.");
- return PC_ERR_INVALID_PARAM;
- }
- for (i = 0; app_list[i] != NULL; i++) {
- if (!smack_label_is_valid(app_list[i])) {
- C_LOGE("Invalid %d element from param app_list.", i);
- return PC_ERR_INVALID_PARAM;
- }
-
- ret = app_add_rule(app_list[i], shared_label, "rx");
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_add_rule failed.");
- return ret;
- }
- }
+ C_LOGE("add_shared_dir_readers is deprecated and unimplemented!");
- return PC_OPERATION_SUCCESS;
+ // TODO: This function is not implemented with RDB.
+ return PC_ERR_INVALID_OPERATION;
}
static char* smack_label_for_path(const char *app_id, const char *path)
return label;
}
-/*
- * This function should be called in perm_app_setup_path_internal().
- * After installation of new application (pkg_id) and labeling its shared directory (RW or RO),
- * all others apps installed on system should get rules to this shared directory.
- * This function will add and store those rules in rule-file of new installed app (pkg_id)
- */
-static int add_other_apps_rules_for_shared_dir(const char *pkg_id, const char *type_of_shared_dir, const char *shared_dir_label)
-{
- C_LOGD("Enter function: %s", __func__);
-
- int ret;
- int fd AUTO_CLOSE;
- char *smack_path AUTO_FREE;
- char *smack_rules_file_path AUTO_FREE;
- struct smack_accesses* smack AUTO_SMACK_FREE;
-
- ret = load_smack_from_file(pkg_id, &smack, &fd, &smack_path);
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("load_smack_from_file failed: %d", ret);
- return ret;
- }
-
- ret = asprintf(&smack_rules_file_path, TOSTRING(SHAREDIR)"/%s", type_of_shared_dir);
- if (ret < 0) {
- C_LOGE("asprintf failed");
- return PC_ERR_MEM_OPERATION;
- }
-
- ret = perm_to_smack_from_file(smack, shared_dir_label, SMACK_SHARED_DIR_LABEL_TEMPLATE, smack_rules_file_path);
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("perm_to_smack_from_file failed: %d", ret);
- }
-
- if (have_smack() && smack_accesses_apply(smack)) {
- C_LOGE("smack_accesses_apply failed");
- return PC_ERR_INVALID_OPERATION;
- }
-
- if (smack_accesses_save(smack, fd)) {
- C_LOGE("smack_accesses_save failed");
- return PC_ERR_INVALID_OPERATION;
- }
-
- return PC_OPERATION_SUCCESS;
-}
-
-/* Add all anti-viruses RWX access to specific label.
- * This function should be used grant anti-viruses access to
- * public RO/group RW shared folder
- * const char *path param is used only for logs.
- */
-static int add_all_anti_viruses_access_to_label(const char *label, const char *path)
-{
- int i;
- int ret;
- int avs_ids_cnt = 0;
- char **avs_ids AUTO_FREE;
-
- /* Add all anti-viruses RWX access to public RO shared folder */
- ret = get_all_avs_ids(&avs_ids, &avs_ids_cnt);
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("get_all_avs_ids failed.");
- return ret;
- }
- for (i = 0; i < avs_ids_cnt; ++i) {
- SECURE_C_LOGD("Allowing anti-virus %s to RWX access public path %s", avs_ids[i], path);
- ret = app_add_rule(avs_ids[i], label, "rwx");
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("app_add_rule failed");
- while (i < avs_ids_cnt)
- free(avs_ids[i++]);
- return ret;
- }
- free(avs_ids[i]);
- }
-
- return PC_OPERATION_SUCCESS;
-}
/* FIXME: remove this pragma once deprecated API is deleted */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return PC_ERR_INVALID_PARAM;
}
- ret = app_label_shared_dir(pkg_id, shared_label, path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_label_shared_dir failed: %d", ret);
- return ret;
- }
-
- /* FIXME: This should be in some kind of transaction/lock */
- ret = db_add_groups_dir(shared_label);
+ // Add the path to the database:
+ ret = rdb_add_path(pkg_id, shared_label, path, "rwxatl", "GROUP_RW");
if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("db_add_groups_dir failed.");
+ C_LOGE("RDB rdb_add_path failed with: %d", ret);
return ret;
}
- /* Add all anti-viruses RWX access to groups RW shared folder */
- ret = add_all_anti_viruses_access_to_label(shared_label, path);
+ ret = app_label_shared_dir(pkg_id, shared_label, path);
if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("add_all_anti_viruses_access_to_label failed");
+ C_LOGE("app_label_shared_dir failed: %d", ret);
return ret;
}
- return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_GROUP_RW, shared_label);
+ return PC_OPERATION_SUCCESS;
}
case APP_PATH_PUBLIC_RO: {
C_LOGD("app_path_type is APP_PATH_PUBLIC_RO.");
char **app_ids AUTO_FREE;
- int app_ids_cnt = 0;
const char *label;
- int i, ret;
+ int ret;
C_LOGD("New public RO path %s", path);
+
+ // Generate label:
label = smack_label_for_path(pkg_id, path);
if (label == NULL) {
C_LOGE("smack_label_for_path failed.");
return PC_ERR_INVALID_OPERATION;
}
-
C_LOGD("Generated label '%s' for public RO path %s", label, path);
- ret = app_label_shared_dir(pkg_id, label, path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_label_shared_dir failed.");
- return ret;
- }
-
- /* FIXME: This should be in some kind of transaction/lock */
- ret = db_add_public_dir(label);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("db_add_public_dir failed.");
- return ret;
- }
- ret = get_all_apps_ids(&app_ids, &app_ids_cnt);
+ // Add the path to the database:
+ ret = rdb_add_path(pkg_id, label, path, "rwxatl", "PUBLIC_RO");
if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("get_all_aps_ids failed.");
+ C_LOGE("RDB rdb_add_path failed with: %d", ret);
return ret;
}
- for (i = 0; i < app_ids_cnt; ++i) {
- SECURE_C_LOGD("Allowing app %s to access public path %s", app_ids[i], path);
- ret = app_add_rule(app_ids[i], label, "rx");
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_add_rule failed");
- while (i < app_ids_cnt)
- free(app_ids[i++]);
- return ret;
- }
- free(app_ids[i]);
- }
-
- /* Add all anti-viruses RWX access to public RO shared folder */
- ret = add_all_anti_viruses_access_to_label(label, path);
+ ret = app_label_shared_dir(pkg_id, label, path);
if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("add_all_anti_viruses_access_to_label failed");
+ C_LOGE("app_label_shared_dir failed.");
return ret;
}
-
- return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_PUBLIC_RO, label);
+ return PC_OPERATION_SUCCESS;
}
- case APP_PATH_SETTINGS_RW:
- {
+ case APP_PATH_SETTINGS_RW: {
C_LOGD("app_path_type is APP_PATH_SETTINGS_RW.");
char **app_ids AUTO_FREE;
- int app_ids_cnt = 0;
const char *label;
- int i;
int ret;
- /*get path id*/
+ // Generate label:
label = smack_label_for_path(pkg_id, path);
if (label == NULL) {
C_LOGE("smack_label_for_path failed.");
return PC_ERR_INVALID_OPERATION;
}
-
- /*set id for path and all subfolders*/
C_LOGD("Appsetting: generated label '%s' for setting path %s", label, path);
- ret = app_label_shared_dir(pkg_id, label, path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
- return ret;
- }
- /* add path to database */
- /* FIXME: This should be in some kind of transaction/lock */
- ret = add_setting_dir_id_to_databse(label);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("Appsetting: add_setting_dir_id_to_databse failed");
- return ret;
- }
- /*read all apps with appsetting privilege*/
- ret = get_all_appsetting_ids(&app_ids, &app_ids_cnt);
+ // Add the path to the database:
+ ret = rdb_add_path(pkg_id, label, path, "rwxatl", "SETTINGS_RW");
if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("Appsetting: get_all_appsetting_ids failed");
+ C_LOGE("RDB rdb_add_path failed with: %d", ret);
return ret;
}
- C_LOGD("Appsetting: %d appsetting privileged apps registered",
- app_ids_cnt);
-
- /*give RWX rights to all apps that have appsetting privilege*/
- for (i = 0; i < app_ids_cnt; ++i) {
- C_LOGD("Appsetting: allowing app %s to access setting path %s",
- app_ids[i], label);
- ret = app_add_rule(app_ids[i], label, "rwx");
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_add_rule failed");
- while (i < app_ids_cnt)
- free(app_ids[i++]);
- return ret;
- }
- free(app_ids[i]);
- }
- /* Add all anti-viruses RWX access to settings RW shared folder */
- ret = add_all_anti_viruses_access_to_label(label, path);
+ /*set id for path and all subfolders*/
+ ret = app_label_shared_dir(pkg_id, label, path);
if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("add_all_anti_viruses_access_to_label failed");
+ C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
return ret;
}
-
return PC_OPERATION_SUCCESS;
}
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
{
SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
__func__, pkg_id);
-
int ret;
int fd AUTO_CLOSE;
char* smack_path AUTO_FREE;
struct smack_accesses *smack AUTO_SMACK_FREE;
- if (!smack_label_is_valid(pkg_id)) {
- C_LOGE("Invalid param pkg_id.");
- return PC_ERR_INVALID_PARAM;
- }
-
- ret = smack_file_name(pkg_id, &smack_path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("smack_file_name failed.");
- return ret;
- }
-
- ret = load_smack_from_file(pkg_id, &smack, &fd, &smack_path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("load_smack_from_file failed");
- return ret;
- }
-
- ret = add_app_id_to_databse(pkg_id);
- if (ret != PC_OPERATION_SUCCESS ) {
- SECURE_C_LOGE("Error while adding app %s to database: %s ", pkg_id, strerror(errno));
- return ret;
- }
-
- ret = register_app_for_av(pkg_id);
- if (ret != PC_OPERATION_SUCCESS) {
- SECURE_C_LOGE("Error while adding rules for anti viruses to app %s: %s ", pkg_id, strerror(errno));
+ ret = perm_modification_start();
+ if(ret != PC_OPERATION_SUCCESS) {
+ C_LOGE("RDB perm_modification_start failed with: %d", ret);
return ret;
}
- ret = register_app_for_appsetting(pkg_id);
- if (ret != PC_OPERATION_SUCCESS) {
- SECURE_C_LOGE("Error while adding rules for setting managers to app %s: %s ", pkg_id, strerror(errno));
- return ret;
+ if (!smack_label_is_valid(pkg_id)) {
+ C_LOGE("Invalid param pkg_id.");
+ return PC_ERR_INVALID_PARAM;
}
- ret = register_app_for_public_dirs(pkg_id, smack);
+ // Add application to the database:
+ ret = rdb_add_application(pkg_id);
if (ret != PC_OPERATION_SUCCESS) {
- SECURE_C_LOGE("Error while adding rules for access to public dirs for app %s: %s ", pkg_id, strerror(errno));
+ C_LOGE("RDB rdb_add_application failed with: %d", ret);
return ret;
}
- if (have_smack() && smack_accesses_apply(smack)) {
- C_LOGE("smack_accesses_apply failed");
- return PC_ERR_INVALID_OPERATION;
- }
-
- if (smack_accesses_save(smack, fd)) {
- C_LOGE("smack_accesses_save failed");
- return PC_ERR_INVALID_OPERATION;
- }
-
return PC_OPERATION_SUCCESS;
}
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;
return PC_ERR_INVALID_PARAM;
}
- ret = smack_file_name(pkg_id, &smack_path);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("smack_file_name failed.");
- return ret;
- }
-
- if (unlink(smack_path)) {
- C_LOGE("unlink failed (error: %s)", strerror(errno));
- return PC_OPERATION_SUCCESS;
- }
-
- ret = app_uninstall_remove_early_rules(pkg_id);
+ // Remove application from the database
+ ret = rdb_remove_application(pkg_id);
if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("app_uninstall_remove_early_rules failed.");
+ C_LOGE("RDB rdb_remove_application failed with: %d", ret);
return ret;
}
return PC_OPERATION_SUCCESS;
}
-static int save_rules(int fd, struct smack_accesses* accesses) {
- SECURE_C_LOGD("Entering function: %s. Params: fd=%d", __func__, fd);
-
- if (flock(fd, LOCK_EX)) {
- C_LOGE("flock failed (error: %s)", strerror(errno));
- return PC_ERR_FILE_OPERATION;
- }
-
- if (smack_accesses_save(accesses, fd)) {
- C_LOGE("smack_accesses_save failed");
- return PC_ERR_FILE_OPERATION;
- }
- return PC_OPERATION_SUCCESS ;
-}
-
-static int label_valid(const char *label) {
- if (label == NULL)
- return 0;
-
- // allow ~APP~ template when adding new feature
- if (strcmp(label, SMACK_APP_LABEL_TEMPLATE) == 0)
- return 1;
-
- return smack_label_is_valid(label);
-}
-
-static int validate_and_add_rule(char* rule, struct smack_accesses* accesses) {
- SECURE_C_LOGD("Entering function: %s. Params: rule=%s",
- __func__, rule);
-
- const char* subject = NULL;
- const char* object = NULL;
- const char* access = NULL;
- char* saveptr = NULL;
-
- subject = strtok_r(rule, " \t\n", &saveptr);
- object = strtok_r(NULL, " \t\n", &saveptr);
- access = strtok_r(NULL, " \t\n", &saveptr);
-
- // check rule validity
- if (access == NULL ||
- strtok_r(NULL, " \t\n", &saveptr) != NULL ||
- !label_valid(subject) ||
- !label_valid(object))
- {
- C_LOGE("Incorrect rule format: %s", rule);
- return PC_ERR_INVALID_PARAM;
- }
-
- if (smack_accesses_add(accesses, subject, object, access)) {
- C_LOGE("smack_accesses_add failed");
- return PC_ERR_INVALID_OPERATION;
- }
- return PC_OPERATION_SUCCESS ;
-}
-
-static int parse_and_save_rules(const char** smack_rules,
- struct smack_accesses* accesses, const char* feature_file) {
- SECURE_C_LOGD("Entering function: %s. Params: feature_file=%s",
- __func__, feature_file);
-
- size_t i = 0;
- int fd = 0;
- int ret = PC_OPERATION_SUCCESS;
- char* tmp = NULL;
-
- for (i = 0; smack_rules[i] != NULL ; i++) {
- // ignore empty lines
- if (strspn(smack_rules[i], " \t\n") == strlen(smack_rules[i]))
- continue;
-
- tmp = strdup(smack_rules[i]);
- ret = validate_and_add_rule(tmp, accesses);
- free(tmp);
- if (ret != PC_OPERATION_SUCCESS )
- return ret;
- }
-
- // save to file
- fd = open(feature_file, O_CREAT | O_WRONLY, 0644);
- if (fd == -1) {
- SECURE_C_LOGE("Unable to create file %s. (error: %s)", feature_file, strerror(errno));
- return PC_ERR_FILE_OPERATION;
- }
-
- ret = save_rules(fd, accesses);
- close(fd);
- return ret;
-}
-
static int save_gids(FILE* file, const gid_t* list_of_db_gids, size_t list_size) {
+
SECURE_C_LOGD("Entering function: %s.", __func__);
int ret = PC_OPERATION_SUCCESS;
int written = 0;
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
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
SECURE_C_LOGD("Opening file %s.", dac_file);
file = fopen(dac_file, "w+");
ret = save_gids(file, list_of_db_gids, list_size);
- fclose(file);
+ if(file) fclose(file);
+ }
+
+ // remove file in case of failure
+ if (ret != PC_OPERATION_SUCCESS && dac_file) {
+ unlink(dac_file);
+ }
+
+ ret = base_name_from_perm(api_feature_name, &base_api_feature_name);
+ if (ret != PC_OPERATION_SUCCESS){
+ C_LOGE("Error during creating base name: ", ret);
+ return ret;
}
- // remove both files in case of failure
+ // Save api feature to the database.
+ ret = rdb_add_permission_rules(base_api_feature_name, s_type_name, smack_rules);
if (ret != PC_OPERATION_SUCCESS) {
- unlink(smack_file);
- if (dac_file) {
- unlink(dac_file);
- }
+ C_LOGE("RDB rdb_add_permission_rules failed with: %d", ret);
+ return ret;
}
return ret;
/**
* This function is marked as deprecated and will be removed
*/
-API int app_register_av(const char* app_av_id)//deprecated
+API int app_register_av(const char* app_av_id UNUSED)//deprecated
{
SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s",
__func__, app_av_id);
- int ret;
- int fd AUTO_CLOSE;
- char* smack_path AUTO_FREE;
- struct smack_accesses* smack AUTO_SMACK_FREE;
-
- if(app_av_id == NULL) {
- C_LOGE("Invalid param app_av_id.");
- return PC_ERR_INVALID_PARAM;
- }
-
- ret = load_smack_from_file(app_av_id, &smack, &fd, &smack_path);
- if (ret != PC_OPERATION_SUCCESS ) {
- C_LOGE("load_smack_from_file failed");
- return ret;
- }
-
- ret = app_register_av_internal(app_av_id, smack);
- if (PC_OPERATION_SUCCESS != ret) {
- C_LOGE("app_register_av_internal failed");
- return ret;
- }
-
- // Add permisions from OSP_antivirus.smack file
- ret = perm_to_smack(smack, app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
- if (PC_OPERATION_SUCCESS != ret) {
- C_LOGE("perm_to_smack failed");
- return ret;
- }
-
- // Add permisions from OSP_antivirus.dac file
- ret = perm_to_dac(app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
- if (ret != PC_OPERATION_SUCCESS) {
- C_LOGE("perm_to_dac failed");
- return ret;
- }
-
- if (have_smack() && smack_accesses_apply(smack)) {
- C_LOGE("smack_accesses_apply failed");
- ret = PC_ERR_INVALID_OPERATION;
- return ret;
- }
-
- if (smack_accesses_save(smack, fd)) {
- C_LOGE("smack_accesses_save failed");
- ret = PC_ERR_INVALID_OPERATION;
- return ret;
- }
+ C_LOGE("app_register_av is deprecated and unimplemented!");
- return ret;
+ // TODO: This function is not implemented with RDB.
+ return PC_ERR_INVALID_OPERATION;
}
--- /dev/null
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+* @file rules-db-internals.c
+* @author Jan Olszak (j.olszak@samsung.com)
+* @version 1.0
+* @brief Definition of internal functions of the rules-db API.
+*/
+
+#include <errno.h> // For error logging
+#include <stdarg.h> // For handling multiple arguments
+#include <stdlib.h> // For free
+#include <stdio.h> // For file manipulation
+#include "common.h" // For smack_label_is_valid
+#include <unistd.h> // For sleep
+
+#include "rules-db-internals.h"
+#include "rules-db.h"
+
+#define RDB_MAX_QUERY_ATTEMPTS 50
+#define RDB_TIME_BETWEEN_ATTEMPTS 1 // sec
+
+
+
+
+/**
+ * Helper function. Use on INSERT or DELETE or UPDATE, when not interested in returned value
+ *
+ * @ingroup RDB: internal functions
+ *
+ * @param p_stmt SQLite3 statement
+ * @return PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+static int step_and_convert_returned_value(sqlite3_stmt *p_stmt)
+{
+ if(sqlite3_step(p_stmt) == SQLITE_DONE) {
+ return PC_OPERATION_SUCCESS;
+ } else {
+ C_LOGE("RDB: Error during stepping: %s",
+ sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
+ return PC_ERR_DB_QUERY_STEP;
+ }
+}
+
+int add_modified_label_internal(sqlite3 *p_db, const char *const s_label_name)
+{
+ int ret = PC_OPERATION_SUCCESS;
+ sqlite3_stmt *p_stmt = NULL;
+ ret = prepare_stmt(p_db, &p_stmt,
+ "INSERT OR IGNORE INTO modified_label(name) VALUES(%Q)",
+ s_label_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+/**
+ * Adds label names of applications with the permission to modified labels.
+ * Used when permission is going to change and we're going to change some
+ * accesses granted by this permission.
+ *
+ *
+ * @param p_db [description]
+ * @param i_permission_id [description]
+ * @return [description]
+ */
+int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id)
+{
+ int ret = PC_OPERATION_SUCCESS;
+ sqlite3_stmt *p_stmt = NULL;
+ ret = prepare_stmt(p_db, &p_stmt,
+ "INSERT INTO modified_label(name) \
+ SELECT app_permission_view.app_name \
+ FROM app_permission_view \
+ WHERE app_permission_view.permission_id = %d",
+ i_permission_id);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+/**
+ * Function called when the target database is busy.
+ * We attempt to access the database every
+ * RDB_TIME_BETWEEN_ATTEMPTS seconds
+ *
+ * @param not_used not used
+ * @param i_attempt number of the attempt
+ * @return 0 when stops waiting
+ * 1 when waiting
+ */
+static int database_busy_handler(void *not_used UNUSED,
+ int i_attempt)
+{
+ if(i_attempt > RDB_MAX_QUERY_ATTEMPTS) {
+ // I ain't gonna wait for you forever!
+ C_LOGE("RDB: Database busy for too long.");
+ return 0;
+ }
+ C_LOGW("RDB: Database busy, waiting");
+ sleep(RDB_TIME_BETWEEN_ATTEMPTS);
+ return 1;
+}
+
+
+int open_rdb_connection(sqlite3 **p_db)
+{
+ RDB_LOG_ENTRY;
+
+ char *p_err_msg;
+
+ // Open connection:
+ int ret = sqlite3_open_v2(RDB_PATH,
+ p_db,
+ RDB_READWRITE_FLAG,
+ NULL);
+ if(*p_db == NULL) {
+ C_LOGE("RDB: Error opening the database: Unable to allocate memory.");
+ return PC_ERR_DB_CONNECTION;
+ }
+ if(ret != SQLITE_OK) {
+ C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
+ return PC_ERR_DB_CONNECTION;
+ }
+
+ //Register busy handler:
+ if(sqlite3_busy_handler(*p_db, database_busy_handler, NULL) != SQLITE_OK) {
+ C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
+ return PC_ERR_DB_CONNECTION;
+ }
+
+ // Load extensions:
+ if(sqlite3_enable_load_extension(*p_db, 1)) {
+ C_LOGE("RDB: Error enabling extensions: %s", sqlite3_errmsg(*p_db));
+ return PC_ERR_DB_CONNECTION;
+ }
+
+ if(sqlite3_load_extension(*p_db,
+ "/usr/lib/librules-db-sql-udf.so", 0,
+ &p_err_msg) != SQLITE_OK) {
+
+ C_LOGE("RDB: Error during loading librules-db-sql-udf.so: %s",
+ p_err_msg);
+ sqlite3_free(p_err_msg);
+ return PC_ERR_DB_CONNECTION;
+ }
+ sqlite3_free(p_err_msg);
+
+
+ // Create the temporary tables:
+ if(sqlite3_exec(*p_db,
+ "CREATE TEMPORARY TABLE history_smack_rule( \
+ subject VARCHAR NOT NULL, \
+ object VARCHAR NOT NULL, \
+ access INTEGER NOT NULL); \
+ \
+ CREATE TEMPORARY TABLE modified_label( \
+ name VARCHAR NOT NULL, \
+ UNIQUE(name)); \
+ \
+ CREATE TEMPORARY TABLE all_smack_binary_rule_modified( \
+ subject VARCHAR NOT NULL, \
+ object VARCHAR NOT NULL, \
+ access INTEGER NOT NULL); \
+ \
+ CREATE TEMPORARY TABLE history_smack_rule_modified( \
+ subject VARCHAR NOT NULL, \
+ object VARCHAR NOT NULL, \
+ access INTEGER NOT NULL); \
+ \
+ CREATE TEMPORARY VIEW modified_smack_rules AS \
+ SELECT subject, object, \
+ access_to_str(access_add) AS access_add, \
+ access_to_str(access_del) AS access_del \
+ FROM ( \
+ SELECT subject, object, \
+ s1.access & ~s2.access AS access_add, \
+ s2.access & ~s1.access AS access_del \
+ FROM all_smack_binary_rule_modified AS s1 \
+ INNER JOIN history_smack_rule_modified AS s2 \
+ USING (subject, object) \
+ WHERE s1.access != s2.access \
+ UNION \
+ SELECT subject, object, \
+ s1.access AS access_add, \
+ 0 AS access_del \
+ FROM all_smack_binary_rule_modified s1 \
+ LEFT JOIN history_smack_rule_modified s2 \
+ USING (subject, object) \
+ WHERE s2.subject IS NULL AND \
+ s2.object IS NULL \
+ UNION \
+ SELECT subject, object, \
+ 0 AS access_add, \
+ s1.access AS access_del \
+ FROM history_smack_rule_modified s1 \
+ LEFT JOIN all_smack_binary_rule_modified s2 \
+ USING (subject, object) \
+ WHERE s2.subject IS NULL AND \
+ s2.object IS NULL \
+ ) \
+ ORDER BY subject, object ASC; \
+ PRAGMA foreign_keys = ON; \
+ ANALYZE;",
+ 0, 0, 0) != SQLITE_OK) {
+ C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
+ return PC_ERR_DB_OPERATION;
+ }
+
+ return PC_OPERATION_SUCCESS;
+}
+
+
+int prepare_stmt(sqlite3 *p_db,
+ sqlite3_stmt **pp_stmt,
+ const char *const s_sql,
+ ...)
+{
+ int ret = PC_ERR_DB_QUERY_PREP;
+ char *s_query = NULL;
+ va_list args;
+ va_start(args, s_sql);
+
+ s_query = sqlite3_vmprintf(s_sql, args);
+
+ if(s_query == NULL) {
+ C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
+ ret = PC_ERR_DB_QUERY_PREP;
+ goto finish;
+ }
+
+ if(sqlite3_prepare_v2(p_db,
+ s_query,
+ strlen(s_query) + 1,
+ pp_stmt,
+ NULL)) {
+ C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_PREP;
+ goto finish;
+ }
+
+ if(*pp_stmt == NULL) {
+ C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
+ ret = PC_ERR_DB_QUERY_PREP;
+ goto finish;
+ }
+
+ ret = PC_OPERATION_SUCCESS;
+
+finish:
+ va_end(args);
+ sqlite3_free(s_query);
+ return ret;
+}
+
+
+int check_app_label_internal(sqlite3 *p_db,
+ const char *const s_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "SELECT COUNT(application_view.name) \
+ FROM application_view \
+ WHERE application_view.name=%Q \
+ LIMIT 1",
+ s_label_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = sqlite3_step(p_stmt);
+ if(ret == SQLITE_ROW) {
+ switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
+ case 0: ret = PC_OPERATION_SUCCESS; break;
+ case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
+ }
+
+ } else {
+ C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_STEP;
+ }
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int check_label_internal(sqlite3 *p_db,
+ const char *const s_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "SELECT COUNT(label.name) \
+ FROM label WHERE name=%Q LIMIT 1",
+ s_label_name);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = sqlite3_step(p_stmt);
+ if(ret == SQLITE_ROW) {
+ switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
+ case 0: ret = PC_OPERATION_SUCCESS; break;
+ case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
+ }
+
+ } else {
+ C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_STEP;
+ }
+
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int add_app_internal(sqlite3 *p_db,
+ const char *const s_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "INSERT into application_view(name) VALUES(%Q)",
+ s_label_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int remove_app_internal(sqlite3 *p_db,
+ const char *const s_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "DELETE FROM application_view \
+ WHERE application_view.name=%Q",
+ s_label_name);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int add_path_internal(sqlite3 *p_db,
+ const char *const s_owner_label_name,
+ const char *const s_path_label_name,
+ const char *const s_path,
+ const char *const s_access,
+ const char *const s_type)
+{
+ RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
+ s_owner_label_name, s_path_label_name,
+ s_path, s_access, s_type);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "INSERT INTO path_view(owner_app_label_name, \
+ path, \
+ path_label_name, \
+ access, \
+ path_type_name) \
+ VALUES(%Q, %Q, %Q, %Q, %Q);",
+ s_owner_label_name, s_path,
+ s_path_label_name, s_access, s_type);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int check_permission_internal(sqlite3 *p_db,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "SELECT COUNT(SELECT permission_view.permission_id \
+ FROM permission_view \
+ WHERE name=%Q AND \
+ type_name=%Q \
+ LIMIT 1)",
+ s_permission_name, s_permission_type_name);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = sqlite3_step(p_stmt);
+ if(ret == SQLITE_ROW) {
+ switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
+ case 0: ret = PC_OPERATION_SUCCESS; break; // No such permission
+ case 1: ret = PC_PERMISSION_EXISTS; break; // Permission exists
+ }
+
+ } else {
+ C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_STEP;
+ }
+
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int add_permission_internal(sqlite3 *p_db,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "INSERT INTO permission_view(name, type_name) \
+ VALUES (%Q,%Q)",
+ s_permission_name, s_permission_type_name);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int get_permission_id_internal(sqlite3 *p_db,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ sqlite3_int64 *p_permission_id)
+{
+ RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "SELECT permission_view.permission_id \
+ FROM permission_view \
+ WHERE permission_view.name = %Q AND \
+ permission_view.type_name = %Q \
+ LIMIT 1",
+ s_permission_name, s_permission_type_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = sqlite3_step(p_stmt);
+ if(ret == SQLITE_ROW) {
+ ret = PC_OPERATION_SUCCESS;
+ *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
+ } else if(ret == SQLITE_DONE) {
+ C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
+ ret = PC_ERR_DB_OPERATION;
+
+ } else {
+ C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_STEP;
+ }
+
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+
+ return ret;
+}
+
+
+int parse_rule(const char *const s_rule,
+ char s_subject[],
+ char s_object[],
+ char s_access[])
+{
+ int ret = PC_OPERATION_SUCCESS;
+ char *tmp_s_rule = NULL;
+ const char *tmp_s_subject = NULL;
+ const char *tmp_s_object = NULL;
+ const char *tmp_s_access = NULL;
+ char *saveptr = NULL;
+
+ // Parse subject, object and access:
+ tmp_s_rule = strdup(s_rule);
+ tmp_s_subject = strtok_r(tmp_s_rule, " \t\n", &saveptr);
+ tmp_s_object = strtok_r(NULL, " \t\n", &saveptr);
+ tmp_s_access = strtok_r(NULL, " \t\n", &saveptr);
+
+ // Check rule validity:
+ if(tmp_s_subject == NULL ||
+ tmp_s_object == NULL ||
+ tmp_s_access == NULL ||
+ strtok_r(NULL, " \t\n", &saveptr) != NULL) {
+ C_LOGE("RDB: Incorrect rule format: %s", s_rule);
+ ret = PC_ERR_INVALID_PARAM;
+ goto finish;
+ }
+
+ // Copy rules
+ strcpy(s_subject, tmp_s_subject);
+ strcpy(s_object, tmp_s_object);
+ strcpy(s_access, tmp_s_access);
+finish:
+ if(tmp_s_rule) free(tmp_s_rule);
+ return ret;
+}
+
+
+int add_permission_rules_internal(sqlite3 *p_db,
+ sqlite3_int64 permission_id,
+ const char *const *const pp_smack_rules)
+{
+ RDB_LOG_ENTRY;
+
+ int i;
+ int ret = PC_OPERATION_SUCCESS;
+ sqlite3_stmt *p_stmt = NULL;
+ char s_subject[SMACK_LABEL_LEN + 1];
+ char s_object[SMACK_LABEL_LEN + 1];
+ char s_access[ACC_LEN + 1];
+
+ // Prepare statement.
+ const char *s_query = "INSERT INTO \
+ permission_label_rule_view(permission_id,access,label_name,is_reverse) \
+ VALUES(?,?,?,?)";
+ if(sqlite3_prepare_v2(p_db,
+ s_query,
+ strlen(s_query) + 1,
+ &p_stmt,
+ NULL)) {
+ C_LOGE("RDB: Error during preparing statement: %s",
+ sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_PREP;
+ goto finish;
+ }
+
+ for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
+ C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
+
+ // Ignore empty lines
+ if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
+ continue;
+
+ ret = parse_rule(pp_smack_rules[i], s_subject, s_object, s_access);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ // Bind values to the statement and run it:
+ sqlite3_bind_int(p_stmt, 1, permission_id);
+ sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0);
+ if(!strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE)) {
+ // Not reversed
+ sqlite3_bind_text(p_stmt, 3, s_object, RDB_AUTO_DETERM_SIZE, 0);
+ sqlite3_bind_int(p_stmt, 4, 0);
+
+ } else if(!strcmp(s_object, SMACK_APP_LABEL_TEMPLATE)) {
+ sqlite3_bind_text(p_stmt, 3, s_subject, RDB_AUTO_DETERM_SIZE, 0);
+ sqlite3_bind_int(p_stmt, 4, 1);
+
+ } else {
+ C_LOGE("RDB: Incorrect rule format: %s", pp_smack_rules[i]);
+ ret = PC_ERR_INVALID_PARAM;
+ goto finish;
+ }
+
+ // Perform the insert
+ ret = step_and_convert_returned_value(p_stmt);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ // Reset and unbind statement:
+ if(sqlite3_reset(p_stmt) != SQLITE_OK) {
+ C_LOGE("RDB: Error reseting statement: %s",
+ sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_STEP;
+ goto finish;
+ }
+ if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
+ C_LOGE("RDB: Error reseting statement: %s",
+ sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_STEP;
+ goto finish;
+ }
+ }
+
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int get_app_id_internal(sqlite3 *p_db,
+ int *pi_app_id,
+ const char *const s_app_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "SELECT application_view.app_id \
+ FROM application_view \
+ WHERE application_view.name = %Q",
+ s_app_label_name);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = sqlite3_step(p_stmt);
+ if(ret == SQLITE_ROW) {
+ ret = PC_OPERATION_SUCCESS;
+ *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
+
+ } else if(ret == SQLITE_DONE) {
+ C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
+ ret = PC_ERR_DB_OPERATION;
+
+ } else {
+ C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_STEP;
+ }
+
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int add_app_permission_internal(sqlite3 *p_db,
+ int i_app_id,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ const bool b_is_volatile_new,
+ const bool b_is_enabled_new)
+{
+ RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
+ s_permission_name, s_permission_type_name,
+ b_is_volatile_new, b_is_enabled_new);
+
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "INSERT INTO \
+ app_permission_view(app_id, name, type_name, \
+ is_volatile, is_enabled) \
+ VALUES(%d,%Q,%Q,%d,%d)",
+ i_app_id, s_permission_name, s_permission_type_name,
+ (int)b_is_volatile_new, (int)b_is_enabled_new);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int switch_app_permission_internal(sqlite3 *p_db,
+ const int i_app_id,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ const bool b_is_enabled_new)
+{
+ RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
+ s_permission_name, s_permission_type_name,
+ b_is_enabled_new);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "UPDATE app_permission_view \
+ SET is_enabled=%d \
+ WHERE app_id = %d AND \
+ name =%Q AND \
+ type_name=%Q",
+ b_is_enabled_new, i_app_id,
+ s_permission_name, s_permission_type_name);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int update_app_permission_internal(sqlite3 *p_db,
+ const int i_app_id,
+ const int i_permission_id,
+ const bool b_is_volatile_new,
+ const bool b_is_enabled_new)
+{
+ RDB_LOG_ENTRY_PARAM("%d %d %d %d",
+ i_app_id, i_permission_id,
+ b_is_volatile_new, b_is_enabled_new);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "UPDATE app_permission \
+ SET is_volatile = %d, is_enabled=%d \
+ WHERE app_id = %d AND permission_id = %d",
+ b_is_volatile_new, b_is_enabled_new,
+ i_app_id, i_permission_id);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int change_app_permission_internal(sqlite3 *p_db,
+ int i_app_id,
+ const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ int i_is_volatile_new,
+ int i_is_enabled_new)
+{
+ RDB_LOG_ENTRY_PARAM("%d %d %d %d %d", i_app_id,
+ s_permission_name, s_permission_type_name,
+ i_is_volatile_new, i_is_enabled_new);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+ int i_is_volatile_old, i_is_enabled_old, i_permission_id;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "SELECT is_volatile, is_enabled, permission_id \
+ FROM app_permission_list_view \
+ WHERE app_id = %d AND \
+ permission_name=%Q AND \
+ permission_type_name=%Q LIMIT 1",
+ i_app_id, s_permission_name, s_permission_type_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = sqlite3_step(p_stmt);
+ if(ret == SQLITE_ROW) {
+ // Phi, I already have this permission...
+ i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
+ i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
+
+ if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
+ // Confucius say, No man can down-cast volatility.
+ C_LOGE("RDB: Down-casting volatility is forbidden.");
+ ret = PC_ERR_DB_PERM_FORBIDDEN;
+ goto finish;
+ }
+
+ if(i_is_volatile_old == i_is_volatile_new &&
+ i_is_enabled_old == i_is_enabled_new) {
+ // There is no change. Nice.
+ C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
+ ret = PC_OPERATION_SUCCESS;
+ goto finish;
+ }
+
+ i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
+
+ // Finalize statement
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ p_stmt = NULL;
+
+ C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
+ ret = update_app_permission_internal(p_db,
+ i_app_id,
+ i_permission_id,
+ i_is_volatile_new,
+ i_is_enabled_new);
+
+ } else if(ret == SQLITE_DONE) {
+ // Wow! A brand new permission! Omnomnom...
+
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ p_stmt = NULL;
+
+ C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
+ ret = add_app_permission_internal(p_db,
+ i_app_id,
+ s_permission_name,
+ s_permission_type_name,
+ i_is_volatile_new,
+ i_is_enabled_new);
+ } else {
+ C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_QUERY_STEP;
+ }
+
+finish:
+ if(p_stmt && sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int revoke_app_permissions_internal(sqlite3 *p_db,
+ const char *const s_app_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "DELETE FROM app_permission_view \
+ WHERE app_permission_view.app_name=%Q;",
+ s_app_label_name);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int reset_app_permissions_internal(sqlite3 *p_db,
+ const char *const s_app_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3_stmt *p_stmt = NULL;
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "DELETE FROM app_permission_volatile_view \
+ WHERE app_permission_volatile_view.app_name=%Q;",
+ s_app_label_name);
+
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = step_and_convert_returned_value(p_stmt);
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+ return ret;
+}
+
+
+int save_smack_rules(sqlite3 *p_db)
+{
+ RDB_LOG_ENTRY;
+
+ if(sqlite3_exec(p_db,
+ "DELETE FROM history_smack_rule",
+ 0, 0, 0) != SQLITE_OK) {
+ C_LOGE("RDB: Error during clearing history table: %s",
+ sqlite3_errmsg(p_db));
+ return PC_ERR_DB_OPERATION;
+ }
+ if(sqlite3_exec(p_db,
+ "INSERT INTO history_smack_rule \
+ SELECT subject, object, access \
+ FROM all_smack_binary_rules",
+ 0, 0, 0) != SQLITE_OK) {
+ C_LOGE("RDB: Error during inserting into history_smack_rule table: %s",
+ sqlite3_errmsg(p_db));
+ return PC_ERR_DB_OPERATION;
+ }
+
+ // TODO: Maybe don't use index?
+ if(sqlite3_exec(p_db,
+ "CREATE INDEX history_smack_rule_subject_object_index \
+ ON history_smack_rule(subject, object)",
+ 0, 0, 0) != SQLITE_OK) {
+ C_LOGE("RDB: Error during indexing history_smack_rule table: %s",
+ sqlite3_errmsg(p_db));
+ return PC_ERR_DB_OPERATION;
+ }
+ return PC_OPERATION_SUCCESS;
+}
+
+
+static int update_rules_in_db(sqlite3 *p_db)
+{
+ RDB_LOG_ENTRY;
+
+ // All rules generated by the present state of the database
+ if(sqlite3_exec(p_db,
+ "DELETE FROM all_smack_binary_rules; \
+ \
+ INSERT INTO all_smack_binary_rules \
+ SELECT subject, object, access, is_volatile \
+ FROM all_smack_binary_rules_view; \
+ \
+ DELETE FROM all_smack_binary_rule_modified; \
+ \
+ INSERT INTO all_smack_binary_rule_modified \
+ SELECT subject, object, access \
+ FROM all_smack_binary_rules, \
+ modified_label \
+ WHERE subject IN modified_label OR \
+ object IN modified_label; \
+ \
+ DELETE FROM history_smack_rule_modified; \
+ \
+ INSERT INTO history_smack_rule_modified \
+ SELECT subject, object, access \
+ FROM history_smack_rule, \
+ modified_label \
+ WHERE subject IN modified_label OR \
+ object IN modified_label; \
+ ",
+ 0, 0, 0) != SQLITE_OK) {
+ C_LOGE("RDB: Error during updating rules: %s",
+ sqlite3_errmsg(p_db));
+ return PC_ERR_DB_OPERATION;
+ }
+ return PC_OPERATION_SUCCESS;
+}
+
+int update_smack_rules(sqlite3 *p_db)
+{
+ RDB_LOG_ENTRY;
+
+ int ret = PC_OPERATION_SUCCESS;
+ sqlite3_stmt *p_stmt = NULL;
+ const unsigned char *s_subject = NULL;
+ const unsigned char *s_object = NULL;
+ const unsigned char *s_access_add = NULL;
+ const unsigned char *s_access_del = NULL;
+ struct smack_accesses *smack = NULL;
+
+ ret = update_rules_in_db(p_db);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ if(smack_accesses_new(&smack)) {
+ C_LOGE("RDB: Error during updating smack rules: smack_accesses_new failed.");
+ ret = PC_ERR_MEM_OPERATION;
+ goto finish;
+ }
+
+ ret = prepare_stmt(p_db, &p_stmt,
+ "SELECT * from modified_smack_rules;");
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ while((ret = sqlite3_step(p_stmt)) == SQLITE_ROW) {
+ s_subject = sqlite3_column_text(p_stmt, RDB_FIRST_COLUMN);
+ s_object = sqlite3_column_text(p_stmt, RDB_SECOND_COLUMN);
+ s_access_add = sqlite3_column_text(p_stmt, RDB_THIRD_COLUMN);
+ s_access_del = sqlite3_column_text(p_stmt, RDB_FOURTH_COLUMN);
+
+ C_LOGD("RDB: Added rule to smack:: %s %s %s %s",
+ s_subject, s_object, s_access_add, s_access_del);
+
+ if(smack_accesses_add_modify(smack,
+ (const char *) s_subject,
+ (const char *) s_object,
+ (const char *) s_access_add,
+ (const char *) s_access_del)) {
+ C_LOGE("RDB: Error during updating smack rules: %s",
+ sqlite3_errmsg(p_db));
+ ret = PC_ERR_INVALID_OPERATION;
+ goto finish;
+ }
+ }
+ if(ret == SQLITE_DONE) {
+ ret = PC_OPERATION_SUCCESS;
+ } else {
+ C_LOGE("RDB: Error during updating smack rules [%d]: %s",
+ ret, sqlite3_errmsg(p_db));
+ ret = PC_ERR_DB_OPERATION;
+ }
+
+ if(smack_accesses_apply(smack)) {
+ C_LOGE("RDB: Error in smack_accesses_apply");
+ ret = PC_ERR_INVALID_OPERATION;
+ }
+
+finish:
+ if(sqlite3_finalize(p_stmt) < 0)
+ C_LOGE("RDB: Error during finalizing statement: %s",
+ sqlite3_errmsg(p_db));
+
+ smack_accesses_free(smack);
+ return ret;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * libprivilege control, rules database
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak <j.olszak@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+* @file rules-db.c
+* @author Jan Olszak (j.olszak@samsung.com)
+* @version 1.0
+* @brief This file contains declaration of the API to rules database.
+*/
+
+#include "rules-db-internals.h"
+
+static sqlite3 *p_db__ = NULL;
+static int i_session_ret_code__ = PC_OPERATION_SUCCESS;
+
+/**
+ * Prepare to modify the database.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param pp_db pointer to a pointer to a SQLite3 database object
+ * @return PC_OPERATION_SUCCESS on success,
+ * error code otherwise
+ */
+static int rdb_begin(sqlite3 **pp_db)
+{
+ RDB_LOG_ENTRY;
+
+ // If rdb_modification_start was called we use a global connection.
+ if(p_db__) {
+ *pp_db = p_db__;
+ return PC_OPERATION_SUCCESS;
+ }
+
+ int ret = open_rdb_connection(pp_db);
+ if(ret != PC_OPERATION_SUCCESS) return ret;
+
+ if(sqlite3_exec(*pp_db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0)
+ != SQLITE_OK) {
+ C_LOGE("RDB: Error during transaction begin: %s",
+ sqlite3_errmsg(*pp_db));
+ return PC_ERR_DB_CONNECTION;
+ }
+
+ if(have_smack()) {
+ ret = save_smack_rules(*pp_db);
+ if(ret != PC_OPERATION_SUCCESS) return ret;
+ }
+
+ return PC_OPERATION_SUCCESS;
+}
+
+
+/**
+ * Finish database modification.
+ * If previous operation returned an error try to rollback changes.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param p_db pointer to a SQLite3 database object
+ * @param ret previous return code
+ */
+static void rdb_end(sqlite3 *p_db, int ret)
+{
+ RDB_LOG_ENTRY;
+
+ if(have_smack()) {
+ if(ret == PC_OPERATION_SUCCESS &&
+ (ret = update_smack_rules(p_db))
+ != PC_OPERATION_SUCCESS) {
+ C_LOGE("RDB: Error updating smack rules");
+ }
+ }
+
+ // Finish transaction
+ C_LOGD("RDB: Closing connection.");
+ if(ret == PC_OPERATION_SUCCESS) {
+ if(sqlite3_exec(p_db, "COMMIT TRANSACTION", 0, 0, 0)
+ != SQLITE_OK) {
+ C_LOGE("RDB: Error during transaction commit: %s",
+ sqlite3_errmsg(p_db));
+ }
+ } else if(ret == PC_ERR_DB_CONNECTION) {
+ /* Life is pointless. I can't even rollback...*/
+ C_LOGE("RDB: No rollback nor commit.");
+ } else if(sqlite3_exec(p_db, "ROLLBACK TRANSACTION", 0, 0, 0)
+ != SQLITE_OK) {
+ C_LOGE("RDB: Error during transaction rollback: %s",
+ sqlite3_errmsg(p_db));
+ }
+
+ if(sqlite3_close(p_db)) {
+ C_LOGE("RDB: Error during closing the database.");
+ }
+}
+
+
+static void update_ret_code(int i_ret)
+{
+ i_session_ret_code__ = i_session_ret_code__ ? i_session_ret_code__ : i_ret;
+}
+
+
+int rdb_modification_start(void)
+{
+ if(p_db__) {
+ // We have to finish the previous session:
+ C_LOGW("RDB: rdb_modification_finish was not called!");
+ rdb_modification_finish();
+ }
+
+ return rdb_begin(&p_db__);
+}
+
+
+void rdb_modification_finish(void)
+{
+ if(p_db__) {
+ rdb_end(p_db__, i_session_ret_code__);
+ p_db__ = NULL;
+ i_session_ret_code__ = PC_OPERATION_SUCCESS;
+ }
+}
+
+
+int rdb_add_application(const char *const s_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3 *p_db = NULL;
+
+ ret = rdb_begin(&p_db);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = check_app_label_internal(p_db, s_label_name);
+ if(ret == PC_ERR_DB_LABEL_TAKEN) {
+ ret = PC_OPERATION_SUCCESS;
+ C_LOGW("RDB: There is an application with label: %s", s_label_name);
+
+ } else if(ret == PC_OPERATION_SUCCESS) {
+ // There is no such label yet.
+ ret = add_app_internal(p_db, s_label_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ }
+
+ ret = add_modified_label_internal(p_db, s_label_name);
+finish:
+ if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+ return ret;
+}
+
+
+int rdb_remove_application(const char *const s_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3 *p_db = NULL;
+
+ ret = rdb_begin(&p_db);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = remove_app_internal(p_db, s_label_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = add_modified_label_internal(p_db, s_label_name);
+finish:
+ if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+ return ret;
+}
+
+
+int rdb_add_path(const char *const s_owner_label_name,
+ const char *const s_path_label_name,
+ const char *const s_path,
+ const char *const s_access,
+ const char *const s_type)
+{
+ RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
+ s_owner_label_name, s_path_label_name,
+ s_path, s_access, s_type);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3 *p_db = NULL;
+
+ ret = rdb_begin(&p_db);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = add_path_internal(p_db,
+ s_owner_label_name,
+ s_path_label_name,
+ s_path,
+ s_access,
+ s_type);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = add_modified_label_internal(p_db, s_path_label_name);
+finish:
+ if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+ return ret;
+}
+
+
+int rdb_add_permission_rules(const char *const s_permission_name,
+ const char *const s_permission_type_name,
+ const char *const *const pp_smack_rules)
+{
+ RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3 *p_db = NULL;
+ sqlite3_int64 permission_id = -1;
+
+ ret = rdb_begin(&p_db);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = add_permission_internal(p_db,
+ s_permission_name,
+ s_permission_type_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = get_permission_id_internal(p_db,
+ s_permission_name,
+ s_permission_type_name,
+ &permission_id);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = add_modified_permission_internal(p_db, permission_id);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ if(pp_smack_rules != NULL) {
+ ret = add_permission_rules_internal(p_db,
+ permission_id,
+ pp_smack_rules);
+ }
+
+finish:
+ if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+ return ret;
+}
+
+
+int rdb_enable_app_permissions(const char *const s_app_label_name,
+ const char *const s_permission_type_name,
+ const char *const *const pp_permissions_list,
+ const bool b_is_volatile)
+{
+ RDB_LOG_ENTRY_PARAM("%s %s %d", s_app_label_name, s_permission_type_name, b_is_volatile);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3 *p_db = NULL;
+ int i;
+ int i_app_id = 0;
+ C_LOGD("RDB: Enabling permissions START");
+
+ ret = rdb_begin(&p_db);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ // Add permissions specific for the permission type:
+ ret = change_app_permission_internal(p_db,
+ i_app_id,
+ s_permission_type_name,
+ s_permission_type_name,
+ b_is_volatile,
+ RDB_ENABLE);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ // Add permissions from the list:
+ for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
+ // Ignore empty lines
+ if(strspn(pp_permissions_list[i], " \t\n")
+ == strlen(pp_permissions_list[i]))
+ continue;
+
+ ret = change_app_permission_internal(p_db,
+ i_app_id,
+ pp_permissions_list[i],
+ s_permission_type_name,
+ b_is_volatile,
+ RDB_ENABLE);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+ }
+
+ ret = add_modified_label_internal(p_db, s_app_label_name);
+finish:
+ if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+ return ret;
+}
+
+
+int rdb_disable_app_permissions(const char *const s_app_label_name,
+ const char *const s_permission_type_name,
+ const char *const *const pp_permissions_list)
+{
+ RDB_LOG_ENTRY_PARAM("%s %s", s_app_label_name, s_permission_type_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3 *p_db = NULL;
+ int i, i_app_id;
+
+ ret = rdb_begin(&p_db);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
+ // Ignore empty lines
+ if(strspn(pp_permissions_list[i], " \t\n")
+ == strlen(pp_permissions_list[i]))
+ continue;
+
+ ret = switch_app_permission_internal(p_db,
+ i_app_id,
+ pp_permissions_list[i],
+ s_permission_type_name,
+ RDB_DISABLE);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+ }
+
+ ret = add_modified_label_internal(p_db, s_app_label_name);
+finish:
+ if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+ return ret;
+}
+
+
+int rdb_revoke_app_permissions(const char *const s_app_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3 *p_db = NULL;
+
+ ret = rdb_begin(&p_db);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = revoke_app_permissions_internal(p_db, s_app_label_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = add_modified_label_internal(p_db, s_app_label_name);
+finish:
+ if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+ return ret;
+}
+
+
+int rdb_reset_app_permissions(const char *const s_app_label_name)
+{
+ RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
+
+ int ret = PC_ERR_DB_OPERATION;
+ sqlite3 *p_db = NULL;
+
+ ret = rdb_begin(&p_db);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = reset_app_permissions_internal(p_db, s_app_label_name);
+ if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+ ret = add_modified_label_internal(p_db, s_app_label_name);
+finish:
+ if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+ return ret;
+}
+
+
+int validate_all_rules(const char *const *const pp_permissions_list)
+{
+ RDB_LOG_ENTRY;
+
+ int i;
+ char s_subject[SMACK_LABEL_LEN + 1];
+ char s_object[SMACK_LABEL_LEN + 1];
+ char s_access[ACC_LEN + 1];
+
+ // Parse and check rules.
+ for(i = 0; pp_permissions_list[i] != NULL; ++i) {
+ // C_LOGE("RDB: Validating rules: %s", pp_permissions_list[i]);
+
+ // Ignore empty lines
+ if(strspn(pp_permissions_list[i], " \t\n")
+ == strlen(pp_permissions_list[i]))
+ continue;
+
+ if(parse_rule(pp_permissions_list[i], s_subject, s_object, s_access)
+ != PC_OPERATION_SUCCESS) {
+ C_LOGE("RDB: Invalid parameter");
+ return PC_ERR_INVALID_PARAM;
+ }
+
+ if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) != 0 &&
+ strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) != 0) {
+ C_LOGE("RDB: There is no " SMACK_APP_LABEL_TEMPLATE " argument in template rule.");
+ return PC_ERR_INVALID_PARAM;
+ }
+
+ if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
+ strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0) {
+ C_LOGE("RDB: Rule with two " SMACK_APP_LABEL_TEMPLATE " has no sense.");
+ return PC_ERR_INVALID_PARAM;
+ }
+
+ // Check the other label
+ if(strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE) == 0 &&
+ !smack_label_is_valid(s_object)) {
+ C_LOGE("RDB: Incorrect object label: %s", s_object);
+ return PC_ERR_INVALID_PARAM;
+ } else if(strcmp(s_object, SMACK_APP_LABEL_TEMPLATE) == 0 &&
+ !smack_label_is_valid(s_subject)) {
+ C_LOGE("RDB: Incorrect subject label: %s", s_subject);
+ return PC_ERR_INVALID_PARAM;
+ }
+ }
+
+ return PC_OPERATION_SUCCESS;
+}
\ No newline at end of file