Adding additional rules.
authorJan Olszak <j.olszak@samsung.com>
Thu, 26 Sep 2013 16:26:19 +0000 (18:26 +0200)
committerJan Olszak <j.olszak@samsung.com>
Fri, 18 Oct 2013 12:40:27 +0000 (14:40 +0200)
[Issue#]       N/A
[Bug/Feature]  New rule patterns in templates.
[Cause]        N/A
[Solution]     Loading rules from ADDITIONAL_RULES.smack
[Verification] Build, install,
               run api_feature_loader --verbose
               confirm rules are in /smack/load2
               reboot
               confirm rules are in /smack/load2

Change-Id: I4cc5a7d0ddd83d9bdff45b61f5ec242d7a9860d6

12 files changed:
api_feature_loader/api_feature_loader.c
db/rules-db.sql
db/rules-db.xml
include/common.h
include/privilege-control.h
include/rules-db-internals.h
include/rules-db.h
packaging/libprivilege-control.spec
src/common.c
src/privilege-control.c
src/rules-db-internals.c
src/rules-db.c

index 9884a6f..c721714 100644 (file)
@@ -38,7 +38,6 @@
 
 
 #define API_FEATURE_LOADER_VERSION "1.0"
-#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__)
 
@@ -122,6 +121,11 @@ int efl_family_filter(const struct dirent *entry)
               has_smack_ext(entry->d_name);
 }
 
+int additional_rules_filter(const struct dirent *entry)
+{
+       return !strcmp(entry->d_name, "ADDITIONAL_RULES.smack");;
+}
+
 void load_rules_from_file(const char *s_rules_file_path,
                          const char *s_permission_name,
                          const app_type_t app_type)
@@ -259,6 +263,7 @@ void load_from_dir(const char  *const s_dir)
        load_permission_family(osp_family_filter, "OSP_", APP_TYPE_OSP, s_dir);
        load_permission_family(efl_family_filter, "EFL_", APP_TYPE_EFL, s_dir);
 
+
        perm_end();
        API_FEATURE_LOADER_LOG("Done.\n");
 }
@@ -304,7 +309,48 @@ void load_from_file(const char  *const s_file_path)
        API_FEATURE_LOADER_LOG("Done.\n");
 }
 
+void load_additional_rules(const char  *const s_rules_file_path)
+{
+       FILE *p_file       = NULL;
+       char *s_rule       = NULL;
+       char **rules_array = NULL;
+       size_t i_num_rules = 0;
+       size_t i           = 0;
+       int ret;
+       vector_t rules_vector;
+
+       API_FEATURE_LOADER_LOG("Loading additional rules from file...\n");
+
+       p_file = fopen(s_rules_file_path, "r");
+       if(!p_file) goto finish;
+
+
+       vector_init(rules_vector);
+       while(getline(&s_rule, &i, p_file) > 0) {
+               vector_push_back_ptr(rules_vector, s_rule);
+               API_FEATURE_LOADER_LOG("Loading rule: %s", s_rule);
+               ++i_num_rules;
+               s_rule = NULL;
+       }
+       vector_push_back_ptr(rules_vector, NULL);
+
+       rules_array = vector_finish(rules_vector);
+
+       ret = perm_add_additional_rules((const char **)rules_array);
+       if(ret != PC_OPERATION_SUCCESS)
+               API_FEATURE_LOADER_LOG("Error %d\n", ret);
+
+finish:
+       if(p_file != NULL) fclose(p_file);
+       if(rules_array != NULL) {
+               for(i = 0; i < i_num_rules; ++i) {
+                       free(rules_array[i]);
+               }
+               vector_free(rules_vector);
+       }
 
+       API_FEATURE_LOADER_LOG("Done.\n");
+}
 
 int main(int argc, char *argv[])
 {
@@ -317,12 +363,16 @@ int main(int argc, char *argv[])
        bool b_load_from_dir = false;
        const char *s_dir_name = NULL;
 
+       bool b_load_additional_rules = false;
+       const char *s_additional_rules_file_name = NULL;
+
        static struct option long_options[] = {
                {"verbose", no_argument,       &i_verbose_flag__,  1},
                {"file",    required_argument, 0, 'f'},
                {"dir",     required_argument, 0, 'd'},
                {"help",    no_argument,       0, 'h'},
                {"version", no_argument,       0, 'v'},
+               {"rules",   required_argument, 0, 'r'},
                {0, 0, 0, 0}
        };
 
@@ -348,12 +398,18 @@ int main(int argc, char *argv[])
                        s_dir_name = optarg;
                        break;
 
+               case 'r':
+                       b_load_additional_rules = true;
+                       s_additional_rules_file_name = optarg;
+                       break;
+
                case 'h':
                        printf("Api feature loader v." API_FEATURE_LOADER_VERSION "\n\n");
                        printf("    Options:\n");
                        printf("        -d,--dir=path        load api-features from the directory\n");
                        printf("        -f,--file=file_name  load api-feature from the file\n");
                        printf("        -h,--help            print this help\n");
+                       printf("        -r,--rules           load additional rules from the file\n");
                        printf("        --verbose            verbose output\n");
                        printf("        -v,--version         show applcation version\n");
 
@@ -378,10 +434,16 @@ int main(int argc, char *argv[])
        }
 
        // Run task
