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 [ ] = {
2023-03-15 10:12:07 +00:00
{ " { \" type \" : \" object \" , \" required \" :[ \" ver \" ], \" properties \" :{ \" ver \" :{ \" type \" : \" integer \" }}} " , " Incorrect field [ver] " } ,
{ " { \" type \" : \" object \" , \" required \" :[ \" cryptoType \" ], \" properties \" :{ \" cryptoType \" :{ \" type \" : \" integer \" , \" minimum \" :0, \" maximum \" :4}}} " , " Incorrect field [cryptoType] " } ,
{ " { \" type \" : \" object \" , \" required \" :[ \" timeStamp \" ], \" properties \" :{ \" timeStamp \" :{ \" type \" : \" integer \" }}} " , " Incorrect field [timeStamp] " } ,
2023-02-27 02:34:43 +00:00
{ " { \" type \" : \" object \" , \" required \" :[ \" msgContent \" ]} " , " Missing required field [msgContent] " } ,
} ;
const char * proto_schema_validation ( const char * pJsonStr ) {
int i ;
json_object * pJs = json_tokener_parse ( pJsonStr ) ;
if ( ! pJs ) {
cJSON * pRspRoot = cJSON_CreateObject ( ) ;
2023-03-15 10:12:07 +00:00
cJSON_AddNumberToObject ( pRspRoot , " status " , ERR_JSON_PARSE_OBJ ) ;
cJSON_AddStringToObject ( pRspRoot , " message " , getErrorEnumDesc ( ERR_JSON_PARSE_OBJ ) ) ;
2023-02-27 02:34:43 +00:00
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
2023-03-15 10:12:07 +00:00
const char * proto_msg_validation ( const char * pJsonStr , const char * msgJson ) {
2023-03-13 07:46:31 +00:00
json_object * pJs = json_tokener_parse ( pJsonStr ) ;
if ( ! pJs ) {
cJSON * pRspRoot = cJSON_CreateObject ( ) ;
2023-03-15 10:12:07 +00:00
cJSON_AddNumberToObject ( pRspRoot , " status " , ERR_JSON_PARSE_OBJ ) ;
cJSON_AddStringToObject ( pRspRoot , " message " , getErrorEnumDesc ( ERR_JSON_PARSE_OBJ ) ) ;
2023-03-13 07:46:31 +00:00
return proto_create_new ( pRspRoot , 200 ) ;
}
2023-03-15 10:12:07 +00:00
json_object * pSc = json_tokener_parse ( msgJson ) ;
2023-03-13 07:46:31 +00:00
if ( ! pSc ) {
2023-03-15 10:12:07 +00:00
LOG_MOD ( error , ZLOG_MOD_PROTO , " Json schema format error: [%s] \n " , msgJson ) ;
2023-03-13 07:46:31 +00:00
}
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 ) ) ;
2023-03-15 10:12:07 +00:00
cJSON_AddStringToObject ( pRspRoot , " details " , getErrorEnumDesc ( ERR_MSG_CONTENT ) ) ;
2023-03-13 07:46:31 +00:00
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-15 10:12:07 +00:00
const char * proto_decode_context ( const char * pString , unsigned int * pVer , unsigned long long * pTm , int * pErrCode ) {
cJSON * pMsgCtx ;
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
2023-03-15 10:12:07 +00:00
const char * pSchJson ;
2023-02-27 02:34:43 +00:00
# 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-15 10:12:07 +00:00
pMsgCtx = cJSON_GetObjectItem ( pRoot , " msgContent " ) ;
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 ;
}