1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include <pthread.h> 16#include <stdlib.h> 17 18#ifndef APPSPAWN_CLIENT 19#include "appspawn_sandbox.h" 20#endif 21#include "appspawn_client.h" 22#include "appspawn_mount_permission.h" 23#include "appspawn_msg.h" 24#include "appspawn_permission.h" 25#include "appspawn_utils.h" 26#include "json_utils.h" 27#include "securec.h" 28 29typedef struct TagParseJsonContext { 30 SandboxQueue permissionQueue; 31 int32_t maxPermissionIndex; 32 uint32_t inited; 33 AppSpawnClientType type; 34} ParseJsonContext, PermissionManager; 35 36static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 37static PermissionManager g_permissionMgr[CLIENT_MAX] = {}; 38 39#ifdef APPSPAWN_SANDBOX_NEW 40static int ParseAppSandboxConfig(const cJSON *root, PermissionManager *mgr) 41{ 42 // conditional 43 cJSON *json = cJSON_GetObjectItemCaseSensitive(root, "conditional"); 44 APPSPAWN_CHECK(json != NULL, return 0, "No found conditional in config"); 45 46 // permission 47 cJSON *config = cJSON_GetObjectItemCaseSensitive(json, "permission"); 48 APPSPAWN_CHECK(config != NULL && cJSON_IsArray(config), return 0, "No found permission in config"); 49 50 uint32_t configSize = cJSON_GetArraySize(config); 51 for (uint32_t i = 0; i < configSize; i++) { 52 json = cJSON_GetArrayItem(config, i); 53 char *name = GetStringFromJsonObj(json, "name"); 54 APPSPAWN_CHECK(name != NULL, break, "No found name in config"); 55 56 int ret = AddSandboxPermissionNode(name, &mgr->permissionQueue); 57 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 58 } 59 return 0; 60} 61 62static PermissionManager *GetPermissionMgrByType(AppSpawnClientType type) 63{ 64 APPSPAWN_CHECK_ONLY_EXPER(type < CLIENT_MAX, return NULL); 65 g_permissionMgr[type].type = type; 66 return &g_permissionMgr[type]; 67} 68#else 69 70static int ParsePermissionConfig(const cJSON *permissionConfigs, PermissionManager *mgr) 71{ 72 cJSON *config = NULL; 73 cJSON_ArrayForEach(config, permissionConfigs) 74 { 75 const char *name = config->string; 76 int ret = AddSandboxPermissionNode(name, &mgr->permissionQueue); 77 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 78 } 79 return 0; 80} 81 82static int ParseAppSandboxConfig(const cJSON *appSandboxConfig, PermissionManager *mgr) 83{ 84 cJSON *configs = cJSON_GetObjectItemCaseSensitive(appSandboxConfig, "permission"); 85 APPSPAWN_CHECK(configs != NULL && cJSON_IsArray(configs), return 0, "No permission in json"); 86 87 int ret = 0; 88 uint32_t configSize = (uint32_t)cJSON_GetArraySize(configs); 89 for (uint32_t i = 0; i < configSize; i++) { 90 cJSON *json = cJSON_GetArrayItem(configs, i); 91 ret = ParsePermissionConfig(json, mgr); 92 APPSPAWN_CHECK(ret == 0, return ret, "Parse permission config fail result: %{public}d ", ret); 93 } 94 return ret; 95} 96 97static PermissionManager *GetPermissionMgrByType(AppSpawnClientType type) 98{ 99 APPSPAWN_CHECK_ONLY_EXPER(type < CLIENT_MAX, return NULL); 100 g_permissionMgr[0].type = CLIENT_FOR_APPSPAWN; 101 return &g_permissionMgr[0]; 102} 103#endif 104 105static int LoadPermissionConfig(PermissionManager *mgr) 106{ 107 int ret = ParseJsonConfig("etc/sandbox", 108 mgr->type == CLIENT_FOR_APPSPAWN ? APP_SANDBOX_FILE_NAME : WEB_SANDBOX_FILE_NAME, ParseAppSandboxConfig, mgr); 109 APPSPAWN_CHECK(ret == 0, return ret, "Load sandbox fail %{public}d", ret); 110 mgr->maxPermissionIndex = PermissionRenumber(&mgr->permissionQueue); 111 return 0; 112} 113 114static inline int32_t CheckPermissionManager(PermissionManager *mgr) 115{ 116 if (mgr != NULL && mgr->inited) { 117 return 1; 118 } 119 return 0; 120} 121 122static int32_t PMGetPermissionIndex(AppSpawnClientType type, const char *permission) 123{ 124 PermissionManager *mgr = GetPermissionMgrByType(type); 125 APPSPAWN_CHECK_ONLY_EXPER(CheckPermissionManager(mgr), return INVALID_PERMISSION_INDEX); 126 return GetPermissionIndexInQueue((SandboxQueue *)&mgr->permissionQueue, permission); 127} 128 129static int32_t PMGetMaxPermissionIndex(AppSpawnClientType type) 130{ 131 PermissionManager *mgr = GetPermissionMgrByType(type); 132 APPSPAWN_CHECK_ONLY_EXPER(CheckPermissionManager(mgr), return INVALID_PERMISSION_INDEX); 133 return mgr->maxPermissionIndex; 134} 135 136static const char *PMGetPermissionByIndex(AppSpawnClientType type, int32_t index) 137{ 138 PermissionManager *mgr = GetPermissionMgrByType(type); 139 APPSPAWN_CHECK_ONLY_EXPER(CheckPermissionManager(mgr), return NULL); 140 if (mgr->maxPermissionIndex <= index) { 141 return NULL; 142 } 143 const SandboxPermissionNode *node = GetPermissionNodeInQueueByIndex((SandboxQueue *)&mgr->permissionQueue, index); 144 return PERMISSION_NAME(node); 145} 146 147APPSPAWN_STATIC int LoadPermission(AppSpawnClientType type) 148{ 149 APPSPAWN_LOGW("LoadPermission %{public}d", type); 150 pthread_mutex_lock(&g_mutex); 151 PermissionManager *mgr = GetPermissionMgrByType(type); 152 if (mgr == NULL) { 153 pthread_mutex_unlock(&g_mutex); 154 return APPSPAWN_ARG_INVALID; 155 } 156 157 if (mgr->inited) { 158 pthread_mutex_unlock(&g_mutex); 159 return 0; 160 } 161 mgr->maxPermissionIndex = -1; 162 mgr->permissionQueue.type = 0; 163 OH_ListInit(&mgr->permissionQueue.front); 164 int ret = LoadPermissionConfig(mgr); 165 if (ret == 0) { 166 mgr->inited = 1; 167 } 168 pthread_mutex_unlock(&g_mutex); 169 return ret; 170} 171 172APPSPAWN_STATIC void DeletePermission(AppSpawnClientType type) 173{ 174 pthread_mutex_lock(&g_mutex); 175 PermissionManager *mgr = GetPermissionMgrByType(type); 176 if (mgr == NULL || !mgr->inited) { 177 pthread_mutex_unlock(&g_mutex); 178 return; 179 } 180 DeleteSandboxPermissions(&mgr->permissionQueue); 181 mgr->maxPermissionIndex = -1; 182 mgr->inited = 0; 183 pthread_mutex_unlock(&g_mutex); 184} 185 186int32_t GetPermissionMaxCount() 187{ 188 int32_t maxCount = 0; 189 for (uint32_t i = 0; i < CLIENT_MAX; i++) { 190 int32_t max = PMGetMaxPermissionIndex(i); 191 if (max > maxCount) { 192 maxCount = max; 193 } 194 } 195 return maxCount; 196} 197 198int32_t GetPermissionIndex(AppSpawnClientHandle handle, const char *permission) 199{ 200 APPSPAWN_CHECK(permission != NULL, return INVALID_PERMISSION_INDEX, "Invalid permission name"); 201 if (handle == NULL) { 202 return PMGetPermissionIndex(CLIENT_FOR_APPSPAWN, permission); 203 } 204 AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle; 205 return PMGetPermissionIndex(reqMgr->type, permission); 206} 207 208int32_t GetMaxPermissionIndex(AppSpawnClientHandle handle) 209{ 210 if (handle == NULL) { 211 return PMGetMaxPermissionIndex(CLIENT_FOR_APPSPAWN); 212 } 213 AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle; 214 return PMGetMaxPermissionIndex(reqMgr->type); 215} 216 217const char *GetPermissionByIndex(AppSpawnClientHandle handle, int32_t index) 218{ 219 if (handle == NULL) { 220 return PMGetPermissionByIndex(CLIENT_FOR_APPSPAWN, index); 221 } 222 AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle; 223 return PMGetPermissionByIndex(reqMgr->type, index); 224} 225 226__attribute__((constructor)) static void LoadPermissionModule(void) 227{ 228 (void)LoadPermission(CLIENT_FOR_APPSPAWN); 229 (void)LoadPermission(CLIENT_FOR_NWEBSPAWN); 230} 231 232__attribute__((destructor)) static void DeletePermissionModule(void) 233{ 234 DeletePermission(CLIENT_FOR_APPSPAWN); 235 DeletePermission(CLIENT_FOR_NWEBSPAWN); 236}