-       if(b_load_from_dir) load_from_dir(s_dir_name);
-       if(b_load_from_file) load_from_file(s_file_name);
-       if(!b_load_from_dir &&
-           !b_load_from_file) load_from_dir(API_FEATURES_DIR);
+       if(b_load_additional_rules)
+               load_additional_rules(s_additional_rules_file_name);
+       if(b_load_from_dir)
+               load_from_dir(s_dir_name);
+       if(b_load_from_file)
+               load_from_file(s_file_name);
+       if(!b_load_additional_rules &&
+           !b_load_from_dir &&
+           !b_load_from_file)
+               load_from_dir(API_FEATURES_DIR);
 
        return 0;
 }
index 54de195..f6f590c 100644 (file)
@@ -103,6 +103,17 @@ CREATE TABLE IF NOT EXISTS permission_app_path_type_rule (
     FOREIGN KEY(app_path_type_id) REFERENCES app_path_type(app_path_type_id)
 );
 
+CREATE TABLE IF NOT EXISTS label_app_path_type_rule (
+    label_id INTEGER NOT NULL,
+    app_path_type_id INTEGER NOT NULL,
+    access INTEGER NOT NULL DEFAULT 0,
+    is_reverse INTEGER NOT NULL  DEFAULT 0,
+
+    PRIMARY KEY (label_id, app_path_type_id, is_reverse),
+
+    FOREIGN KEY(label_id) REFERENCES label(label_id),
+    FOREIGN KEY(app_path_type_id) REFERENCES app_path_type(app_path_type_id)
+);
 
 CREATE TABLE IF NOT EXISTS label (
     label_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
@@ -314,6 +325,58 @@ BEGIN
 END;
 
 
+-- LABEL TO APP PATH TYPE RULE VIEW --------------------------------------------
+DROP VIEW IF EXISTS label_app_path_type_rule_view;
+CREATE VIEW label_app_path_type_rule_view AS
+SELECT
+        label_app_path_type_rule.label_id   AS label_id,
+        label.name                          AS label_name,
+        app_path_type.name                  AS app_path_type_name,
+        label_app_path_type_rule.access     AS access,
+        label_app_path_type_rule.is_reverse AS is_reverse
+FROM    label_app_path_type_rule
+LEFT JOIN label USING(label_id)
+LEFT JOIN app_path_type USING(app_path_type_id);
+
+
+DROP TRIGGER IF EXISTS label_app_path_type_rule_view_insert_trigger;
+CREATE TRIGGER label_app_path_type_rule_view_insert_trigger
+INSTEAD OF INSERT
+ON label_app_path_type_rule_view
+BEGIN
+    INSERT OR IGNORE INTO label(name) VALUES (NEW.label_name);
+
+    INSERT INTO label_app_path_type_rule(label_id,
+                                         app_path_type_id,
+                                         access,
+                                         is_reverse)
+    SELECT      label.label_id,
+                app_path_type.app_path_type_id,
+                str_to_access(NEW.access),
+                NEW.is_reverse
+    FROM        label, app_path_type
+    WHERE       label.name = NEW.label_name AND
+                app_path_type.name = NEW.app_path_type_name;
+END;
+
+
+DROP TRIGGER IF EXISTS label_app_path_type_rule_view_delete_trigger;
+CREATE TRIGGER label_app_path_type_rule_view_delete_trigger
+INSTEAD OF DELETE
+ON label_app_path_type_rule_view
+BEGIN
+    -- Delete the rules with this label
+    DELETE FROM label_app_path_type_rule
+    WHERE       label_app_path_type_rule.label_id
+                IN (SELECT label.label_id
+                    FROM   label
+                    WHERE  label.name = OLD.label_name);
+
+    -- Delete the label if it's not referenced
+    DELETE FROM label_view
+    WHERE label_view.name = OLD.label_name;
+END;
+
 -- PERMISSION TO PERMISSION RULE VIEW ------------------------------------------
 DROP VIEW IF EXISTS permission_permission_rule_view;
 CREATE VIEW permission_permission_rule_view AS
@@ -379,11 +442,13 @@ 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
+                             FROM   app) AND
         OLD.label_id NOT IN (SELECT permission_label_rule.label_id
-                             FROM permission_label_rule) AND
+                             FROM   permission_label_rule) AND
         OLD.label_id NOT IN (SELECT app_path.label_id
-                             FROM app_path)
+                             FROM   app_path) AND
+        OLD.label_id NOT IN (SELECT label_app_path_type_rule.label_id
+                             FROM   label_app_path_type_rule)
 BEGIN
         DELETE FROM label WHERE label.name = OLD.name;
 END;
@@ -675,6 +740,21 @@ INNER JOIN  label USING(label_id)
 WHERE       app.name != label.name;
 
 
+-- LABEL TO PATH TYPE RULE VIEW -------------------------------------------
+-- ltl = label to label
+DROP VIEW IF EXISTS ltl_label_app_path_type_rule_view;
+CREATE VIEW ltl_label_app_path_type_rule_view AS
+SELECT      (CASE WHEN is_reverse = 0 THEN label.name ELSE path_label.name END) AS subject,
+            (CASE WHEN is_reverse = 1 THEN label.name ELSE path_label.name END) AS object,
+            l.access AS access,
+            0 AS is_volatile
+FROM        label_app_path_type_rule AS l
+INNER JOIN  label USING(label_id)
+INNER JOIN  app_path USING(app_path_type_id)
+INNER JOIN  label AS path_label ON app_path.label_id = path_label.label_id
+WHERE       path_label.name != label.name;
+
+
 -- PERMISSION TO APPLICATION'S OWN PATHS ---------------------------------------
 -- ltl = label to label
 DROP VIEW IF EXISTS ltl_app_path_view;
