/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "appspawn_message.h" #include #include #include #include #ifdef __LINUX__ #include #else #include #endif #include "appspawn_server.h" #include "cJSON.h" #include "ohos_errno.h" #include "securec.h" static const size_t MAX_BUNDLE_NAME_LEN = 127; static const size_t MIN_BUNDLE_NAME_LEN = 7; static const size_t MAX_IDENTITY_ID_LEN = 24; static const size_t MIN_IDENTITY_ID_LEN = 1; static const size_t MAX_CAPABILITY_COUNT = 10; void FreeMessageSt(MessageSt *targetSt) { if (targetSt != NULL) { if (targetSt->bundleName != NULL) { free(targetSt->bundleName); targetSt->bundleName = NULL; } if (targetSt->identityID != NULL) { free(targetSt->identityID); targetSt->identityID = NULL; } if (targetSt->caps != NULL) { free(targetSt->caps); targetSt->caps = NULL; } targetSt->uID = -1; targetSt->gID = -1; targetSt->capsCnt = 0; } } static enum OHOSLiteErrorCode ReadStringItem(cJSON *strItem, char **buf, size_t maxLen, size_t minLen) { if (strItem == NULL || !cJSON_IsString(strItem)) { return EC_INVALID; } char *strPtr = cJSON_GetStringValue(strItem); if (strPtr == NULL) { return EC_PROTOCOL; } size_t strLength = strlen(strPtr); if (strLength > maxLen || strLength < minLen) { return EC_PROTOCOL; } char *bufTmp = (char *)malloc(strLength + 1); if (bufTmp == NULL) { return EC_NOMEMORY; } if (strLength > 0 && memcpy_s(bufTmp, strLength, strPtr, strLength) != EOK) { free(bufTmp); bufTmp = NULL; return EC_FAILURE; } bufTmp[strLength] = '\0'; *buf = bufTmp; return EC_SUCCESS; } static double ReadNumberItem(cJSON *strItem) { if (strItem == NULL || !cJSON_IsNumber(strItem)) { return -1; } return cJSON_GetNumberValue(strItem); } static int GetCaps(const cJSON *curItem, MessageSt *msgSt) { msgSt->capsCnt = 0; msgSt->caps = NULL; cJSON *capItem = cJSON_GetObjectItem(curItem, "capability"); if (!cJSON_IsArray(capItem)) { APPSPAWN_LOGE("[appspawn] GetCaps failed, no caps array found."); return EC_INVALID; } // caps array empty, means do not need any capability int capsCnt = cJSON_GetArraySize(capItem); if (capsCnt <= 0) { return EC_SUCCESS; } if (capsCnt > MAX_CAPABILITY_COUNT) { APPSPAWN_LOGE("[appspawn] GetCaps, too many caps[cnt %d], max %d", capsCnt, MAX_CAPABILITY_COUNT); return EC_INVALID; } msgSt->caps = (unsigned int *)malloc(sizeof(unsigned int) * capsCnt); if (msgSt->caps == NULL) { APPSPAWN_LOGE("[appspawn] GetCaps, malloc failed! capsCnt[cnt %d].", capsCnt); return EC_NOMEMORY; } for (int i = 0; i < capsCnt; ++i) { cJSON *capJ = cJSON_GetArrayItem(capItem, i); if (!cJSON_IsNumber(capJ) || cJSON_GetNumberValue(capJ) < 0) { APPSPAWN_LOGE("[appspawn] GetCaps, invalid cap value detected!"); free(msgSt->caps); msgSt->caps = NULL; return EC_INVALID; } msgSt->caps[i] = (unsigned int)cJSON_GetNumberValue(capJ); if (msgSt->caps[i] > CAP_LAST_CAP) { APPSPAWN_LOGE("[appspawn] GetCaps, invalid cap value %u detected!", \ msgSt->caps[i]); free(msgSt->caps); msgSt->caps = NULL; return EC_INVALID; } } msgSt->capsCnt = capsCnt; return EC_SUCCESS; } int SplitMessage(const char *msg, unsigned int msgLen, MessageSt *msgSt) { if (msgSt == NULL) { return EC_INVALID; } if (msg == NULL || msgLen == 0) { FreeMessageSt(msgSt); return EC_INVALID; } cJSON *rootJ = cJSON_ParseWithLength(msg, msgLen); if (rootJ == NULL) { FreeMessageSt(msgSt); return EC_PROTOCOL; } cJSON *bundleNameItem = cJSON_GetObjectItem(rootJ, "bundleName"); int ret = (int)ReadStringItem(bundleNameItem, &(msgSt->bundleName), MAX_BUNDLE_NAME_LEN, MIN_BUNDLE_NAME_LEN); if (ret != EC_SUCCESS) { FreeMessageSt(msgSt); cJSON_Delete(rootJ); return ret; } cJSON *identityIDItem = cJSON_GetObjectItem(rootJ, "identityID"); ret = (int)ReadStringItem(identityIDItem, &(msgSt->identityID), MAX_IDENTITY_ID_LEN, MIN_IDENTITY_ID_LEN); if (ret != EC_SUCCESS) { FreeMessageSt(msgSt); cJSON_Delete(rootJ); return ret; } cJSON *uIDItem = cJSON_GetObjectItem(rootJ, "uID"); cJSON *gIDItem = cJSON_GetObjectItem(rootJ, "gID"); msgSt->uID = (int)ReadNumberItem(uIDItem); msgSt->gID = (int)ReadNumberItem(gIDItem); ret = GetCaps(rootJ, msgSt); if (ret != EC_SUCCESS) { FreeMessageSt(msgSt); cJSON_Delete(rootJ); return ret; } cJSON_Delete(rootJ); if (msgSt->uID <= 0 || msgSt->gID <= 0 || msgSt->uID == INT_MAX || msgSt->gID == INT_MAX) { FreeMessageSt(msgSt); return EC_PROTOCOL; } return EC_SUCCESS; }