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