• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 #include "appspawn_message.h"
16 
17 #include <errno.h>
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #ifdef __LINUX__
23 #include <linux/capability.h>
24 #else
25 #include <sys/capability.h>
26 #endif
27 
28 #include "appspawn_server.h"
29 #include "cJSON.h"
30 #include "ohos_errno.h"
31 #include "securec.h"
32 
33 static const size_t MAX_BUNDLE_NAME_LEN = 127;
34 static const size_t MIN_BUNDLE_NAME_LEN = 7;
35 static const size_t MAX_IDENTITY_ID_LEN = 24;
36 static const size_t MIN_IDENTITY_ID_LEN = 1;
37 static const size_t MAX_CAPABILITY_COUNT = 10;
38 
FreeMessageSt(MessageSt * targetSt)39 void FreeMessageSt(MessageSt *targetSt)
40 {
41     if (targetSt != NULL) {
42         if (targetSt->bundleName != NULL) {
43             free(targetSt->bundleName);
44             targetSt->bundleName = NULL;
45         }
46 
47         if (targetSt->identityID != NULL) {
48             free(targetSt->identityID);
49             targetSt->identityID = NULL;
50         }
51 
52         if (targetSt->caps != NULL) {
53             free(targetSt->caps);
54             targetSt->caps = NULL;
55         }
56 
57         targetSt->uID = -1;
58         targetSt->gID = -1;
59         targetSt->capsCnt = 0;
60     }
61 }
62 
ReadStringItem(cJSON * strItem,char ** buf,size_t maxLen,size_t minLen)63 static enum OHOSLiteErrorCode ReadStringItem(cJSON *strItem, char **buf, size_t maxLen, size_t minLen)
64 {
65     if (strItem == NULL || !cJSON_IsString(strItem)) {
66         return EC_INVALID;
67     }
68 
69     char *strPtr = cJSON_GetStringValue(strItem);
70     if (strPtr == NULL) {
71         return EC_PROTOCOL;
72     }
73 
74     size_t strLength = strlen(strPtr);
75     if (strLength > maxLen || strLength < minLen) {
76         return EC_PROTOCOL;
77     }
78 
79     char *bufTmp = (char *)malloc(strLength + 1);
80     if (bufTmp == NULL) {
81         return EC_NOMEMORY;
82     }
83 
84     if (strLength > 0 && memcpy_s(bufTmp, strLength, strPtr, strLength) != EOK) {
85         free(bufTmp);
86         bufTmp = NULL;
87         return EC_FAILURE;
88     }
89 
90     bufTmp[strLength] = '\0';
91     *buf = bufTmp;
92     return EC_SUCCESS;
93 }
94 
ReadNumberItem(cJSON * strItem)95 static double ReadNumberItem(cJSON *strItem)
96 {
97     if (strItem == NULL || !cJSON_IsNumber(strItem)) {
98         return -1;
99     }
100 
101     return cJSON_GetNumberValue(strItem);
102 }
103 
GetCaps(const cJSON * curItem,MessageSt * msgSt)104 static int GetCaps(const cJSON *curItem, MessageSt *msgSt)
105 {
106     msgSt->capsCnt = 0;
107     msgSt->caps = NULL;
108     cJSON *capItem = cJSON_GetObjectItem(curItem, "capability");
109     if (!cJSON_IsArray(capItem)) {
110         APPSPAWN_LOGE("[appspawn] GetCaps failed, no caps array found.");
111         return EC_INVALID;
112     }
113 
114     // caps array empty, means do not need any capability
115     int capsCnt = cJSON_GetArraySize(capItem);
116     if (capsCnt <= 0) {
117         return EC_SUCCESS;
118     }
119 
120     if (capsCnt > MAX_CAPABILITY_COUNT) {
121         APPSPAWN_LOGE("[appspawn] GetCaps, too many caps[cnt %d], max %d",
122             capsCnt, MAX_CAPABILITY_COUNT);
123         return EC_INVALID;
124     }
125 
126     msgSt->caps = (unsigned int *)malloc(sizeof(unsigned int) * capsCnt);
127     if (msgSt->caps == NULL) {
128         APPSPAWN_LOGE("[appspawn] GetCaps, malloc failed! capsCnt[cnt %d].", capsCnt);
129         return EC_NOMEMORY;
130     }
131 
132     for (int i = 0; i < capsCnt; ++i) {
133         cJSON *capJ = cJSON_GetArrayItem(capItem, i);
134         if (!cJSON_IsNumber(capJ) || cJSON_GetNumberValue(capJ) < 0) {
135             APPSPAWN_LOGE("[appspawn] GetCaps, invalid cap value detected!");
136             free(msgSt->caps);
137             msgSt->caps = NULL;
138             return EC_INVALID;
139         }
140         msgSt->caps[i] = (unsigned int)cJSON_GetNumberValue(capJ);
141         if (msgSt->caps[i] > CAP_LAST_CAP) {
142             APPSPAWN_LOGE("[appspawn] GetCaps, invalid cap value %u detected!", \
143                 msgSt->caps[i]);
144             free(msgSt->caps);
145             msgSt->caps = NULL;
146             return EC_INVALID;
147         }
148     }
149 
150     msgSt->capsCnt = capsCnt;
151     return EC_SUCCESS;
152 }
153 
SplitMessage(const char * msg,unsigned int msgLen,MessageSt * msgSt)154 int SplitMessage(const char *msg, unsigned int msgLen, MessageSt *msgSt)
155 {
156     if (msgSt == NULL) {
157         return EC_INVALID;
158     }
159 
160     if (msg == NULL || msgLen == 0) {
161         FreeMessageSt(msgSt);
162         return EC_INVALID;
163     }
164 
165     cJSON *rootJ = cJSON_ParseWithLength(msg, msgLen);
166     if (rootJ == NULL) {
167         FreeMessageSt(msgSt);
168         return EC_PROTOCOL;
169     }
170 
171     cJSON *bundleNameItem = cJSON_GetObjectItem(rootJ, "bundleName");
172     int ret = (int)ReadStringItem(bundleNameItem, &(msgSt->bundleName), MAX_BUNDLE_NAME_LEN, MIN_BUNDLE_NAME_LEN);
173     if (ret != EC_SUCCESS) {
174         FreeMessageSt(msgSt);
175         cJSON_Delete(rootJ);
176         return ret;
177     }
178 
179     cJSON *identityIDItem = cJSON_GetObjectItem(rootJ, "identityID");
180     ret = (int)ReadStringItem(identityIDItem, &(msgSt->identityID), MAX_IDENTITY_ID_LEN, MIN_IDENTITY_ID_LEN);
181     if (ret != EC_SUCCESS) {
182         FreeMessageSt(msgSt);
183         cJSON_Delete(rootJ);
184         return ret;
185     }
186 
187     cJSON *uIDItem = cJSON_GetObjectItem(rootJ, "uID");
188     cJSON *gIDItem = cJSON_GetObjectItem(rootJ, "gID");
189     msgSt->uID = (int)ReadNumberItem(uIDItem);
190     msgSt->gID = (int)ReadNumberItem(gIDItem);
191 
192     ret = GetCaps(rootJ, msgSt);
193     if (ret != EC_SUCCESS) {
194         FreeMessageSt(msgSt);
195         cJSON_Delete(rootJ);
196         return ret;
197     }
198 
199     cJSON_Delete(rootJ);
200 
201     if (msgSt->uID <= 0 || msgSt->gID <= 0 || msgSt->uID == INT_MAX || msgSt->gID == INT_MAX) {
202         FreeMessageSt(msgSt);
203         return EC_PROTOCOL;
204     }
205     return EC_SUCCESS;
206 }
207