Implement perm_app_get_permissions() API in libprivilege-control.
authorDamian Chromejko <d.chromejko@samsung.com>
Fri, 22 Nov 2013 11:49:10 +0000 (12:49 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 30 Jan 2014 11:47:56 +0000 (12:47 +0100)
[Issue#]       SSDWSSP-669
[Bug/Feature]  Add function to get a list of all permissions of a given
               type for the specified application.
[Cause]        Extending provided API.
[Solution]     Added a chain of functions extending existing API with
               necessary features.
[Verification] Build, install, run tests.

Change-Id: I0b3335191e50e954f95804463a2e073f1715e9db

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 20e2d90..d3dbce6 100644 (file)
@@ -329,6 +329,23 @@ int perm_app_has_permission(const char *pkg_id,
                            bool *is_enabled);
 
 /**
+ * Get permissions for the specified app.
+ *
+ * In case of success caller is responsible for freeing memory allocated by it.
+ * Each cell in *ppp_perm_list except for the last (NULL) should be freed, followed by freeing
+ * *ppp_perm_list itself.
+ *
+ * In case of error an error code is returned and, provided that ppp_perm_list is not NULL,
+ * *ppp_perm_list is set to NULL.
+ *
+ * @param  pkg_id        application identifier
+ * @param  app_type      application type
+ * @param  ppp_perm_list buffer for return value
+ * @return               PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int perm_app_get_permissions(const char *pkg_id, app_type_t app_type, char ***ppp_perm_list);
+
+/**
  * 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 0071961..7d619be 100644 (file)
@@ -304,6 +304,37 @@ int check_app_has_permission_internal(sqlite3 *p_db,
 
 
 /**
+ * Get number of permission of a certain type for the specified app.
+ *
+ * @param  p_db                   pointer to a SQLite3 database object
+ * @param  s_app_label_name       application label's name
+ * @param  s_permission_type_name permission type's name
+ * @param  p_num_permissions      buffer for return value
+ * @return                        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int get_app_permissions_number_internal(sqlite3  *p_db,
+                                       const char *const s_app_label_name,
+                                       const char *const s_permission_type_name,
+                                       int *const p_num_permissions);
+
+/**
+ * Get permissions for the specified app.
+ *
+ * @param  p_db                   pointer to a SQLite3 database object
+ * @param  s_app_label_name       application label's name
+ * @param  s_permission_type_name permission type's name
+ * @param  i_num_permissions      number of permissions of the specified type
+ * @param  ppp_perm_list          buffer for return value
+ * @return                        PC_OPERATION_SUCCESS on success, error code otherwise
+ */
+int get_app_permissions_internal(sqlite3 *p_db,
+                                const char *const s_app_label_name,
+                                const char *const s_permission_type_name,
+                                const int i_num_permissions,
+                                char ***ppp_perm_list);
+
+
+/**
  * Gets the internal app id of an application with a given name.
  *
  * @ingroup RDB internal functions
index 6b0102a..11570e5 100644 (file)
@@ -231,4 +231,20 @@ int rdb_app_has_permission(const char *const s_app_label_name,
                           const char *const s_permission_name,
                           bool *const p_is_enabled);
 
+
+/**
+ * Get permissions for the specified app.
+ *
+ * @ingroup RDB API functions
+ *
+ * @param  s_app_label_name       application label's name
+ * @param  s_permission_type_name permission type's name
+ * @param  ppp_perm_list          buffer for return value
+ * @return                        PC_OPERATION_SUCCESS on success,
+ *                                error code otherwise
+ */
+int rdb_app_get_permissions(const char *const s_app_label_name,
+                           const char *const s_permission_type_name,
+                           char ***ppp_perm_list);
+
 #endif /*_RULES_DB_H_*/
index 42625ce..cb373b8 100644 (file)
@@ -1027,6 +1027,40 @@ API int perm_app_has_permission(const char *pkg_id,
        return rdb_app_has_permission(pkg_id, app_group, permission_name, is_enabled);
 }
 
+API int perm_app_get_permissions(const char *pkg_id, app_type_t app_type, char ***ppp_perm_list)
+{
+       SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d", __func__, pkg_id,
+                     app_type);
+
+       const char *app_group = app_type_group_name(app_type);
+       int ret;
+
+       if (ppp_perm_list == NULL) {
+               C_LOGE("Invalid param ppp_perm_list (NULL).");
+               return PC_ERR_INVALID_PARAM;
+       }
+       // Set the given pointer to NULL in case of future failure.
+       *ppp_perm_list = NULL;
+
+       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;
+       }
+
+       ret = rdb_app_get_permissions(pkg_id, app_group, ppp_perm_list);
+       if (ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("RDB rdb_app_get_permissions failed with: %d", ret);
+               return ret;
+       }
+
+       return PC_OPERATION_SUCCESS;
+}
+
 API int app_label_dir(const char* label, const char* path)//deprecated
 {
        SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
index dbc3de9..b4ed4ae 100644 (file)
@@ -1024,6 +1024,121 @@ finish:
        return ret;
 }
 
