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