• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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