2022-12-03 08:46:52 +00:00
|
|
|
//
|
|
|
|
// Created by xajhuang on 2022/12/2.
|
|
|
|
//
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "misc.h"
|
|
|
|
|
|
|
|
#include "proto.h"
|
|
|
|
#include "crypto.h"
|
|
|
|
#include "user_errno.h"
|
2023-02-06 07:10:02 +00:00
|
|
|
#include "zlog_module.h"
|
2023-02-27 06:10:36 +00:00
|
|
|
#ifdef JSON_SCHEMA_ON
|
2023-02-27 02:34:43 +00:00
|
|
|
#include "json_schema/jsoncdaccord.h"
|
2023-02-27 06:10:36 +00:00
|
|
|
#endif
|
2022-12-03 08:46:52 +00:00
|
|
|
#define CURRENT_PROTOCOL_VERSION (1)
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
unsigned int ver;
|
|
|
|
unsigned int cryptoType;
|
|
|
|
unsigned long long timeStamp;
|
|
|
|
unsigned int code;
|
|
|
|
cJSON *msgContend;
|
|
|
|
} PROTOCOL_WARP, *PPROTOCOL_WARP;
|
|
|
|
|
2023-02-27 02:34:43 +00:00
|
|
|
#ifdef JSON_SCHEMA_ON
|
|
|
|
typedef struct {
|
|
|
|
const char *pSchJson;
|
|
|
|
const char *pErrMsg;
|
|
|
|
} JSON_SCHEMA_CTX, *PJSON_SCHEMA_CTX;
|
|
|
|
|
|
|
|
static JSON_SCHEMA_CTX g_json_sch[] = {
|
|
|
|
{"{\"type\":\"object\",\"required\":[\"ver\"]}", "Missing required field [ver]" },
|
|
|
|
{"{\"type\":\"object\",\"required\":[\"cryptoType\"]}", "Missing required field [cryptoType]"},
|
|
|
|
{"{\"type\":\"object\",\"required\":[\"timeStamp\"]}", "Missing required field [timeStamp]" },
|
|
|
|
{"{\"type\":\"object\",\"required\":[\"msgContent\"]}", "Missing required field [msgContent]"},
|
|
|
|
};
|
|
|
|
|
2023-03-13 07:46:31 +00:00
|
|
|
static JSON_SCHEMA_CTX g_json_msg[] = {
|
|
|
|
{"{\"type\":\"object\",\"required\":[\"rangeSet\"],\"properties\":{\"rangeSet\":{\"type\":\"array\",\"minItems\":1,\"items\":{\"type\":\"object\",\"required\":[\"dhcpRange\"]}}}}", "Incorrect [rangeSet]"},
|
|
|
|
{"{\"type\":\"object\",\"required\":[\"dhcpRange\"],\"properties\":{\"dhcpRange\":{\"type\":\"array\",\"minItems\":1}}}", "Incorrect [dhcpRange]"},
|
|
|
|
{"{\"type\":\"object\",\"required\":[\"userMac\"],\"properties\":{\"userMac\":{\"type\":\"array\",\"minItems\":1}}}", "Incorrect [userMac]"},
|
|
|
|
};
|
|
|
|
|
2023-02-27 02:34:43 +00:00
|
|
|
const char *proto_schema_validation(const char *pJsonStr) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
json_object *pJs = json_tokener_parse(pJsonStr);
|
|
|
|
|
|
|
|
if (!pJs) {
|
|
|
|
cJSON *pRspRoot = cJSON_CreateObject();
|
|
|
|
cJSON_AddNumberToObject(pRspRoot, "status", ERR_JSON_PRASE_OBJ);
|
|
|
|
cJSON_AddStringToObject(pRspRoot, "message", getErrorEnumDesc(ERR_JSON_PRASE_OBJ));
|
|
|
|
return proto_create_new(pRspRoot, 200);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(g_json_sch); i++) {
|
|
|
|
json_object *pSc = json_tokener_parse(g_json_sch[i].pSchJson);
|
|
|
|
|
|
|
|
if (!pSc) {
|
|
|
|
LOG_MOD(error, ZLOG_MOD_PROTO, "Json schema format error: [%s]\n", g_json_sch[i].pSchJson);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (jdac_validate(pJs, pSc) != JDAC_ERR_VALID) {
|
|
|
|
cJSON *pRspRoot = cJSON_CreateObject();
|
|
|
|
cJSON_AddNumberToObject(pRspRoot, "status", ERR_JSON_VALID_SCH);
|
|
|
|
cJSON_AddStringToObject(pRspRoot, "message", getErrorEnumDesc(ERR_JSON_VALID_SCH));
|
|
|
|
cJSON_AddStringToObject(pRspRoot, "details", g_json_sch[i].pErrMsg);
|
|
|
|
json_object_put(pSc);
|
2023-02-27 06:10:36 +00:00
|
|
|
json_object_put(pJs);
|
2023-02-27 02:34:43 +00:00
|
|
|
return proto_create_new(pRspRoot, 200);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_object_put(pSc);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_object_put(pJs);
|
|
|
|
return NULL;
|
|
|
|
}
|
2023-03-13 07:46:31 +00:00
|
|
|
|
|
|
|
const char *proto_msg_validation(const char *pJsonStr, PROTO_POST_TYPE type_id) {
|
|
|
|
json_object *pJs = json_tokener_parse(pJsonStr);
|
|
|
|
if (!pJs) {
|
|
|
|
cJSON *pRspRoot = cJSON_CreateObject();
|
|
|
|
cJSON_AddNumberToObject(pRspRoot, "status", ERR_JSON_PRASE_OBJ);
|
|
|
|
cJSON_AddStringToObject(pRspRoot, "message", getErrorEnumDesc(ERR_JSON_PRASE_OBJ));
|
|
|
|
return proto_create_new(pRspRoot, 200);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_object *pSc = json_tokener_parse(g_json_msg[type_id].pSchJson);
|
|
|
|
if (!pSc) {
|
|
|
|
LOG_MOD(error, ZLOG_MOD_PROTO, "Json schema format error: [%s]\n", g_json_msg[type_id].pSchJson);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (jdac_validate(pJs, pSc) != JDAC_ERR_VALID) {
|
|
|
|
cJSON *pRspRoot = cJSON_CreateObject();
|
|
|
|
cJSON_AddNumberToObject(pRspRoot, "status", ERR_JSON_VALID_SCH);
|
|
|
|
cJSON_AddStringToObject(pRspRoot, "message", getErrorEnumDesc(ERR_JSON_VALID_SCH));
|
|
|
|
cJSON_AddStringToObject(pRspRoot, "details", g_json_msg[type_id].pErrMsg);
|
|
|
|
json_object_put(pSc);
|
|
|
|
json_object_put(pJs);
|
|
|
|
return proto_create_new(pRspRoot, 200);
|
|
|
|
}
|
|
|
|
|
|
|
|
json_object_put(pSc);
|
|
|
|
json_object_put(pJs);
|
|
|
|
return NULL;
|
|
|
|
}
|
2023-02-27 02:34:43 +00:00
|
|
|
#endif
|
|
|
|
|
2023-03-13 07:46:31 +00:00
|
|
|
const char *proto_decode_context(const char *pString, unsigned int *pVer,
|
|
|
|
unsigned long long *pTm, PROTO_POST_TYPE type_id, int *pErrCode) {
|
2022-12-05 10:14:07 +00:00
|
|
|
unsigned char *pBase64;
|
2022-12-06 06:58:42 +00:00
|
|
|
int decodeSize;
|
2022-12-05 10:14:07 +00:00
|
|
|
unsigned int outSize = 0;
|
|
|
|
char *pMsgContent = NULL;
|
2023-02-27 02:34:43 +00:00
|
|
|
cJSON *pRoot;
|
|
|
|
#ifdef JSON_SCHEMA_ON
|
|
|
|
const char *pSchJson;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (pErrCode == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pString == NULL || strlen(pString) == 0) {
|
|
|
|
*pErrCode = ERR_INPUT_PARAMS;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-27 06:10:36 +00:00
|
|
|
LOG_MOD(debug, ZLOG_MOD_PROTO, "Request: %s\n", pString);
|
|
|
|
|
2023-02-27 02:34:43 +00:00
|
|
|
#ifdef JSON_SCHEMA_ON
|
|
|
|
pSchJson = proto_schema_validation(pString);
|
|
|
|
if (pSchJson != NULL && strlen(pSchJson) > 0) {
|
|
|
|
*pErrCode = ERR_JSON_VALID_SCH;
|
|
|
|
return pSchJson;
|
|
|
|
}
|
|
|
|
#endif
|
2022-12-05 10:14:07 +00:00
|
|
|
|
2023-02-27 02:34:43 +00:00
|
|
|
pRoot = cJSON_Parse(pString);
|
2022-12-05 10:14:07 +00:00
|
|
|
if (!pRoot) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cJSON *pCrypto = cJSON_GetObjectItem(pRoot, "cryptoType");
|
|
|
|
|
|
|
|
if (!pCrypto) {
|
2023-02-20 09:23:21 +00:00
|
|
|
cJSON_Delete(pRoot);
|
2022-12-05 10:14:07 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pVer) {
|
|
|
|
cJSON *pObj = cJSON_GetObjectItem(pRoot, "ver");
|
|
|
|
|
|
|
|
if (pObj) {
|
|
|
|
*pVer = pObj->valueint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pTm) {
|
|
|
|
cJSON *pObj = cJSON_GetObjectItem(pRoot, "timeStamp");
|
|
|
|
|
|
|
|
if (pObj) {
|
|
|
|
*pTm = (unsigned long long)pObj->valuedouble;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 07:46:31 +00:00
|
|
|
cJSON *pMsgCtx = cJSON_GetObjectItem(pRoot, "msgContent");
|
|
|
|
char *msgCont = cJSON_Print(pMsgCtx);
|
|
|
|
|
|
|
|
#ifdef JSON_SCHEMA_ON
|
|
|
|
pSchJson = proto_msg_validation(msgCont, type_id);
|
|
|
|
free((void *)msgCont);
|
|
|
|
|
|
|
|
if (pSchJson != NULL && strlen(pSchJson) > 0) {
|
|
|
|
*pErrCode = ERR_JSON_VALID_SCH;
|
|
|
|
cJSON_Delete(pRoot);
|
|
|
|
return pSchJson;
|
|
|
|
}
|
|
|
|
#endif
|
2022-12-05 10:14:07 +00:00
|
|
|
|
|
|
|
if (!pMsgCtx) {
|
2023-02-20 09:23:21 +00:00
|
|
|
cJSON_Delete(pRoot);
|
2022-12-05 10:14:07 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (pCrypto->valueint) {
|
|
|
|
case CRYPTO_NONE:
|
2023-02-20 09:23:21 +00:00
|
|
|
pMsgContent = cJSON_Print(pMsgCtx);
|
2022-12-05 10:14:07 +00:00
|
|
|
break;
|
|
|
|
case CRYPTO_BASE64:
|
|
|
|
pMsgContent = (char *)base64_decode(pMsgCtx->valuestring, (unsigned int *)&outSize);
|
|
|
|
break;
|
|
|
|
case CRYPTO_AES128:
|
|
|
|
case CRYPTO_AES256:
|
|
|
|
case CRYPTO_3DES: {
|
|
|
|
int cryptoType;
|
|
|
|
const char *pKey = config_get_proto_crypto_key();
|
|
|
|
|
|
|
|
if (pCrypto->valueint == CRYPTO_AES128) {
|
|
|
|
cryptoType = AES128_ECB_PKCS7PADDING;
|
|
|
|
} else if (pCrypto->valueint == CRYPTO_AES256) {
|
|
|
|
cryptoType = AES256_ECB_PKCS7PADDING;
|
|
|
|
} else if (pCrypto->valueint == CRYPTO_3DES) {
|
|
|
|
cryptoType = DES3_ECB_PKCS7PADDING;
|
|
|
|
} else {
|
2023-02-20 09:23:21 +00:00
|
|
|
cJSON_Delete(pRoot);
|
2022-12-05 10:14:07 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-12-06 06:33:58 +00:00
|
|
|
pBase64 = (unsigned char *)base64_decode(pMsgCtx->valuestring, (unsigned int *)&outSize);
|
|
|
|
|
|
|
|
if (symmetric_decrypto(cryptoType, pBase64, outSize, (unsigned char **)(&pMsgContent), &decodeSize, pKey) !=
|
|
|
|
ERR_SUCCESS) {
|
2022-12-05 10:14:07 +00:00
|
|
|
free((void *)pBase64);
|
|
|
|
if (pMsgContent) {
|
|
|
|
free(pMsgContent);
|
|
|
|
}
|
2023-02-20 09:23:21 +00:00
|
|
|
cJSON_Delete(pRoot);
|
2022-12-05 10:14:07 +00:00
|
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
pMsgContent[decodeSize] = 0;
|
|
|
|
}
|
|
|
|
free((void *)pBase64);
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
|
2023-02-20 09:23:21 +00:00
|
|
|
cJSON_Delete(pRoot);
|
2022-12-05 10:14:07 +00:00
|
|
|
return pMsgContent;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *proto_create_new(cJSON *pMsgCtx, int httpCode) {
|
2022-12-03 08:46:52 +00:00
|
|
|
const char *pStrProto;
|
|
|
|
cJSON *pRoot;
|
|
|
|
PROTOCOL_WARP pro = {.ver = CURRENT_PROTOCOL_VERSION,
|
|
|
|
.cryptoType = config_get_proto_crypto_type(),
|
|
|
|
.timeStamp = get_current_time_ms(),
|
2022-12-05 10:14:07 +00:00
|
|
|
.code = httpCode};
|
2022-12-03 08:46:52 +00:00
|
|
|
|
|
|
|
pRoot = cJSON_CreateObject();
|
|
|
|
|
|
|
|
if (pRoot == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cJSON_AddNumberToObject(pRoot, "ver", pro.ver);
|
|
|
|
cJSON_AddNumberToObject(pRoot, "cryptoType", pro.cryptoType);
|
|
|
|
cJSON_AddNumberToObject(pRoot, "timeStamp", (double)pro.timeStamp);
|
|
|
|
cJSON_AddNumberToObject(pRoot, "code", pro.code);
|
|
|
|
|
|
|
|
if (pMsgCtx == NULL) {
|
|
|
|
pro.msgContend = cJSON_CreateObject();
|
2022-12-03 10:00:55 +00:00
|
|
|
} else {
|
|
|
|
pro.msgContend = pMsgCtx;
|
2022-12-03 08:46:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (pro.cryptoType) {
|
|
|
|
case CRYPTO_NONE:
|
|
|
|
cJSON_AddItemToObject(pRoot, "msgContent", pro.msgContend);
|
|
|
|
break;
|
|
|
|
case CRYPTO_BASE64: {
|
|
|
|
const char *pStrMsg = cJSON_Print(pro.msgContend);
|
|
|
|
const char *base64 = base64_encode((unsigned char *)pStrMsg, strlen(pStrMsg));
|
|
|
|
cJSON_AddStringToObject(pRoot, "msgContent", base64);
|
|
|
|
free((void *)base64);
|
2022-12-03 10:00:55 +00:00
|
|
|
cJSON_free(pro.msgContend);
|
2022-12-03 08:46:52 +00:00
|
|
|
} break;
|
|
|
|
case CRYPTO_AES128:
|
|
|
|
case CRYPTO_AES256:
|
|
|
|
case CRYPTO_3DES: {
|
2022-12-03 10:00:55 +00:00
|
|
|
int cryptoType;
|
|
|
|
const char *pKey = config_get_proto_crypto_key();
|
|
|
|
const char *base64;
|
|
|
|
const char *pStrMsg = cJSON_Print(pro.msgContend);
|
2022-12-03 08:46:52 +00:00
|
|
|
|
|
|
|
if (pro.cryptoType == CRYPTO_AES128) {
|
2022-12-03 10:00:55 +00:00
|
|
|
cryptoType = AES128_ECB_PKCS7PADDING;
|
2022-12-03 08:46:52 +00:00
|
|
|
} else if (pro.cryptoType == CRYPTO_AES256) {
|
|
|
|
cryptoType = AES256_ECB_PKCS7PADDING;
|
|
|
|
} else {
|
2022-12-03 10:00:55 +00:00
|
|
|
cryptoType = DES3_ECB_PKCS7PADDING;
|
2022-12-03 08:46:52 +00:00
|
|
|
}
|
|
|
|
|
2022-12-03 10:00:55 +00:00
|
|
|
if (pKey == NULL || strlen(pKey) == 0) {
|
2023-02-06 08:04:11 +00:00
|
|
|
LOG_MOD(error,
|
2023-02-06 07:10:02 +00:00
|
|
|
ZLOG_MOD_PROTO,
|
|
|
|
"Cryptography key empty of algorithm %d, Used default algorithm BASE64\n",
|
|
|
|
cryptoType);
|
2022-12-03 08:46:52 +00:00
|
|
|
base64 = base64_encode((unsigned char *)pStrMsg, strlen(pStrMsg));
|
|
|
|
pro.cryptoType = CRYPTO_BASE64;
|
|
|
|
} else {
|
2022-12-03 10:00:55 +00:00
|
|
|
int ret;
|
|
|
|
unsigned char *buf;
|
|
|
|
int outSize = 0;
|
|
|
|
|
2022-12-06 06:33:58 +00:00
|
|
|
ret = symmetric_encrypto(cryptoType, (unsigned char *)pStrMsg, strlen(pStrMsg), &buf, &outSize, pKey);
|
2022-12-03 10:00:55 +00:00
|
|
|
|
|
|
|
if (ret != ERR_SUCCESS) {
|
2023-02-06 08:04:11 +00:00
|
|
|
LOG_MOD(error,
|
2023-02-06 07:10:02 +00:00
|
|
|
ZLOG_MOD_PROTO,
|
|
|
|
"Unsupported protocol crypto : %d, Used default algorithm BASE64\n",
|
|
|
|
cryptoType);
|
2022-12-03 10:00:55 +00:00
|
|
|
base64 = base64_encode((unsigned char *)pStrMsg, strlen(pStrMsg));
|
|
|
|
pro.cryptoType = CRYPTO_BASE64;
|
|
|
|
} else {
|
|
|
|
base64 = base64_encode((unsigned char *)buf, outSize);
|
|
|
|
}
|
2022-12-03 08:46:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cJSON_AddStringToObject(pRoot, "msgContent", base64);
|
|
|
|
free((void *)base64);
|
2022-12-03 10:00:55 +00:00
|
|
|
cJSON_free(pro.msgContend);
|
2022-12-03 08:46:52 +00:00
|
|
|
} break;
|
|
|
|
default:
|
2023-02-06 08:04:11 +00:00
|
|
|
LOG_MOD(error,
|
2023-02-06 07:10:02 +00:00
|
|
|
ZLOG_MOD_PROTO,
|
|
|
|
"Unsupported protocol crypto algorithms: %d, Used default algorithm BASE64\n",
|
|
|
|
pro.cryptoType);
|
2022-12-03 10:00:55 +00:00
|
|
|
cJSON_free(pro.msgContend);
|
2022-12-03 08:46:52 +00:00
|
|
|
cJSON_Delete(pRoot);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-20 09:23:21 +00:00
|
|
|
pStrProto = cJSON_PrintUnformatted(pRoot);
|
2023-02-27 06:10:36 +00:00
|
|
|
LOG_MOD(debug, ZLOG_MOD_PROTO, "Create: %s\n", pStrProto);
|
2022-12-03 08:46:52 +00:00
|
|
|
|
|
|
|
cJSON_Delete(pRoot);
|
|
|
|
|
|
|
|
return pStrProto;
|
|
|
|
}
|