@@ -703,6 +783,9 @@ FROM   (SELECT subject, object, access, is_volatile
         SELECT subject, object, access, is_volatile
         FROM   ltl_permission_app_path_type_rule_view
         UNION ALL
+        SELECT subject, object, access, is_volatile
+        FROM   ltl_label_app_path_type_rule_view
+        UNION ALL
         SELECT subject, object, access, 0
         FROM   ltl_app_path_view
        )
index f739e28..f7d80ad 100644 (file)
@@ -97,6 +97,7 @@
 <datatype>INTEGER</datatype>
 <relation table="app_path" row="app_path_type_id" />
 <relation table="permission_app_path_type_rule" row="app_path_type_id" />
+<relation table="label_app_path_type_rule" row="app_path_type_id" />
 </row>
 <row name="name" null="0" autoincrement="0">
 <datatype>MEDIUMTEXT</datatype>
 <part>is_reverse</part>
 </key>
 </table>
+<table x="849" y="620" name="label_app_path_type_rule">
+<row name="label_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+<relation table="label" row="label_id" />
+</row>
+<row name="app_path_type_id" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+</row>
+<row name="access" null="0" autoincrement="0">
+<datatype>INTEGER</datatype>
+<default>0</default></row>
+<row name="is_reverse" null="1" autoincrement="0">
+<datatype>TINYINT</datatype>
+<default>NULL</default></row>
+<key type="PRIMARY" name="">
+<part>label_id</part>
+<part>app_path_type_id</part>
+<part>is_reverse</part>
+</key>
+</table>
 </sql>
index dafe93e..f32030d 100644 (file)
@@ -99,6 +99,7 @@ void fts_closep(FTS **f);
 
 #define SMACK_APP_LABEL_TEMPLATE        "~APP~"
 #define SMACK_SHARED_DIR_LABEL_TEMPLATE "~APP_SHARED_DIR~"
+#define ACC_LEN 6
 
 int smack_label_is_valid(const char* smack_label);
 
@@ -109,4 +110,58 @@ bool file_exists(const char* path);
 int smack_file_name(const char* app_id, char** path);
 inline int have_smack(void);
 
+
+/**
+ * Divide a Smack rule into subject, object and access
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  s_rule    the rule
+ * @param  s_subject buffer for the subject
+ * @param  s_object  buffer for the object
+ * @param  s_access  buffer for the access
+ * @return           PC_OPERATION_SUCCESS on success,
+ *                   error code otherwise
+ */
+int tokenize_rule(const char *const s_rule,
+                 char s_subject[],
+                 char s_object[],
+                 char s_access[]);
+
+/**
+ * Check if the label is a wildcard.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  s_label the label
+ * @return         is the label a wildcard?
+ */
+bool is_wildcard(const char *const s_label);
+
+/**
+ * Divides the rule into subject, object and access strings.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  s_rule         the string that we parse
+ * @param  s_label        buffer for the label
+ * @param  s_access       buffer for the access
+ * @param  pi_is_reverse  buffer for the is_reversed
+ * @return                PC_OPERATION_SUCCESS on success,
+ *                        error code otherwise
+ */
+int parse_rule(const char *const s_rule,
+              char s_label[],
+              char s_access[],
+              int *pi_is_reverse);
+
+/**
+ * Validate if all rules in the array can be parsed.
+ *
+ * @param  pp_permissions_list array of permissions to check
+ * @return                     PC_OPERATION_SUCCESS on success,
+ *                             error code otherwise
+ */
+int validate_all_rules(const char *const *const pp_permissions_list);
+
 #endif /* COMMON_H_ */
index 55beb23..143e705 100644 (file)
@@ -430,6 +430,16 @@ int perm_begin(void);
  */
 int perm_end(void);
 
+/**
+ * Add additional rules to libprivilege.
+ * The rules can use wild-cards and labels.
+ *
+ * @param  set_smack_rule_set an array of rules, NULL terminated
+ * @return                    PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int perm_add_additional_rules(const char** set_smack_rule_set);
+
+
 int base_name_from_perm(const char *perm, char **name);
 
 
index dc56a26..9f5f486 100644 (file)
@@ -281,24 +281,6 @@ int get_app_id_internal(sqlite3 *p_db,
 
 
 /**
- * Divides the rule into subject, object and access strings.
- *
- * @ingroup RDB internal functions
- *
- * @param  s_rule         the string that we parse
- * @param  s_label        buffer for the label
- * @param  s_access       buffer for the access
- * @param  pi_is_reverse  buffer for the is_reversed
- * @return                PC_OPERATION_SUCCESS on success,
- *                        error code otherwise
- */
-int parse_rule(const char *const s_rule,
-              char s_label[],
-              char s_access[],
-              int *pi_is_reverse);
-
-
-/**
  * Add a new permission to an application.
  *
  * @ingroup RDB internal functions
@@ -438,4 +420,16 @@ int update_rules_in_db(sqlite3 *p_db);
 int update_smack_rules(sqlite3 *p_db);
 
 
+/**
+ * Add additional rules to the database.
+ *
+ * @ingroup RDB internal functions
+ *
+ * @param  p_db           pointer to a SQLite3 database object
+ * @param  pp_smack_rules a list of smack rules
+ * @return                PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int add_additional_rules_internal(sqlite3 *p_db,
+                                 const char  *const *const pp_smack_rules);
+
 #endif // _RULES_DB_INTERNALS_H_
index 6ae4f91..7f8cd1d 100644 (file)
@@ -161,16 +161,6 @@ int rdb_disable_app_permissions(const char  *const s_app_label_name,
 
 
 /**
- * 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.
  *
@@ -195,4 +185,15 @@ int rdb_revoke_app_permissions(const char *const s_app_label_name);
  */
 int rdb_reset_app_permissions(const char *const s_app_label_name);
 
