New API for permission checking
authorMarcin Lis <m.lis@samsung.com>
Tue, 8 Oct 2013 09:41:06 +0000 (11:41 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 14 Nov 2013 13:19:51 +0000 (14:19 +0100)
[Issue#]       SSDWSSP-527
[Feature]      Introduce new API function.
[Cause]        New API will improve the performance while checking
               app permissions. It is also needed by Security Server.
[Solution]     One new API function is added, which enables user to check
               whether an app with given label has enabled permission
               specified by name.
[Verification] Build, install & run tests.

Change-Id: I4c068f593c585d5a16e2ca9f72666aea79fafcab

include/privilege-control.h
include/rules-db-internals.h
include/rules-db.h
src/privilege-control.c
src/rules-db-internals.c
src/rules-db.c

index bf82d2c..bc02aa3 100644 (file)
@@ -313,6 +313,20 @@ int perm_app_reset_permissions(const char* pkg_id);
 int app_reset_permissions(const char* pkg_id) DEPRECATED;
 
 /**
+ * Check if an application has the privilege that is specified by the name
+ *
+ * @param pkg_id application identifier
+ * @param app_type application type
+ * @param permission_name permission name
+ * @param is_enabled buffer for return value
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int perm_app_has_permission(const char *pkg_id,
+                           app_type_t app_type,
+                           const char *permission_name,
+                           bool *is_enabled);
+
+/**
  * Recursively set SMACK access labels for an application directory
  * and execute labels for executable files.
  * This function should be called once during app installation.
index 2dc7412..d6603c3 100644 (file)
@@ -237,6 +237,24 @@ int add_permission_rules_internal(sqlite3 *p_db,
                                  const char  *const *const pp_smack_rules);
 
 
+/**
+ * Check if an app has a permission that is specified by the name.
+ *
+ * @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  p_is_enabled           buffer for return value
+ * @return                        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int check_app_has_permission_internal(sqlite3 *p_db,
+                                     const char *const s_app_label_name,
+                                     const char *const s_permission_name,
+                                     const char *const s_permission_type_name,
+                                     bool *const p_is_enabled);
+
 
 /**
  * Gets the internal app id of an application with a given name.
index 0dfc843..38fafc6 100644 (file)
@@ -199,4 +199,22 @@ int rdb_reset_app_permissions(const char *const s_app_label_name);
  */
 int rdb_add_additional_rules(const char *const *const pp_smack_rules);
 
+
+/**
+ * Check if app has the privilege that is specified by the name.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_app_label_name       application's label name
+ * @param  s_permission_type_name permission's type name
+ * @param  s_permission_name      permission name
+ * @param  p_is_enabled           buffer for return value
+ * @return                        PC_OPERATION_SUCCESS on success,
+ *                                error code otherwise
+ */
+int rdb_app_has_permission(const char *const s_app_label_name,
+                          const char *const s_permission_type_name,
+                          const char *const s_permission_name,
+                          bool *const p_is_enabled);
+
 #endif /*_RULES_DB_H_*/
index 1eb356f..1a1f90a 100644 (file)
@@ -1015,6 +1015,39 @@ API int perm_app_reset_permissions(const char* pkg_id)
        return PC_OPERATION_SUCCESS;
 }
 
+API int perm_app_has_permission(const char *pkg_id,
+                               app_type_t app_type,
+                               const char *permission_name,
+                               bool *is_enabled)
+{
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, permission_name=%s",
+                               __func__, pkg_id, app_type, permission_name);
+
+       const char *app_group = app_type_group_name(app_type);
+
+       if (app_group == NULL) {
+               C_LOGE("Unknown param app type.");
+               return PC_ERR_INVALID_PARAM;
+       }
+
+       if (!smack_label_is_valid(pkg_id)) {
+               C_LOGE("Invalid param app_id.");
+               return PC_ERR_INVALID_PARAM;
+       }
+
+       if (permission_name == NULL) {
+               C_LOGE("Invalid param permission_name (NULL).");
+               return PC_ERR_INVALID_PARAM;
+       }
+
+       if (is_enabled == NULL) {
+               C_LOGE("Invalid param is_enabled (NULL).");
+               return PC_ERR_INVALID_PARAM;
+       }
+
+       return rdb_app_has_permission(pkg_id, app_group, permission_name, is_enabled);
+}
+
 API int app_label_dir(const char* label, const char* path)//deprecated
 {
        SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
index b7113c0..9d8a555 100644 (file)
@@ -851,6 +851,54 @@ finish:
        return ret;
 }
 
