2022-11-17 05:05:35 +08:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* File : maat_utils . cpp
* Description :
* Authors : Liu WenTan < liuwentan @ geedgenetworks . com >
* Date : 2022 - 10 - 31
* Copyright : ( c ) 2018 - 2022 Geedge Networks , Inc . All rights reserved .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
2022-11-25 16:32:29 +08:00
# include <stdio.h>
# include <string.h>
2022-12-09 17:12:18 +08:00
# include <assert.h>
2022-11-25 16:32:29 +08:00
# include <sys/stat.h>
2022-12-09 17:12:18 +08:00
# include <sys/syscall.h>
2022-12-03 22:23:41 +08:00
# include <zlib.h>
# include <openssl/md5.h>
# include <openssl/evp.h>
2022-11-25 16:32:29 +08:00
2022-12-05 23:21:18 +08:00
# include "utils.h"
2022-11-17 05:05:35 +08:00
# include "maat_utils.h"
2022-12-09 17:12:18 +08:00
pid_t gettid ( )
{
return syscall ( SYS_gettid ) ;
}
const char * module_name_str ( const char * name )
{
static __thread char module [ 64 ] ;
snprintf ( module , sizeof ( module ) , " %s(%d) " , name , gettid ( ) ) ;
return module ;
}
2022-11-25 16:32:29 +08:00
char * maat_strdup ( const char * s )
{
if ( NULL = = s ) {
return NULL ;
}
2022-12-03 22:23:41 +08:00
2022-11-25 16:32:29 +08:00
char * d = ( char * ) malloc ( strlen ( s ) + 1 ) ;
memcpy ( d , s , strlen ( s ) + 1 ) ;
return d ;
}
int get_column_pos ( const char * line , int column_seq , size_t * offset , size_t * len )
2022-11-17 05:05:35 +08:00
{
2022-12-03 22:23:41 +08:00
int i = 0 ;
int ret = - 1 ;
char * str = NULL ;
char * saveptr = NULL ;
char * subtoken = NULL ;
const char * seps = " \t " ;
2022-11-25 16:32:29 +08:00
char * dup_line = maat_strdup ( line ) ;
2022-12-03 22:23:41 +08:00
2022-11-25 16:32:29 +08:00
for ( str = dup_line ; ; str = NULL ) {
2022-11-17 05:05:35 +08:00
subtoken = strtok_r ( str , seps , & saveptr ) ;
if ( subtoken = = NULL )
break ;
2022-11-25 16:32:29 +08:00
if ( i = = column_seq - 1 ) {
* offset = subtoken - dup_line ;
* len = strlen ( subtoken ) ;
ret = 0 ;
2022-11-17 05:05:35 +08:00
break ;
}
i + + ;
}
2022-12-05 23:21:18 +08:00
FREE ( dup_line ) ;
2022-11-25 16:32:29 +08:00
2022-11-17 05:05:35 +08:00
return ret ;
2022-11-25 16:32:29 +08:00
}
int load_file_to_memory ( const char * file_name , unsigned char * * pp_out , size_t * out_sz )
{
int ret = 0 ;
FILE * fp = NULL ;
struct stat fstat_buf ;
2022-12-03 22:23:41 +08:00
size_t read_size = 0 ;
2022-11-25 16:32:29 +08:00
ret = stat ( file_name , & fstat_buf ) ;
if ( ret ! = 0 ) {
return - 1 ;
}
fp = fopen ( file_name , " r " ) ;
if ( fp = = NULL ) {
return - 1 ;
}
* out_sz = fstat_buf . st_size ;
* pp_out = ( unsigned char * ) calloc ( 1 , * out_sz + 1 ) ;
read_size = fread ( * pp_out , 1 , * out_sz , fp ) ;
if ( read_size ! = * out_sz ) {
2022-12-05 23:21:18 +08:00
FREE ( * pp_out ) ;
2022-11-25 16:32:29 +08:00
return - 1 ;
}
fclose ( fp ) ;
fp = NULL ;
return 0 ;
}
static char * strchr_esc ( char * s , const char delim )
{
char * token = NULL ;
if ( NULL = = s ) {
return NULL ;
}
for ( token = s ; * token ! = ' \0 ' ; token + + ) {
if ( * token = = ' \\ ' ) {
token + + ;
continue ;
}
if ( * token = = delim ) {
break ;
}
}
if ( * token = = ' \0 ' ) {
return NULL ;
} else {
return token ;
}
}
char * strtok_r_esc ( char * s , const char delim , char * * save_ptr )
{
char * token = NULL ;
if ( NULL = = s ) {
s = * save_ptr ;
}
/* Scan leading delimiters. */
token = strchr_esc ( s , delim ) ;
if ( NULL = = token ) {
* save_ptr = token ;
return s ;
}
/* Find the end of the token. */
* token = ' \0 ' ;
token + + ;
* save_ptr = token ;
return s ;
}
char * str_unescape_and ( char * s )
{
size_t i = 0 ;
size_t j = 0 ;
for ( i = 0 , j = 0 ; i < strlen ( s ) ; i + + ) {
if ( s [ i ] = = ' \\ ' & & s [ i + 1 ] = = ' & ' ) {
s [ j ] = ' & ' ;
i + + ;
j + + ;
} else {
s [ j ] = s [ i ] ;
j + + ;
}
}
s [ j ] = ' \0 ' ;
return s ;
}
char * str_unescape ( char * s )
{
size_t i = 0 ;
size_t j = 0 ;
for ( i = 0 , j = 0 ; i < strlen ( s ) ; i + + ) {
if ( s [ i ] = = ' \\ ' ) {
switch ( s [ i + 1 ] ) {
case ' & ' :
s [ j ] = ' & ' ;
break ;
case ' b ' :
s [ j ] = ' ' ; //space,0x20;
break ;
case ' \\ ' :
s [ j ] = ' \\ ' ;
break ;
default :
s [ j ] = s [ i ] ;
i - - ; //undo the followed i++
break ;
}
i + + ;
j + + ;
} else {
s [ j ] = s [ i ] ;
j + + ;
}
}
s [ j ] = ' \0 ' ;
return s ;
2022-11-29 14:12:40 +08:00
}
# define MAX_SYSTEM_CMD_LEN 512
int system_cmd_mkdir ( const char * path )
{
char cmd [ MAX_SYSTEM_CMD_LEN ] = { 0 } ;
snprintf ( cmd , sizeof ( cmd ) , " mkdir -p %s " , path ) ;
return system ( cmd ) ;
2022-12-03 22:23:41 +08:00
}
2022-12-05 23:21:18 +08:00
int system_cmd_rmdir ( const char * dir )
{
char cmd [ MAX_SYSTEM_CMD_LEN ] = { 0 } ;
snprintf ( cmd , sizeof ( cmd ) , " rm %s -rf " , dir ) ;
return system ( cmd ) ;
}
2022-12-03 22:23:41 +08:00
char * md5_file ( const char * filename , char * md5string )
{
unsigned char md5 [ MD5_DIGEST_LENGTH ] = { 0 } ;
struct stat file_info ;
stat ( filename , & file_info ) ;
size_t file_size = file_info . st_size ;
FILE * fp = fopen ( filename , " r " ) ;
if ( NULL = = fp ) {
return NULL ;
}
char * file_buff = ( char * ) malloc ( file_size ) ;
fread ( file_buff , 1 , file_size , fp ) ;
fclose ( fp ) ;
MD5 ( ( const unsigned char * ) ( file_buff ) , ( unsigned long ) ( file_size ) , md5 ) ;
for ( int i = 0 ; i < MD5_DIGEST_LENGTH ; + + i ) {
sprintf ( & md5string [ i * 2 ] , " %02x " , ( unsigned int ) md5 [ i ] ) ;
}
2022-12-05 23:21:18 +08:00
FREE ( file_buff ) ;
2022-12-03 22:23:41 +08:00
return md5string ;
}
int crypt_memory ( const unsigned char * inbuf , size_t inlen , unsigned char * * pp_out , size_t * out_sz ,
const char * key , const char * algorithm , int do_encrypt ,
char * err_str , size_t err_str_sz )
{
OpenSSL_add_all_algorithms ( ) ;
const EVP_CIPHER * cipher = EVP_get_cipherbyname ( algorithm ) ;
if ( NULL = = cipher ) {
snprintf ( err_str , err_str_sz , " Cipher %s is not supported. " , algorithm ) ;
return 0 ;
}
const EVP_MD * dgst = EVP_get_digestbyname ( " md5 " ) ;
if ( NULL = = dgst ) {
snprintf ( err_str , err_str_sz , " Get MD5 object failed. " ) ;
return 0 ;
}
const unsigned char * salt = NULL ;
unsigned char cipher_key [ EVP_MAX_KEY_LENGTH ] ;
unsigned char cipher_iv [ EVP_MAX_IV_LENGTH ] ;
memset ( cipher_key , 0 , sizeof ( cipher_key ) ) ;
memset ( cipher_iv , 0 , sizeof ( cipher_iv ) ) ;
int ret = EVP_BytesToKey ( cipher , dgst , salt , ( unsigned char * ) key ,
strlen ( ( const char * ) key ) , 1 , cipher_key , cipher_iv ) ;
if ( 0 = = ret ) {
snprintf ( err_str , err_str_sz , " Key and IV generatioin failed. " ) ;
return 0 ;
}
/* Don't set key or IV right away; we want to check lengths */
EVP_CIPHER_CTX * ctx = EVP_CIPHER_CTX_new ( ) ;
EVP_CipherInit_ex ( ctx , cipher , NULL , NULL , NULL , do_encrypt ) ;
OPENSSL_assert ( EVP_CIPHER_CTX_key_length ( ctx ) % 16 = = 0 ) ;
OPENSSL_assert ( EVP_CIPHER_CTX_iv_length ( ctx ) = = 16 ) ;
/* Now we can set key and IV */
//It should be set to 1 for encryption, 0 for decryption and -1 to leave the value unchanged (the actual value of 'enc' being supplied in a previous call).
EVP_CipherInit_ex ( ctx , NULL , NULL , cipher_key , cipher_iv , - 1 ) ;
int out_blk_len = 0 ;
int out_buff_offset = 0 ;
int out_buff_len = inlen + EVP_CIPHER_block_size ( cipher ) - 1 ;
* pp_out = ( unsigned char * ) malloc ( out_buff_len * sizeof ( unsigned char ) ) ;
if ( ! EVP_CipherUpdate ( ctx , * pp_out + out_buff_offset , & out_blk_len , inbuf , inlen ) ) {
snprintf ( err_str , err_str_sz , " EVP_CipherUpdate failed. " ) ;
EVP_CIPHER_CTX_free ( ctx ) ;
goto error_out ;
}
out_buff_offset + = out_blk_len ;
if ( ! EVP_CipherFinal_ex ( ctx , * pp_out + out_buff_offset , & out_blk_len ) ) {
snprintf ( err_str , err_str_sz , " EVP_CipherFinal_ex failed. Maybe password is wrong? " ) ;
EVP_CIPHER_CTX_free ( ctx ) ;
goto error_out ;
}
out_buff_offset + = out_blk_len ;
EVP_CIPHER_CTX_free ( ctx ) ;
* out_sz = out_buff_offset ;
return 0 ;
error_out :
2022-12-05 23:21:18 +08:00
FREE ( * pp_out ) ;
2022-12-03 22:23:41 +08:00
return - 1 ;
}
int decrypt_open ( const char * file_name , const char * key , const char * algorithm ,
unsigned char * * pp_out , size_t * out_sz , char * err_str , size_t err_str_sz )
{
size_t file_sz = 0 ;
unsigned char * file_buff = NULL ;
int ret = load_file_to_memory ( file_name , & file_buff , & file_sz ) ;
if ( ret < 0 ) {
return - 1 ;
}
ret = crypt_memory ( file_buff , file_sz , pp_out , out_sz , key , algorithm , 0 , err_str , err_str_sz ) ;
2022-12-05 23:21:18 +08:00
FREE ( file_buff ) ;
2022-12-03 22:23:41 +08:00
return ret ;
}
int gzip_uncompress_one_try ( const unsigned char * in_compressed_data , size_t in_compressed_sz ,
unsigned char * * out_uncompressed_data , size_t * out_uncompressed_sz )
{
z_stream strm ;
strm . zalloc = NULL ;
strm . zfree = NULL ;
strm . opaque = NULL ;
strm . avail_in = in_compressed_sz ;
strm . avail_out = * out_uncompressed_sz ;
strm . next_in = ( Bytef * ) in_compressed_data ;
strm . next_out = * out_uncompressed_data ;
int ret = - 1 ;
ret = inflateInit2 ( & strm , MAX_WBITS + 16 ) ;
if ( ret = = Z_OK ) {
ret = inflate ( & strm , Z_FINISH ) ;
if ( ret = = Z_STREAM_END ) {
* out_uncompressed_sz = strm . total_out ;
ret = inflateEnd ( & strm ) ;
return ret ;
}
}
inflateEnd ( & strm ) ;
return ret ;
}
int gzip_uncompress ( const unsigned char * in_compressed_data , size_t in_compressed_sz ,
unsigned char * * out_uncompressed_data , size_t * out_uncompressed_sz )
{
int z_result ;
int ret = - 1 ;
size_t buffer_sz = in_compressed_sz * 2 ;
* out_uncompressed_data = ( unsigned char * ) malloc ( buffer_sz ) ;
do {
* out_uncompressed_sz = buffer_sz ;
z_result = gzip_uncompress_one_try ( in_compressed_data , in_compressed_sz ,
out_uncompressed_data , out_uncompressed_sz ) ;
switch ( z_result ) {
case Z_OK :
ret = 0 ;
break ;
case Z_BUF_ERROR :
buffer_sz * = 2 ;
* out_uncompressed_data = ( unsigned char * ) realloc ( * out_uncompressed_data , buffer_sz ) ;
break ;
default :
ret = - 1 ;
break ;
}
} while ( z_result = = Z_BUF_ERROR ) ;
return ret ;
}
size_t memcat ( void * * dest , size_t offset , size_t * n_dest , const void * src , size_t n_src )
{
if ( * n_dest < offset + n_src ) {
* n_dest = ( offset + n_src ) * 2 ;
* dest = realloc ( * dest , sizeof ( char ) * ( * n_dest ) ) ;
}
memcpy ( ( char * ) * dest + offset , src , n_src ) ;
return n_src ;
}
2022-12-09 17:12:18 +08:00
enum maat_ip_format ip_format_str2int ( const char * format )
{
if ( 0 = = strcasecmp ( format , " range " ) ) {
return IP_FORMAT_RANGE ;
} else if ( 0 = = strcasecmp ( format , " mask " ) ) {
return IP_FORMAT_MASK ;
} else if ( 0 = = strcasecmp ( format , " CIDR " ) ) {
return IP_FORMAT_CIDR ;
} else {
assert ( 0 ) ;
}
return IP_FORMAT_UNKNOWN ;
}
int ip_format2range ( int ip_type , enum maat_ip_format format , const char * ip1 , const char * ip2 ,
uint32_t range_begin [ ] , uint32_t range_end [ ] )
{
int cidr = 0 ;
int ret = 0 ;
if ( ip_type ! = 4 & & ip_type ! = 6 ) {
assert ( 0 ) ;
return - 1 ;
}
if ( ip_type = = 4 ) {
uint32_t ipv4_addr = 0 ;
ret = inet_pton ( AF_INET , ip1 , & ipv4_addr ) ;
if ( ret < = 0 ) {
return - 1 ;
}
ipv4_addr = ntohl ( ipv4_addr ) ;
uint32_t ipv4_range_end = 0 ;
uint32_t ipv4_mask = 0 ;
switch ( format ) {
case IP_FORMAT_RANGE :
range_begin [ 0 ] = ipv4_addr ;
ret = inet_pton ( AF_INET , ip2 , & ipv4_range_end ) ;
if ( ret < = 0 ) {
return - 1 ;
}
ipv4_range_end = ntohl ( ipv4_range_end ) ;
range_end [ 0 ] = ipv4_range_end ;
break ;
case IP_FORMAT_MASK :
ret = inet_pton ( AF_INET , ip2 , & ipv4_mask ) ;
if ( ret < = 0 ) {
return - 1 ;
}
ipv4_mask = ntohl ( ipv4_mask ) ;
range_begin [ 0 ] = ipv4_addr & ipv4_mask ;
range_end [ 0 ] = ipv4_addr | ~ ipv4_mask ;
break ;
case IP_FORMAT_CIDR :
cidr = atoi ( ip2 ) ;
if ( cidr > 32 | | cidr < 0 ) {
return - 1 ;
}
ipv4_mask = ( 0xFFFFFFFFUL < < ( 32 - cidr ) ) & 0xFFFFFFFFUL ;
range_begin [ 0 ] = ipv4_addr & ipv4_mask ;
range_end [ 0 ] = ipv4_addr | ~ ipv4_mask ;
break ;
default :
assert ( 0 ) ;
}
} else {
//ipv6
int i = 0 ;
uint32_t ipv6_addr [ 4 ] = { 0 } ;
uint32_t ipv6_mask [ 4 ] = { 0 } ;
uint32_t ipv6_range_end [ 4 ] = { 0 } ;
ret = inet_pton ( AF_INET6 , ip1 , ipv6_addr ) ;
if ( ret < = 0 ) {
return - 1 ;
}
ipv6_ntoh ( ipv6_addr ) ;
switch ( format ) {
case IP_FORMAT_RANGE :
ret = inet_pton ( AF_INET6 , ip2 , ipv6_range_end ) ;
if ( ret < = 0 ) {
return - 1 ;
}
ipv6_ntoh ( ipv6_range_end ) ;
memcpy ( range_begin , ipv6_addr , sizeof ( ipv6_addr ) ) ;
memcpy ( range_end , ipv6_range_end , sizeof ( ipv6_range_end ) ) ;
break ;
case IP_FORMAT_MASK :
ret = inet_pton ( AF_INET6 , ip2 , ipv6_mask ) ;
if ( ret < = 0 ) {
return - 1 ;
}
ipv6_ntoh ( ipv6_mask ) ;
for ( i = 0 ; i < 4 ; i + + ) {
range_begin [ i ] = ipv6_addr [ i ] & ipv6_mask [ i ] ;
range_end [ i ] = ipv6_addr [ i ] | ~ ipv6_mask [ i ] ;
}
break ;
case IP_FORMAT_CIDR :
cidr = atoi ( ip2 ) ;
if ( cidr > 128 | | cidr < 0 ) {
return - 1 ;
}
for ( i = 0 ; i < 4 ; i + + ) {
int bit32 = 128 - cidr - 32 * ( 3 - i ) ;
if ( bit32 < 0 ) {
bit32 = 0 ;
}
ipv6_mask [ i ] = ( 0xFFFFFFFFUL < < bit32 ) & 0xFFFFFFFFUL ;
range_begin [ i ] = ipv6_addr [ i ] & ipv6_mask [ i ] ;
range_end [ i ] = ipv6_addr [ i ] | ~ ipv6_mask [ i ] ;
}
break ;
default :
assert ( 0 ) ;
}
}
return 0 ;
}