+/**
+ * Add the additional rules to the database. Erase the previous rules.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  pp_smack_rules NULL terminated table of rules
+ * @return                PC_OPERATION_SUCCESS on success,
+ *                        error code otherwise
+ */
+int rdb_add_additional_rules(const char *const *const pp_smack_rules);
+
 #endif /*_RULES_DB_H_*/
\ No newline at end of file
index 89aa9f0..c5cb6a8 100644 (file)
@@ -106,7 +106,8 @@ rm -f /opt/dbspace/rules-db.sql
 sqlite3 /opt/dbspace/.rules-db.db3 < /opt/dbspace/rules-db-data.sql
 rm -f /opt/dbspace/rules-db-data.sql
 
-api_feature_loader --verbose
+api_feature_loader --verbose --dir=/usr/share/privilege-control/
+api_feature_loader --verbose --rules=/usr/share/privilege-control/ADDITIONAL_RULES.smack
 
 %files
 %{_libdir}/*.so.*
index 4b68e48..43f6a0a 100644 (file)
 #include "privilege-control.h"
 
 /* TODO: implement such function in libsmack instead */
-int smack_label_is_valid(const charsmack_label)
+int smack_label_is_valid(const char *smack_label)
 {
        SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s",
-                               __func__, smack_label);
+                     __func__, smack_label);
 
        int i;
 
-       if (!smack_label || smack_label[0] == '\0' || smack_label[0] == '-')
+       if(!smack_label || smack_label[0] == '\0' || smack_label[0] == '-')
                goto err;
 
