1/* 2 * Copyright (c) 2020-2022 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 16#include <ohos_errno.h> 17#include <pthread.h> 18#include <securec.h> 19 20#include "cJSON.h" 21#include "iproxy_client.h" 22#include "ipc_skeleton.h" 23#include "log.h" 24#include "pms_interface.h" 25#include "pms_types.h" 26#include "registry.h" 27#include "samgr_lite.h" 28 29#define PERMISSION_SERVICE "permissionms" 30#define PERM_FEATURE "PmsFeature" 31#define PERM_INNER_FEATURE "PmsInnerFeature" 32#define MAX_DATA_LEN 0x100 33#define FIELD_PERMISSION "permissions" 34#define FIELD_NAME "name" 35#define FIELD_DESC "desc" 36#define FIELD_IS_GRANTED "isGranted" 37#define FIELD_FLAGS "flags" 38#define SYS_SVC_UID_MAX 99 39#define SYS_APP_UID_MIN 100 40#define SYS_APP_UID_MAX 999 41#define PERMISSION_NUM_MAX 1000 42 43enum FUNCID { 44 ID_CHECK_SELF = 0, 45 ID_QUERY, 46 ID_CHECK = 10, 47 ID_GRANT, 48 ID_REVOKE, 49 ID_GRANT_RUNTIME, 50 ID_REVOKE_RUNTIME, 51 ID_UPDATE_PERMS_FLAGS, 52}; 53 54typedef struct ClientApi { 55 INHERIT_CLIENT_IPROXY; 56 int (*CheckSelfPermission)(const char *permissionName); 57 int (*QueryPermission)(const char *identifier, PermissionSaved **permissions, int *permNum); 58} ClientApi; 59 60typedef struct ClientEntry { 61 INHERIT_IUNKNOWNENTRY(ClientApi); 62} ClientEntry; 63 64typedef struct InnerClientApi { 65 INHERIT_CLIENT_IPROXY; 66 int (*CheckPermission)(int uid, const char *permissionName); 67 int (*GrantPermission)(const char *identifier, const char *permName); 68 int (*RevokePermission)(const char *identifier, const char *permName); 69 int (*GrantRuntimePermission)(int uid, const char *permissionName); 70 int (*RevokeRuntimePermission)(int uid, const char *permissionName); 71 int (*UpdatePermissionFlags)(const char *identifier, const char *permissionName, int flags); 72} InnerClientApi; 73 74typedef struct ClientInnerEntry { 75 INHERIT_IUNKNOWNENTRY(InnerClientApi); 76} ClientInnerEntry; 77 78typedef struct RetOfQueryPerms { 79 int resultCode; 80 int length; 81 PermissionSaved *permission; 82} RetOfQueryPerms; 83 84void *CreatClient(const char *service, const char *feature, uint32 size) 85{ 86 (void)service; 87 (void)feature; 88 uint32 len = size + sizeof(ClientEntry); 89 if ((len < size) || (len < sizeof(ClientEntry))) { 90 return NULL; 91 } 92 uint8 *client = malloc(len); 93 if (client == NULL) { 94 return NULL; 95 } 96 (void)memset_s(client, len, 0, len); 97 ClientEntry *entry = (ClientEntry *)&client[size]; 98 entry->ver = ((uint16)CLIENT_PROXY_VER | (uint16)DEFAULT_VERSION); 99 entry->ref = 1; 100 entry->iUnknown.QueryInterface = IUNKNOWN_QueryInterface; 101 entry->iUnknown.AddRef = IUNKNOWN_AddRef; 102 entry->iUnknown.Release = IUNKNOWN_Release; 103 entry->iUnknown.Invoke = NULL; 104 entry->iUnknown.CheckSelfPermission = CheckSelfPermission; 105 entry->iUnknown.QueryPermission = QueryPermission; 106 return client; 107} 108 109void DestroyClient(const char *service, const char *feature, void *iproxy) 110{ 111 (void)service; 112 (void)feature; 113 free(iproxy); 114} 115 116static ClientApi *GetClientApi(void) 117{ 118 SAMGR_RegisterFactory(PERMISSION_SERVICE, PERM_FEATURE, CreatClient, DestroyClient); 119 ClientApi *clientApi = NULL; 120 HILOG_INFO(HILOG_MODULE_APP, "[GetFeatureApi S:%s F:%s]: BEGIN\n", PERMISSION_SERVICE, PERM_FEATURE); 121 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(PERMISSION_SERVICE, PERM_FEATURE); 122 if (iUnknown == NULL) { 123 HILOG_INFO(HILOG_MODULE_APP, "[GetFeatureApi S:%s F:%s]: error is NULL\n", PERMISSION_SERVICE, PERM_FEATURE); 124 return NULL; 125 } 126 127 (void)iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&clientApi); 128 HILOG_INFO(HILOG_MODULE_APP, "[QueryInterface CLIENT_PROXY_VER S:%s, F:%s]\n", 129 PERMISSION_SERVICE, PERM_FEATURE); 130 return clientApi; 131} 132 133static void ReleaseClientApi(ClientApi *clientApi) 134{ 135 if (clientApi == NULL) { 136 return; 137 } 138 int32 ref = clientApi->Release((IUnknown *)clientApi); 139 HILOG_INFO(HILOG_MODULE_APP, "[Release api S:%s, F:%s]: ref:%d\n", 140 PERMISSION_SERVICE, PERM_FEATURE, ref); 141} 142 143void *CreatInnerClient(const char *service, const char *feature, uint32 size) 144{ 145 (void)service; 146 (void)feature; 147 uint32 len = size + sizeof(ClientInnerEntry); 148 if ((len < size) || (len < sizeof(ClientInnerEntry))) { 149 return NULL; 150 } 151 uint8 *client = malloc(len); 152 if (client == NULL) { 153 return NULL; 154 } 155 (void)memset_s(client, len, 0, len); 156 ClientInnerEntry *entry = (ClientInnerEntry *)&client[size]; 157 entry->ver = ((uint16)CLIENT_PROXY_VER | (uint16)DEFAULT_VERSION); 158 entry->ref = 1; 159 entry->iUnknown.QueryInterface = IUNKNOWN_QueryInterface; 160 entry->iUnknown.AddRef = IUNKNOWN_AddRef; 161 entry->iUnknown.Release = IUNKNOWN_Release; 162 entry->iUnknown.Invoke = NULL; 163 entry->iUnknown.CheckPermission = CheckPermission; 164 entry->iUnknown.GrantPermission = GrantPermission; 165 entry->iUnknown.RevokePermission = RevokePermission; 166 entry->iUnknown.GrantRuntimePermission = GrantRuntimePermission; 167 entry->iUnknown.RevokeRuntimePermission = RevokeRuntimePermission; 168 entry->iUnknown.UpdatePermissionFlags = UpdatePermissionFlags; 169 return client; 170} 171 172void DestroyInnerClient(const char *service, const char *feature, void *iproxy) 173{ 174 (void)service; 175 (void)feature; 176 free(iproxy); 177} 178 179static InnerClientApi *GetInnerClientApi(void) 180{ 181 SAMGR_RegisterFactory(PERMISSION_SERVICE, PERM_INNER_FEATURE, CreatInnerClient, DestroyInnerClient); 182 InnerClientApi *clientApi = NULL; 183 HILOG_INFO(HILOG_MODULE_APP, "[GetFeatureApi S:%s F:%s]: BEGIN\n", PERMISSION_SERVICE, PERM_INNER_FEATURE); 184 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(PERMISSION_SERVICE, PERM_INNER_FEATURE); 185 if (iUnknown == NULL) { 186 HILOG_INFO(HILOG_MODULE_APP, "[GetFeatureApi S:%s F:%s]: error is NULL\n", PERMISSION_SERVICE, 187 PERM_INNER_FEATURE); 188 return NULL; 189 } 190 (void)iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&clientApi); 191 HILOG_INFO(HILOG_MODULE_APP, "[QueryInterface CLIENT_PROXY_VER S:%s, F:%s]\n", 192 PERMISSION_SERVICE, PERM_INNER_FEATURE); 193 return clientApi; 194} 195 196static void ReleaseInnerClientApi(InnerClientApi *clientApi) 197{ 198 if (clientApi == NULL) { 199 return; 200 } 201 int32 ref = clientApi->Release((IUnknown *)clientApi); 202 HILOG_INFO(HILOG_MODULE_APP, "[Release api S:%s, F:%s]: ref:%d\n", 203 PERMISSION_SERVICE, PERM_INNER_FEATURE, ref); 204} 205 206static int ParsePermissions(const char *jsonStr, PermissionSaved **perms, int *permNum) 207{ 208 cJSON *root = cJSON_Parse(jsonStr); 209 if (root == NULL) { 210 return PERM_ERRORCODE_JSONPARSE_FAIL; 211 } 212 cJSON *array = cJSON_GetObjectItem(root, FIELD_PERMISSION); 213 int pSize = cJSON_GetArraySize(array); 214 if (pSize > PERMISSION_NUM_MAX) { 215 cJSON_Delete(root); 216 return PERM_ERRORCODE_JSONPARSE_FAIL; 217 } 218 219 int allocSize = sizeof(PermissionSaved) * pSize; 220 if (allocSize == 0) { 221 cJSON_Delete(root); 222 return PERM_ERRORCODE_SUCCESS; 223 } 224 225 *perms = (PermissionSaved *) malloc(allocSize); 226 if (*perms == NULL) { 227 cJSON_Delete(root); 228 return PERM_ERRORCODE_MALLOC_FAIL; 229 } 230 for (int i = 0; i < pSize; i++) { 231 cJSON *object = cJSON_GetArrayItem(array, i); 232 cJSON *itemName = cJSON_GetObjectItem(object, FIELD_NAME); 233 cJSON *itemDesc = cJSON_GetObjectItem(object, FIELD_DESC); 234 cJSON *itemGranted = cJSON_GetObjectItem(object, FIELD_IS_GRANTED); 235 if (itemName == NULL || itemDesc == NULL || itemGranted == NULL || !cJSON_IsString(itemName) 236 || itemName->valuestring == NULL || !cJSON_IsString(itemDesc) || itemDesc->valuestring == NULL) { 237 cJSON_Delete(root); 238 free(*perms); 239 *perms = NULL; 240 return PERM_ERRORCODE_JSONPARSE_FAIL; 241 } 242 if (strcpy_s((*perms + i)->name, PERM_NAME_LEN, itemName->valuestring) != EOK 243 || strcpy_s((*perms + i)->desc, PERM_DESC_LEN, itemDesc->valuestring) != EOK) { 244 cJSON_Delete(root); 245 free(*perms); 246 *perms = NULL; 247 return PERM_ERRORCODE_COPY_ERROR; 248 } 249 (*perms + i)->granted = (enum IsGranted) itemGranted->valueint; 250 } 251 *permNum = pSize; 252 cJSON_Delete(root); 253 return PERM_ERRORCODE_SUCCESS; 254} 255 256static int Notify(IOwner owner, int code, IpcIo *reply) 257{ 258 if ((reply == NULL) || (owner == NULL)) { 259 HILOG_ERROR(HILOG_MODULE_APP, "Lite Ipc reply or owner is NULL"); 260 return OHOS_FAILURE; 261 } 262 263 int32_t *ret = (int32_t *)owner; 264 ReadInt32(reply, ret); 265 266 return EC_SUCCESS; 267} 268 269static int DealQueryReply(IOwner owner, int code, IpcIo *reply) 270{ 271 if ((reply == NULL) || (owner == NULL)) { 272 return OHOS_FAILURE; 273 } 274 int resultCode; 275 ReadInt32(reply, &resultCode); 276 RetOfQueryPerms *ret = (RetOfQueryPerms *)(owner); 277 if (resultCode != PERM_ERRORCODE_SUCCESS) { 278 ret->resultCode = resultCode; 279 return resultCode; 280 } 281 char *jsonStr = (char *)ReadString(reply, NULL); 282 HILOG_INFO(HILOG_MODULE_APP, "[perms: %s]", jsonStr); 283 int retCode = ParsePermissions(jsonStr, &(ret->permission), &(ret->length)); 284 ret->resultCode = retCode; 285 return retCode; 286} 287 288int CheckSelfPermission(const char *permissionName) 289{ 290 uid_t callingUid = getuid(); 291 if (callingUid <= SYS_APP_UID_MAX) { 292 return GRANTED; 293 } 294 ClientApi *proxy = GetClientApi(); 295 if (proxy == NULL) { 296 return OHOS_FAILURE; 297 } 298 IpcIo request; 299 char data[MAX_DATA_LEN]; 300 IpcIoInit(&request, data, MAX_DATA_LEN, 0); 301 WriteString(&request, permissionName); 302 int32_t ret = -1; 303 proxy->Invoke((IClientProxy *)proxy, ID_CHECK_SELF, &request, &ret, Notify); 304 ReleaseClientApi(proxy); 305 return ret; 306} 307 308int CheckPermission(int uid, const char *permissionName) 309{ 310 uid_t callingUid = getuid(); 311 if (callingUid <= SYS_APP_UID_MAX) { 312 return GRANTED; 313 } 314 InnerClientApi *proxy = GetInnerClientApi(); 315 if (proxy == NULL) { 316 return OHOS_FAILURE; 317 } 318 IpcIo request; 319 char data[MAX_DATA_LEN]; 320 IpcIoInit(&request, data, MAX_DATA_LEN, 0); 321 WriteInt64(&request, uid); 322 WriteString(&request, permissionName); 323 int32_t ret = -1; 324 proxy->Invoke((IClientProxy *)proxy, ID_CHECK, &request, &ret, Notify); 325 ReleaseInnerClientApi(proxy); 326 return ret; 327} 328 329int QueryPermission(const char *identifier, PermissionSaved **permissions, int *permNum) 330{ 331 ClientApi *proxy = GetClientApi(); 332 if (proxy == NULL) { 333 return OHOS_FAILURE; 334 } 335 if (permissions == NULL || permNum == NULL) { 336 return OHOS_FAILURE; 337 } 338 IpcIo request; 339 char data[MAX_DATA_LEN]; 340 IpcIoInit(&request, data, MAX_DATA_LEN, 0); 341 WriteString(&request, identifier); 342 RetOfQueryPerms ret = { 343 .resultCode = 0, 344 .length = 0, 345 .permission = NULL 346 }; 347 proxy->Invoke((IClientProxy *)proxy, ID_QUERY, &request, &ret, DealQueryReply); 348 *permissions = ret.permission; 349 *permNum = ret.length; 350 ReleaseClientApi(proxy); 351 return ret.resultCode; 352} 353 354int GrantPermission(const char *identifier, const char *permName) 355{ 356 InnerClientApi *proxy = GetInnerClientApi(); 357 if (proxy == NULL) { 358 return OHOS_FAILURE; 359 } 360 IpcIo request; 361 char data[MAX_DATA_LEN]; 362 IpcIoInit(&request, data, MAX_DATA_LEN, 0); 363 WriteString(&request, identifier); 364 WriteString(&request, permName); 365 int32_t ret = -1; 366 proxy->Invoke((IClientProxy *)proxy, ID_GRANT, &request, &ret, Notify); 367 ReleaseInnerClientApi(proxy); 368 HILOG_INFO(HILOG_MODULE_APP, "client grant[ret: %d]", ret); 369 return ret; 370} 371 372int RevokePermission(const char *identifier, const char *permName) 373{ 374 InnerClientApi *proxy = GetInnerClientApi(); 375 if (proxy == NULL) { 376 return OHOS_FAILURE; 377 } 378 IpcIo request; 379 char data[MAX_DATA_LEN]; 380 IpcIoInit(&request, data, MAX_DATA_LEN, 0); 381 WriteString(&request, identifier); 382 WriteString(&request, permName); 383 int32_t ret = -1; 384 proxy->Invoke((IClientProxy *)proxy, ID_REVOKE, &request, &ret, Notify); 385 ReleaseInnerClientApi(proxy); 386 HILOG_INFO(HILOG_MODULE_APP, "client revoke[ret: %d]", ret); 387 return ret; 388} 389 390int GrantRuntimePermission(int uid, const char *permissionName) 391{ 392 InnerClientApi *proxy = GetInnerClientApi(); 393 if (proxy == NULL) { 394 return OHOS_FAILURE; 395 } 396 IpcIo request; 397 char data[MAX_DATA_LEN]; 398 IpcIoInit(&request, data, MAX_DATA_LEN, 0); 399 WriteInt64(&request, uid); 400 WriteString(&request, permissionName); 401 int32_t ret = -1; 402 proxy->Invoke((IClientProxy *)proxy, ID_GRANT_RUNTIME, &request, &ret, Notify); 403 ReleaseInnerClientApi(proxy); 404 return ret; 405} 406 407int RevokeRuntimePermission(int uid, const char *permissionName) 408{ 409 InnerClientApi *proxy = GetInnerClientApi(); 410 if (proxy == NULL) { 411 return OHOS_FAILURE; 412 } 413 IpcIo request; 414 char data[MAX_DATA_LEN]; 415 IpcIoInit(&request, data, MAX_DATA_LEN, 0); 416 WriteInt64(&request, uid); 417 WriteString(&request, permissionName); 418 int32_t ret = -1; 419 proxy->Invoke((IClientProxy *)proxy, ID_REVOKE_RUNTIME, &request, &ret, Notify); 420 ReleaseInnerClientApi(proxy); 421 return ret; 422} 423 424int UpdatePermissionFlags(const char *identifier, const char *permissionName, const int flags) 425{ 426 InnerClientApi *proxy = GetInnerClientApi(); 427 if (proxy == NULL) { 428 return OHOS_FAILURE; 429 } 430 IpcIo request; 431 char data[MAX_DATA_LEN]; 432 IpcIoInit(&request, data, MAX_DATA_LEN, 0); 433 WriteString(&request, identifier); 434 WriteString(&request, permissionName); 435 WriteInt32(&request, flags); 436 int32_t ret = -1; 437 proxy->Invoke((IClientProxy *)proxy, ID_UPDATE_PERMS_FLAGS, &request, &ret, Notify); 438 ReleaseInnerClientApi(proxy); 439 return ret; 440} 441 442