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 
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 
CreatClient(const char * service,const char * feature,uint32 size)84 void *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 
DestroyClient(const char * service,const char * feature,void * iproxy)109 void DestroyClient(const char *service, const char *feature, void *iproxy)
110 {
111     (void)service;
112     (void)feature;
113     free(iproxy);
114 }
115 
GetClientApi(void)116 static 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 
ReleaseClientApi(ClientApi * clientApi)133 static 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 
CreatInnerClient(const char * service,const char * feature,uint32 size)143 void *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 
DestroyInnerClient(const char * service,const char * feature,void * iproxy)172 void DestroyInnerClient(const char *service, const char *feature, void *iproxy)
173 {
174     (void)service;
175     (void)feature;
176     free(iproxy);
177 }
178 
GetInnerClientApi(void)179 static 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 
ReleaseInnerClientApi(InnerClientApi * clientApi)196 static 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 
ParsePermissions(const char * jsonStr,PermissionSaved ** perms,int * permNum)206 static 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 
Notify(IOwner owner,int code,IpcIo * reply)256 static 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 
DealQueryReply(IOwner owner,int code,IpcIo * reply)269 static 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 
CheckSelfPermission(const char * permissionName)288 int 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 
CheckPermission(int uid,const char * permissionName)308 int 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 
QueryPermission(const char * identifier,PermissionSaved ** permissions,int * permNum)329 int 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 
GrantPermission(const char * identifier,const char * permName)354 int 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 
RevokePermission(const char * identifier,const char * permName)372 int 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 
GrantRuntimePermission(int uid,const char * permissionName)390 int 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 
RevokeRuntimePermission(int uid,const char * permissionName)407 int 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 
UpdatePermissionFlags(const char * identifier,const char * permissionName,const int flags)424 int 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