-       for (i = 0; smack_label[i]; ++i) {
-               if (i >= SMACK_LABEL_LEN)
+       for(i = 0; smack_label[i]; ++i) {
+               if(i >= SMACK_LABEL_LEN)
                        goto err;
-               switch (smack_label[i]) {
+               switch(smack_label[i]) {
                case '~':
                case ' ':
                case '/':
@@ -64,21 +64,130 @@ err:
        return 0;
 }
 
+
+int tokenize_rule(const char *const s_rule,
+                 char s_subject[],
+                 char s_object[],
+                 char s_access[])
+{
+       if(sscanf(s_rule, "%s %s %s", s_subject, s_object, s_access) < 3) {
+               C_LOGE("RDB: Failed to tokenize the rule: %s", s_rule);
+               return PC_ERR_INVALID_OPERATION;
+       }
+       return PC_OPERATION_SUCCESS;
+}
+
+
+bool is_wildcard(const char *const s_label)
+{
+       return  !strcmp(s_label, "~ALL_APPS~") ||
+               !strcmp(s_label, "~ALL_APPS_WITH_SAME_PERMISSION~") ||
+               !strcmp(s_label, "~PUBLIC_PATH~") ||
+               !strcmp(s_label, "~GROUP_PATH~") ||
+               !strcmp(s_label, "~SETTINGS_PATH~");
+}
+
+
+int parse_rule(const char *const s_rule,
+              char s_label[],
+              char s_access[],
+              int *pi_is_reverse)
+{
+       int ret = PC_OPERATION_SUCCESS;
+       char tmp_s_subject[SMACK_LABEL_LEN + 1];
+       char tmp_s_object[SMACK_LABEL_LEN + 1];
+       char tmp_s_access[ACC_LEN + 1];
+
+       bool b_subject_is_template;
+       bool b_object_is_template;
+
+       // Tokenize
+       ret = tokenize_rule(s_rule, tmp_s_subject, tmp_s_object, tmp_s_access);
+       if(ret != PC_OPERATION_SUCCESS) return ret;
+
+       // Check SMACK_APP_LABEL_TEMPLATE
+       b_subject_is_template = (bool) !strcmp(tmp_s_subject, SMACK_APP_LABEL_TEMPLATE);
+       b_object_is_template = (bool) !strcmp(tmp_s_object, SMACK_APP_LABEL_TEMPLATE);
+       if((b_subject_is_template && b_object_is_template) ||
+           (!b_subject_is_template && !b_object_is_template)) {
+               C_LOGE("RDB: Incorrect rule format in rule: %s", s_rule);
+               ret = PC_ERR_INVALID_PARAM;
+               return ret;
+       }
+
+       // Check label validity and copy rules
+       if(b_subject_is_template) {
+               // Not reversed
+               if(!smack_label_is_valid(tmp_s_object) &&
+                   !is_wildcard(tmp_s_object)) {
+                       C_LOGE("RDB: Incorrect subject label: %s", tmp_s_object);
+                       return ret;
+               }
+               strcpy(s_label, tmp_s_object);
+               if(pi_is_reverse != NULL) *pi_is_reverse = 0;
+       } else if(b_object_is_template) {
+               // Reversed
+               if(!smack_label_is_valid(tmp_s_subject) &&
+                   !is_wildcard(tmp_s_subject)) {
+                       C_LOGE("RDB: Incorrect subject label: %s", tmp_s_subject);
+                       return ret;
+               }
+               strcpy(s_label, tmp_s_subject);
+               if(pi_is_reverse != NULL) *pi_is_reverse = 1;
+       }
+       strcpy(s_access, tmp_s_access);
+
+       return PC_OPERATION_SUCCESS;
+}
+
+
+int validate_all_rules(const char *const *const pp_permissions_list)
+{
+       int i;
+       char s_label[SMACK_LABEL_LEN + 1];
+       char s_access[ACC_LEN + 1];
+
+       // Parse and check rules.
+       for(i = 0; pp_permissions_list[i] != NULL; ++i) {
+               // C_LOGE("RDB: Validating rules: %s", pp_permissions_list[i]);
+
+               // Ignore empty lines
+               if(strspn(pp_permissions_list[i], " \t\n")
+                   == strlen(pp_permissions_list[i]))
+                       continue;
+
+               if(parse_rule(pp_permissions_list[i], s_label, s_access, NULL)
+                   != PC_OPERATION_SUCCESS) {
+                       C_LOGE("RDB: Invalid parameter");
+                       return PC_ERR_INVALID_PARAM;
+               }
+
+               // Check the other label
+               if(!is_wildcard(s_label) &&
+                   !smack_label_is_valid(s_label)) {
+                       C_LOGE("RDB: Incorrect object label: %s", s_label);
+                       return PC_ERR_INVALID_PARAM;
+               }
+       }
+
+       return PC_OPERATION_SUCCESS;
+}
+
 /* Auto cleanup stuff */
 void freep(void *p)
 {
-       free(*(void**) p);
+       free(*(void **) p);
 }
 
 void closep(int *fd)
 {
-       if (*fd >= 0)
+       if(*fd >= 0)
                close(*fd);
 }
 
 void fclosep(FILE **f)
 {
-       if (*f)
+       if(*f)
                fclose(*f);
 }
 
@@ -89,58 +198,57 @@ void smack_freep(struct smack_accesses **smack)
 
 void fts_closep(FTS **f)
 {
-       if (*f)
+       if(*f)
                fts_close(*f);
 
 }
 
-static int load_smack_from_file_generic(const char* app_id, struct smack_accesses** smack, int *fd, char** path, bool is_early)
+static int load_smack_from_file_generic(const char *app_id, struct smack_accesses **smack, int *fd, char **path, bool is_early)
 {
        /* Notice that app_id is ignored when flag is_early is set.
         * It's because all of the "early rules" (for all apps) should
         * be in one common file: SMACK_STARTUP_RULES_FILE
         */
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
        int ret;
 
-       if (is_early) {
-               if (0 > asprintf(path, "%s", SMACK_STARTUP_RULES_FILE)) {
+       if(is_early) {
+               if(0 > asprintf(path, "%s", SMACK_STARTUP_RULES_FILE)) {
                        *path = NULL;
                        C_LOGE("asprintf failed.");
                        return PC_ERR_MEM_OPERATION;
                }
-       }
-       else {
+       } else {
                ret = smack_file_name(app_id, path);
-               if (ret != PC_OPERATION_SUCCESS)
+               if(ret != PC_OPERATION_SUCCESS)
                        return ret;
        }
 
-       if (smack_accesses_new(smack)) {
+       if(smack_accesses_new(smack)) {
                C_LOGE("smack_accesses_new failed.");
                return PC_ERR_MEM_OPERATION;
        }
 
-       *fd = open(*path, O_CREAT|O_RDWR, 0644);
-       if (*fd == -1) {
+       *fd = open(*path, O_CREAT | O_RDWR, 0644);
+       if(*fd == -1) {
                C_LOGE("file open failed (error: %s)", strerror(errno));
                return PC_ERR_FILE_OPERATION;
        }
 
-       if (flock(*fd, LOCK_EX)) {
+       if(flock(*fd, LOCK_EX)) {
                C_LOGE("flock failed");
                return PC_ERR_INVALID_OPERATION;
        }
 
-       if (smack_accesses_add_from_file(*smack, *fd)) {
+       if(smack_accesses_add_from_file(*smack, *fd)) {
                C_LOGE("smack_accesses_add_from_file failed.");
                return PC_ERR_INVALID_OPERATION;
        }
 
        /* Rewind the file */
-       if (lseek(*fd, 0, SEEK_SET) == -1) {
+       if(lseek(*fd, 0, SEEK_SET) == -1) {
                C_LOGE("lseek failed.");
                return PC_ERR_FILE_OPERATION;
        }
@@ -148,18 +256,18 @@ static int load_smack_from_file_generic(const char* app_id, struct smack_accesse
        return PC_OPERATION_SUCCESS;
 }
 
-int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd, char** path)
+int load_smack_from_file(const char *app_id, struct smack_accesses **smack, int *fd, char **path)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
        return load_smack_from_file_generic(app_id, smack, fd, path, 0);
 }
 
-int load_smack_from_file_early(const char* app_id, struct smack_accesses** smack, int *fd, char** path)
+int load_smack_from_file_early(const char *app_id, struct smack_accesses **smack, int *fd, char **path)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
        return load_smack_from_file_generic(app_id, smack, fd, path, 1);
 }
@@ -167,9 +275,9 @@ int load_smack_from_file_early(const char* app_id, struct smack_accesses** smack
 int smack_mark_file_name(const char *app_id, char **path)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
-       if (asprintf(path, SMACK_LOADED_APP_RULES "/%s", app_id) == -1) {
+       if(asprintf(path, SMACK_LOADED_APP_RULES "/%s", app_id) == -1) {
                C_LOGE("asprintf failed.");
                *path = NULL;
                return PC_ERR_MEM_OPERATION;
@@ -178,25 +286,26 @@ int smack_mark_file_name(const char *app_id, char **path)
        return PC_OPERATION_SUCCESS;
 }
 
-bool file_exists(const char* path) {
+bool file_exists(const char *path)
+{
        SECURE_C_LOGD("Entering function: %s. Params: path=%s",
-                               __func__, path);
+                     __func__, path);
 
        SECURE_C_LOGD("Opening file %s.", path);
-       FILEfile = fopen(path, "r");
-       if (file) {
+       FILE *file = fopen(path, "r");
+       if(file) {
                fclose(file);
                return true;
        }
        return false;
 }
 
-int smack_file_name(const char* app_id, char** path)
+int smack_file_name(const char *app_id, char **path)
 {
        SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
-                               __func__, app_id);
+                     __func__, app_id);
 
-       if (asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) {
+       if(asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) {
                C_LOGE("asprintf failed.");
                *path = NULL;
                return PC_ERR_MEM_OPERATION;
@@ -211,8 +320,8 @@ inline int have_smack(void)
 
        static int have_smack = -1;
 
-       if (-1 == have_smack) {
-               if (NULL == smack_smackfs_path()) {
+       if(-1 == have_smack) {
+               if(NULL == smack_smackfs_path()) {
                        C_LOGD("Libprivilege-control: no smack found on phone");
                        have_smack = 0;
                } else {
index 6616cf3..9a99733 100644 (file)
@@ -1617,3 +1617,20 @@ API int app_register_av(const char* app_av_id UNUSED)//deprecated
        // TODO: This function is not implemented with RDB.
        return PC_ERR_INVALID_OPERATION;
 }
+
+API int perm_add_additional_rules(const char** smack_rules){
+       SECURE_C_LOGD("Entering function: %s.", __func__);
+       int ret;
+       if (!smack_rules){
+               C_LOGE("smack_rules is NULL");
+               return PC_ERR_INVALID_PARAM;
+       }
+
+       ret = rdb_add_additional_rules(smack_rules);
+       if (ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB rdb_add_additional_rules failed with: %d", ret);
+               return ret;
+       }
+
+       return PC_OPERATION_SUCCESS;
+}
index 372a3bd..31684c0 100644 (file)
  */
 static int reset_and_unbind_stmt(sqlite3_stmt *p_stmt)
 {
-       if(sqlite3_reset(p_stmt) != SQLITE_OK) {
-               C_LOGE("RDB: Error reseting statement: %s",
+       if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
+               C_LOGE("RDB: Error unbinding statement: %s",
                       sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
                return PC_ERR_DB_QUERY_STEP;
        }
-       if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
-               C_LOGE("RDB: Error unbinding statement: %s",
+
+       if(sqlite3_reset(p_stmt) != SQLITE_OK) {
+               C_LOGE("RDB: Error reseting statement: %s",
                       sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
                return PC_ERR_DB_QUERY_STEP;
        }
@@ -569,64 +570,6 @@ finish:
 }
 
 
-int parse_rule(const char *const s_rule,
-              char s_label[],
-              char s_access[],
-              int *pi_is_reverse)
-{
-       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;
-       bool b_subject_is_template;
-       bool b_object_is_template;
-
-       // 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;
-       }
-
-       // Check if valid
-       b_subject_is_template = (bool) !strcmp(tmp_s_subject, SMACK_APP_LABEL_TEMPLATE);
-       b_object_is_template = (bool) !strcmp(tmp_s_object, SMACK_APP_LABEL_TEMPLATE);
-       if((b_subject_is_template && b_object_is_template) ||
-           (!b_subject_is_template && !b_object_is_template)) {
-               C_LOGE("RDB: Incorrect rule format: %s", s_rule);
-               ret = PC_ERR_INVALID_PARAM;
-               goto finish;
-       }
-
-       // Copy rules
-       if(b_subject_is_template) {
-               // Not reversed
-               if(pi_is_reverse != NULL) *pi_is_reverse = 0;
-               strcpy(s_label, tmp_s_object);
-       } else if(b_object_is_template) {
-               // Reversed
-               if(pi_is_reverse != NULL) *pi_is_reverse = 1;
-               strcpy(s_label, tmp_s_subject);
-       }
-       strcpy(s_access, tmp_s_access);
-
-finish:
-       free(tmp_s_rule);
-       return ret;
-}
-
-
 int prepare_stmts_for_bind(sqlite3 *p_db,
                           sqlite3_stmt **pp_stmt,
                           const char *const s_query)
@@ -644,11 +587,11 @@ int prepare_stmts_for_bind(sqlite3 *p_db,
 }
 
 
-int add_permission_label_rule(sqlite3_stmt *p_stmt,
-                             const sqlite3_int64 i_permission_id,
-                             const char *const s_label_name,
-                             const char *const s_access,
-                             const int i_is_reverse)
+static int add_permission_label_rule(sqlite3_stmt *p_stmt,
+                                    const sqlite3_int64 i_permission_id,
+                                    const char *const s_label_name,
+                                    const char *const s_access,
+                                    const int i_is_reverse)
 {
        int ret = PC_OPERATION_SUCCESS;
 
@@ -673,11 +616,11 @@ finish:
 }
 
 
-int add_permission_permission_rule(sqlite3_stmt *p_stmt,
-                                  const sqlite3_int64 i_permission_id,
-                                  const sqlite3_int64 i_target_permission_id,
-                                  const char *const s_access,
-                                  const int i_is_reverse)
+static int add_permission_permission_rule(sqlite3_stmt *p_stmt,
+               const sqlite3_int64 i_permission_id,
+               const sqlite3_int64 i_target_permission_id,
+               const char *const s_access,
+               const int i_is_reverse)
 {
        int ret = PC_OPERATION_SUCCESS;
 
@@ -699,11 +642,11 @@ finish:
 }
 
 
-int add_permission_app_path_type_stmt(sqlite3_stmt *p_stmt,
-                                     const sqlite3_int64 i_permission_id,
-                                     const char *const s_path_type_name,
-                                     const char *const s_access,
-                                     const int i_is_reverse)
+static int add_permission_app_path_type_rule(sqlite3_stmt *p_stmt,
+               const sqlite3_int64 i_permission_id,
+               const char *const s_path_type_name,
+               const char *const s_access,
+               const int i_is_reverse)
 {
        int ret = PC_OPERATION_SUCCESS;
 
@@ -745,21 +688,21 @@ int add_permission_rules_internal(sqlite3 *p_db,
                                     "INSERT INTO permission_label_rule_view(        \
                                      permission_id, access, label_name, is_reverse) \
                                      VALUES(?,?,?,?)");
-       if(ret != PC_OPERATION_SUCCESS) return ret;
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = prepare_stmts_for_bind(p_db, &p_perm_to_perm_stmt,
                                     "INSERT OR REPLACE INTO permission_permission_rule( \
                                      permission_id, target_permission_id,               \
                                      access, is_reverse)                                \
                                      VALUES(?,?,str_to_access(?),?)");
-       if(ret != PC_OPERATION_SUCCESS) return ret;
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
 
        ret = prepare_stmts_for_bind(p_db, &p_perm_to_app_path_type_stmt,
                                     "INSERT INTO permission_app_path_type_rule_view(        \
                                      permission_id, app_path_type_name, access, is_reverse) \
                                      VALUES(?,?,?,?)");
-       if(ret != PC_OPERATION_SUCCESS) return ret;
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
 
        for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
@@ -770,7 +713,7 @@ int add_permission_rules_internal(sqlite3 *p_db,
                        continue;
 
                ret = parse_rule(pp_smack_rules[i], s_label, s_access, &i_is_reverse);
-               if(ret != PC_OPERATION_SUCCESS) return ret;
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
 
                // Interpret wildcards
                if(s_label[0] != '~' &&
@@ -781,21 +724,21 @@ int add_permission_rules_internal(sqlite3 *p_db,
                                                        s_label,
                                                        s_access,
                                                        i_is_reverse);
-                       if(ret != PC_OPERATION_SUCCESS) return ret;
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
                } else if(!strcmp(s_label, "~ALL_APPS~")) {
                        ret = get_permission_id_internal(p_db,
                                                         "ALL_APPS",
                                                         "ALL_APPS",
                                                         &i_all_apps_permission_id);
-                       if(ret != PC_OPERATION_SUCCESS) return ret;
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
                        ret = add_permission_permission_rule(p_perm_to_perm_stmt,
                                                             i_permission_id,
                                                             i_all_apps_permission_id,
                                                             s_access,
                                                             i_is_reverse);
-                       if(ret != PC_OPERATION_SUCCESS) return ret;
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
                } else if(!strcmp(s_label, "~ALL_APPS_WITH_SAME_PERMISSION~")) {
                        ret = add_permission_permission_rule(p_perm_to_perm_stmt,
@@ -803,34 +746,162 @@ int add_permission_rules_internal(sqlite3 *p_db,
                                                             i_permission_id,
                                                             s_access,
                                                             i_is_reverse);
-                       if(ret != PC_OPERATION_SUCCESS) return ret;
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
                } else if(!strcmp(s_label, "~PUBLIC_PATH~")) {
-                       ret = add_permission_app_path_type_stmt(p_perm_to_app_path_type_stmt,
+                       ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
                                                                i_permission_id,
                                                                "PUBLIC_PATH",
                                                                s_access,
                                                                i_is_reverse);
-                       if(ret != PC_OPERATION_SUCCESS) return ret;
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
                } else if(!strcmp(s_label, "~GROUP_PATH~")) {
-                       ret = add_permission_app_path_type_stmt(p_perm_to_app_path_type_stmt,
+                       ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
                                                                i_permission_id,
                                                                "GROUP_PATH",
                                                                s_access,
                                                                i_is_reverse);
-                       if(ret != PC_OPERATION_SUCCESS) return ret;
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
                } else if(!strcmp(s_label, "~SETTINGS_PATH~")) {
-                       ret = add_permission_app_path_type_stmt(p_perm_to_app_path_type_stmt,
+                       ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
                                                                i_permission_id,
                                                                "SETTINGS_PATH",
                                                                s_access,
                                                                i_is_reverse);
-                       if(ret != PC_OPERATION_SUCCESS) return ret;
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
                }
        }
-       return PC_OPERATION_SUCCESS;
+
+       ret = PC_OPERATION_SUCCESS;
+
+finish:
+       if(p_perm_to_label_stmt &&
+           sqlite3_finalize(p_perm_to_label_stmt) < 0) {
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       }
+
+       if(p_perm_to_perm_stmt &&
+           sqlite3_finalize(p_perm_to_perm_stmt) < 0) {
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       }
+
+       if(p_perm_to_app_path_type_stmt &&
+           sqlite3_finalize(p_perm_to_app_path_type_stmt) < 0) {
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       }
+       return ret;
+}
+
+static int add_label_app_path_type_rule(sqlite3_stmt *p_stmt,
+                                       const char *const s_label_name,
+                                       const char *const s_path_type_name,
+                                       const char *const s_access,
+                                       const int i_is_reverse)
+{
+       int ret = PC_OPERATION_SUCCESS;
+
+       if(sqlite3_bind_text(p_stmt, 1, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
+           sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0)  ||
+           sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
+           sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
+               C_LOGE("RDB: Error during binding to statement: %s",
+                      sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
+               ret = PC_ERR_DB_QUERY_BIND;
+               goto finish;
+       }
+
+       ret = step_and_convert_returned_value(p_stmt);
+
+finish:
+       reset_and_unbind_stmt(p_stmt);
+       return ret;
+}
+
+
+int add_additional_rules_internal(sqlite3 *p_db, const char *const *const pp_smack_rules)
+{
+       RDB_LOG_ENTRY;
+       int ret = PC_OPERATION_SUCCESS;
+       size_t i;
+       char s_subject[SMACK_LABEL_LEN + 1];
+       char s_object[SMACK_LABEL_LEN + 1];
+       char s_access[ACC_LEN + 1];
+       sqlite3_stmt *p_label_to_app_path_type_stmt = NULL;
+
+       // Clear the label_app_path_type_rule table
+       if(sqlite3_exec(p_db, "DELETE FROM label_app_path_type_rule_view;", 0, 0, 0) != SQLITE_OK) {
+               C_LOGE("RDB: Error during clearing additional rules: %s", sqlite3_errmsg(p_db));
+               ret = PC_ERR_DB_OPERATION;
+               goto finish;
+       }
+
+       ret = prepare_stmts_for_bind(p_db, &p_label_to_app_path_type_stmt,
+                                    "INSERT INTO label_app_path_type_rule_view(          \
+                                     label_name, app_path_type_name, access, is_reverse) \
+                                     VALUES(?,?,?,?)");
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       // Add rules to the database
+       for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
+
+               // Ignore empty lines
+               if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
+                       continue;
+
+               // Tokenize
+               ret = tokenize_rule(pp_smack_rules[i], s_subject , s_object, s_access);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+
+               // Check validity
+               if(!smack_label_is_valid(s_subject)) {
+                       C_LOGE("Subject is not a valid label");
+                       ret = PC_ERR_INVALID_PARAM;
+                       goto finish;
+               }
+
+               // Add access to paths
+               if(!strcmp(s_object, "~PUBLIC_PATH~")) {
+                       ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
+                                                          s_subject,
+                                                          "PUBLIC_PATH",
+                                                          s_access,
+                                                          0);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               } else if(!strcmp(s_object, "~GROUP_PATH~")) {
+                       ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
+                                                          s_subject,
+                                                          "GROUP_PATH",
+                                                          s_access,
+                                                          0);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+               } else if(!strcmp(s_object, "~SETTINGS_PATH~")) {
+                       ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
+                                                          s_subject,
+                                                          "SETTINGS_PATH",
+                                                          s_access,
+                                                          0);
+                       if(ret != PC_OPERATION_SUCCESS) goto finish;
+               }
+
+               // Mark label as modified
+               ret = add_modified_label_internal(p_db, s_subject);
+               if(ret != PC_OPERATION_SUCCESS) goto finish;
+       }
+
+finish:
+       if(p_label_to_app_path_type_stmt &&
+           sqlite3_finalize(p_label_to_app_path_type_stmt) < 0)
+               C_LOGE("RDB: Error during finalizing statement: %s",
+                      sqlite3_errmsg(p_db));
+       return ret;
 }
 
 
index aaf557f..9a680b5 100644 (file)
@@ -115,7 +115,7 @@ static void rdb_end(sqlite3 *p_db, int ret)
        }
 
        if(sqlite3_close(p_db)) {
-               C_LOGE("RDB: Error during closing the database.");
+               C_LOGE("RDB: Error during closing the database. Error: %s", sqlite3_errmsg(p_db));
        }
 }
 
@@ -411,45 +411,21 @@ finish:
        return ret;
 }
 
-static bool is_wildcard(const char *const s_label)
-{
-       return  !strcmp(s_label, "~ALL_APPS~") ||
-               !strcmp(s_label, "~ALL_APPS_WITH_SAME_PERMISSION~") ||
-               !strcmp(s_label, "~PUBLIC_PATH~") ||
-               !strcmp(s_label, "~GROUP_PATH~") ||
-               !strcmp(s_label, "~SETTINGS_PATH~");
-}
 
-int validate_all_rules(const char *const *const pp_permissions_list)
+int rdb_add_additional_rules(const char *const *const pp_smack_rules)
 {
        RDB_LOG_ENTRY;
 
-       int i;
-       char s_label[SMACK_LABEL_LEN + 1];
-       char s_access[ACC_LEN + 1];
-
-       // Parse and check rules.
-       for(i = 0; pp_permissions_list[i] != NULL; ++i) {
-               // C_LOGE("RDB: Validating rules: %s", pp_permissions_list[i]);
-
-               // Ignore empty lines
-               if(strspn(pp_permissions_list[i], " \t\n")
-                   == strlen(pp_permissions_list[i]))
-                       continue;
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
 
-               if(parse_rule(pp_permissions_list[i], s_label, s_access, NULL)
-                   != PC_OPERATION_SUCCESS) {
-                       C_LOGE("RDB: Invalid parameter");
-                       return PC_ERR_INVALID_PARAM;
-               }
+       ret = rdb_begin(&p_db);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
 
-               // Check the other label
-               if(!is_wildcard(s_label) &&
-                   !smack_label_is_valid(s_label)) {
-                       C_LOGE("RDB: Incorrect object label: %s", s_label);
-                       return PC_ERR_INVALID_PARAM;
-               }
-       }
+       ret = add_additional_rules_internal(p_db,
+                                           pp_smack_rules);
 
-       return PC_OPERATION_SUCCESS;
+finish:
+       if(p_db__) update_ret_code(ret); else rdb_end(p_db, ret);
+       return ret;
 }