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 33static const size_t MAX_BUNDLE_NAME_LEN = 127; 34static const size_t MIN_BUNDLE_NAME_LEN = 7; 35static const size_t MAX_IDENTITY_ID_LEN = 24; 36static const size_t MIN_IDENTITY_ID_LEN = 1; 37static const size_t MAX_CAPABILITY_COUNT = 10; 38 39void 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 63static 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 95static double ReadNumberItem(cJSON *strItem) 96{ 97 if (strItem == NULL || !cJSON_IsNumber(strItem)) { 98 return -1; 99 } 100 101 return cJSON_GetNumberValue(strItem); 102} 103 104static 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 154int 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