startup_appspawn/lite/appspawn_message.c
xlei1030 f7b7dddb2b appspawn归一化
Signed-off-by: xlei1030 <xionglei6@huawei.com>
2022-04-27 09:23:43 +08:00

205 lines
5.7 KiB
C

/*
* 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 <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#ifdef __LINUX__
#include <linux/capability.h>
#else
#include <sys/capability.h>
#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;
}