+
+int get_app_permissions_number_internal(sqlite3  *p_db, const char *const s_app_label_name,
+                                       const char *const s_permission_type_name,
+                                       int *const p_num_permissions)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s", s_app_label_name, s_permission_type_name);
+
+       int ret;
+       int sql_ret;
+       sqlite3_stmt *p_stmt = NULL;
+
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "SELECT COUNT(name)         \
+                           FROM   app_permission_view \
+                           WHERE  app_name = %Q AND   \
+                                  is_enabled = 1 AND  \
+                                  type_name = %Q",
+                          s_app_label_name, s_permission_type_name);
+       if (ret != PC_OPERATION_SUCCESS) goto finish;
+
+       sql_ret = sqlite3_step(p_stmt);
+       if (sql_ret == SQLITE_ROW) {
+               ret = PC_OPERATION_SUCCESS;
+               *p_num_permissions = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
+       } else if(sql_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_permissions_internal(sqlite3 *p_db,
+                                const char *const s_app_label_name,
+                                const char *const s_permission_type_name,
+                                const int i_num_permissions,
+                                char ***ppp_perm_list)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s %d", s_app_label_name, s_permission_type_name,
+                           i_num_permissions);
+
+       int ret;
+       int sql_ret = SQLITE_DONE;
+       int allocated_permissions = 0;
+       int i;
+       sqlite3_stmt *p_stmt = NULL;
+
+       // Allocate an array for permissions (+1 for NULL pointer terminating *ppp_perm_list).
+       *ppp_perm_list = (char **) malloc(sizeof **ppp_perm_list * (i_num_permissions + 1));
+       if (*ppp_perm_list == NULL) {
+               C_LOGE("Cannot allocate memory");
+               return PC_ERR_MEM_OPERATION;
+       }
+
+       // Get the permissions themselves.
+       ret = prepare_stmt(p_db, &p_stmt,
+                          "SELECT name                \
+                           FROM   app_permission_view \
+                           WHERE  app_name = %Q AND   \
+                                  is_enabled = 1 AND  \
+                                  type_name = %Q",
+                          s_app_label_name, s_permission_type_name);
+       if (ret != PC_OPERATION_SUCCESS) goto finish;
+
+       for (i = 0; i < i_num_permissions; ++i) {
+               if ((sql_ret = sqlite3_step(p_stmt)) != SQLITE_ROW) break;
+
+               (*ppp_perm_list)[i] = strdup((const char *) sqlite3_column_text(p_stmt,
+                                       RDB_FIRST_COLUMN));
+
+               if ((*ppp_perm_list)[i] == NULL) {
+                       ret = PC_ERR_MEM_OPERATION;
+                       goto finish;
+               }
+
+               ++allocated_permissions;
+       }
+       (*ppp_perm_list)[allocated_permissions] = NULL;
+
+       if (allocated_permissions == i_num_permissions) {
+               ret = PC_OPERATION_SUCCESS;
+       } else if (sql_ret == SQLITE_BUSY) {
+               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 (ret != PC_OPERATION_SUCCESS) {
+               for (i = 0; i < allocated_permissions; ++i) {
+                       free((*ppp_perm_list)[i]);
+               }
+               free(*ppp_perm_list);
+               *ppp_perm_list = NULL;
+       }
+
+       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)
index 6bf9b1a..26e84e5 100644 (file)
@@ -547,3 +547,32 @@ int rdb_app_has_permission(const char *const s_app_label_name,
 finish:
        return rdb_finish(p_db, ret);
 }
+
+int rdb_app_get_permissions(const char *const s_app_label_name,
+                           const char *const s_permission_type_name,
+                           char ***ppp_perm_list)
+{
+       RDB_LOG_ENTRY_PARAM("%s %s", s_app_label_name, s_permission_type_name);
+
+       int ret = PC_ERR_DB_OPERATION;
+       int i_num_permissions;
+       sqlite3 *p_db = NULL;
+
+       ret = rdb_begin(&p_db, RDB_TRANSACTION_SHARED_READ);
+       if(ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = get_app_permissions_number_internal(p_db,
+                                                 s_app_label_name,
+                                                 s_permission_type_name,
+                                                 &i_num_permissions);
+       if (ret != PC_OPERATION_SUCCESS) goto finish;
+
+       ret = get_app_permissions_internal(p_db,
+                                          s_app_label_name,
+                                          s_permission_type_name,
+                                          i_num_permissions,
+                                          ppp_perm_list);
+
+finish:
+       return rdb_finish(p_db, ret);
+}