+int check_app_has_permission_internal(sqlite3 *p_db,
+                                     const char *const s_app_label_name,
+                                     const char *const s_permission_name,
+                                     const char *const s_permission_type_name,
+                                     bool *const p_is_enabled)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s %s", s_app_label_name,
+                           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 is_enabled              \
+                           FROM   app_permission_view     \
+                           WHERE  app_name = %Q AND       \
+                                  name = %Q AND           \
+                                  type_name = %Q          \
+                           LIMIT  1",
+                          s_app_label_name, 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;
+               //store the result
+               *p_is_enabled = (bool)sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
+       } else if(ret == SQLITE_DONE) {
+               //no entry == permission not assigned
+               C_LOGD("RDB: Permission: %s of type: %s is not assigned to app: %s",
+                      s_permission_name, s_permission_type_name, s_app_label_name);
+               ret = PC_OPERATION_SUCCESS;
+               *p_is_enabled = false;
+       } else if(ret == SQLITE_BUSY) {
+               //base locked in exclusive mode for too long
+               C_LOGE("RDB: Database is busy. RDB Connection Error returned.");
+               ret = PC_ERR_DB_CONNECTION;
+       } 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 get_app_id_internal(sqlite3 *p_db,
                        int *pi_app_id,
index 490d626..39492f7 100644 (file)
 static sqlite3 *p_db__          = NULL;
 static int i_session_ret_code__ = PC_OPERATION_SUCCESS;
 
+typedef enum {
+       RDB_TRANSACTION_EXCLUSIVE,
+       RDB_TRANSACTION_SHARED_READ
+} rdb_transaction_type_t;
 
 /**
  * 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
+ * @param   pp_db             pointer to a pointer to a SQLite3 database object
+ * @param   transaction_type  indicates whether the transaction is exclusive or shared
+ * @return                    PC_OPERATION_SUCCESS on success, error code otherwise
  */
-static int rdb_begin(sqlite3 **pp_db)
+static int rdb_begin(sqlite3 **pp_db, rdb_transaction_type_t transaction_type)
 {
        RDB_LOG_ENTRY;
 
@@ -57,17 +61,26 @@ static int rdb_begin(sqlite3 **pp_db)
        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) {
+       if(transaction_type == RDB_TRANSACTION_EXCLUSIVE) {
+               ret = sqlite3_exec(*pp_db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0);
+       }
+       else if(transaction_type == RDB_TRANSACTION_SHARED_READ) {
+               ret = sqlite3_exec(*pp_db, "BEGIN DEFERRED TRANSACTION", 0, 0, 0);
+       }
+       else {
+               C_LOGE("RDB: Bad transaction type specified: %d",
+                      (int)transaction_type);
+               return PC_ERR_INVALID_PARAM;
+       }
+
+       if(ret != SQLITE_OK) {
                C_LOGE("RDB: Error during transaction begin: %s",
                       sqlite3_errmsg(*pp_db));
                return PC_ERR_DB_CONNECTION;
        }
 
        ret = save_smack_rules(*pp_db);
-       if(ret != PC_OPERATION_SUCCESS) return ret;
-
-       return PC_OPERATION_SUCCESS;
+       return ret;
 }
 
 
@@ -177,7 +190,7 @@ int rdb_modification_start(void)
                rdb_modification_finish();
        }
 
-       return rdb_begin(&p_db__);
+       return rdb_begin(&p_db__, RDB_TRANSACTION_EXCLUSIVE);
 }
 
 
@@ -201,7 +214,7 @@ int rdb_add_application(const char *const s_label_name)
        int ret = PC_ERR_DB_OPERATION;
        sqlite3 *p_db = NULL;
 
-       ret = rdb_begin(&p_db);
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
        if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = check_app_label_internal(p_db, s_label_name);
@@ -229,7 +242,7 @@ int rdb_remove_application(const char *const s_label_name)
        int ret = PC_ERR_DB_OPERATION;
        sqlite3 *p_db = NULL;
 
-       ret = rdb_begin(&p_db);
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
        if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = remove_app_internal(p_db, s_label_name);
@@ -259,7 +272,7 @@ int rdb_add_path(const char *const s_owner_label_name,
        int ret = PC_ERR_DB_OPERATION;
        sqlite3 *p_db = NULL;
 
-       ret = rdb_begin(&p_db);
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
        if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = add_path_internal(p_db,
@@ -288,7 +301,7 @@ int rdb_add_permission_rules(const char *const s_permission_name,
        sqlite3 *p_db = NULL;
        sqlite3_int64 permission_id = -1;
 
-       ret = rdb_begin(&p_db);
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
        if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = add_permission_internal(p_db,
@@ -332,7 +345,7 @@ int rdb_enable_app_permissions(const char *const s_app_label_name,
        const char *s_permission_type_name = app_type_name(i_permission_type);
        const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
 
-       ret = rdb_begin(&p_db);
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
        if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
@@ -386,7 +399,7 @@ int rdb_disable_app_permissions(const char *const s_app_label_name,
        int i, i_app_id;
        const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
 
-       ret = rdb_begin(&p_db);
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
        if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
@@ -425,7 +438,7 @@ int rdb_revoke_app_permissions(const char *const s_app_label_name)
        int ret = PC_ERR_DB_OPERATION;
        sqlite3 *p_db = NULL;
 
-       ret = rdb_begin(&p_db);
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
        if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = revoke_app_permissions_internal(p_db, s_app_label_name);
@@ -448,7 +461,7 @@ int rdb_reset_app_permissions(const char *const s_app_label_name)
        int ret = PC_ERR_DB_OPERATION;
        sqlite3 *p_db = NULL;
 
-       ret = rdb_begin(&p_db);
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
        if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = reset_app_permissions_internal(p_db, s_app_label_name);
@@ -468,7 +481,7 @@ int rdb_add_additional_rules(const char *const *const pp_smack_rules)
        int ret = PC_ERR_DB_OPERATION;
        sqlite3 *p_db = NULL;
 
-       ret = rdb_begin(&p_db);
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
        if(ret != PC_OPERATION_SUCCESS) goto finish;
 
        ret = add_additional_rules_internal(p_db,
@@ -477,3 +490,26 @@ int rdb_add_additional_rules(const char *const *const pp_smack_rules)
 finish:
        return rdb_finish(p_db, ret);
 }
+
+int rdb_app_has_permission(const char *const s_app_label_name,
+                          const char *const s_permission_type_name,
+                          const char *const s_permission_name,
+                          bool *const p_is_enabled)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s %s", s_app_label_name,
+                           s_permission_type_name, s_permission_name);
+       int ret = PC_ERR_DB_OPERATION;
+       sqlite3 *p_db = NULL;
+
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_SHARED_READ); //shared readonly transaction
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = check_app_has_permission_internal(p_db,
+                                               s_app_label_name,
+                                               s_permission_name,
+                                               s_permission_type_name,
+                                               p_is_enabled);
+
+finish:
+       return rdb_finish(p_db, ret);
+}