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