#include "MESA_handle_logger.h" #include "config_monitor.h" #include "Maat_rule_internal.h" #include #include #include #include #include #define module_config_monitor (module_name_str("MAAT_FILE_MONITOR")) #define CM_UPDATE_TYPE_ERR -1 #define CM_UPDATE_TYPE_NONE 0 #define CM_MAX_TABLE_NUM 256 #define MAX_CONFIG_FN_LEN 256 #define MAX_CONFIG_LINE 1024*4 #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif //#define USING_DICTATOR 1 extern "C" void __real_free(void*p); struct cm_table_info_t { char table_name[MAX_CONFIG_FN_LEN]; char cfg_path[MAX_CONFIG_FN_LEN]; int cfg_num; char encryp_algorithm[MAX_CONFIG_FN_LEN]; }; int decrypt_open(FILE* in,const unsigned char* key, const char* algorithm,unsigned char**pp_out,void *logger) { unsigned char inbuf[MAX_CONFIG_LINE]; int inlen, out_blk_len=0; int out_buff_len=0,buff_offset=0; EVP_CIPHER_CTX *ctx; 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)); const EVP_CIPHER *cipher; const EVP_MD *dgst=NULL; const unsigned char *salt=NULL; int ret=0; OpenSSL_add_all_algorithms(); cipher=EVP_get_cipherbyname(algorithm); if(cipher==NULL) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor,"Not cipher:%s not supported.",algorithm); return 0; } dgst=EVP_get_digestbyname("md5"); if(dgst==NULL) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor,"Get MD5 object failed."); return 0; } ret=EVP_BytesToKey(cipher,dgst,salt,key,strlen((const char*)key),1,cipher_key,cipher_iv); if(ret==0) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor,"Key and IV generatioin failed."); return 0; } /* Don't set key or IV right away; we want to check lengths */ ctx = EVP_CIPHER_CTX_new(); EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL,0); OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16); OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16); /* Now we can set key and IV */ EVP_CipherInit_ex(ctx, NULL, NULL, cipher_key, cipher_iv, 0); out_buff_len=16*1024; *pp_out=(unsigned char*)malloc(out_buff_len*sizeof(unsigned char)); for (;;) { inlen = fread(inbuf, 1, MAX_CONFIG_LINE, in); if (inlen <= 0) break; if(out_buff_len-buff_offset= DIR_ENT_SIZE) { DIR_ENT_SIZE+=ENLARGE_STEP; list=(struct dirent **)realloc((void*)list,DIR_ENT_SIZE*sizeof(struct dirent *)); } } closedir(od); *namelist = list; if(compar) qsort((void *)*namelist,n,sizeof(struct dirent *),compar); return n; } int filter_fn(const struct dirent * ent) { // files in xfs are not DT_REG. // if(ent->d_type != DT_REG) // return 0; return (strncmp(ent->d_name,"full_config_index",strlen("full_config_index")) == 0|| strncmp(ent->d_name,"inc_config_index",strlen("inc_config_index")) == 0); } int get_new_idx_path(unsigned int current_version,const char*file_dir,void* logger,char*** idx_path,int*idx_num) { struct dirent **namelist; int n=0,i=0,sscanf_ret; char update_str[32]={0}; unsigned int latest_ful_version=0,latest_inc_version=0; unsigned int config_seq=0; int *inc_file_idx; int full_file_idx=0,inc_idx_num=0,path_len=0; int update_type=CM_UPDATE_TYPE_NONE; n = my_scandir(file_dir, &namelist, filter_fn, (int (*)(const void*, const void*))alphasort); if (n < 0) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor,"scan dir error"); update_type=CM_UPDATE_TYPE_ERR; return update_type; } inc_file_idx=(int*)calloc(sizeof(int),n); inc_idx_num=0; for(i=0;id_name, ".") == 0) || (strcmp(namelist[i]->d_name, "..") == 0)) { continue; } if(strlen(namelist[i]->d_name)>32) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor ,"config file %s filename too long,should like full_config_index.0000000001" ,namelist[i]->d_name); continue; } sscanf_ret=sscanf(namelist[i]->d_name,"%[a-zA-Z]_config_index.%u",update_str,&config_seq); if(sscanf_ret!=2) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor ,"config file %s filename error,should like full_config_index.0000000001" ,namelist[i]->d_name); continue; } if(strncasecmp(update_str,"full",strlen(update_str))==0) { if(config_seq>latest_ful_version) { latest_ful_version=config_seq; full_file_idx=i; } } else if(strncasecmp(update_str,"inc",strlen(update_str))==0) { if(config_seq>current_version) { inc_file_idx[inc_idx_num]=i; inc_idx_num++; if(config_seq>latest_inc_version) { latest_inc_version=config_seq; } } } else { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor ,"config file %s,not full or inc config" ,namelist[i]->d_name); } } //full update if(latest_ful_version>current_version) { *idx_path=(char**)malloc(sizeof(char**)); path_len=strlen(file_dir)+strlen(namelist[full_file_idx]->d_name)+1+1; (*idx_path)[0]=(char*)malloc(path_len); snprintf((*idx_path)[0],path_len,"%s/%s",file_dir,namelist[full_file_idx]->d_name); *idx_num=1; update_type=CM_UPDATE_TYPE_FULL; } //inc update,it's possible that do inc after full update in this function,but we'll process it at next call. else if(latest_inc_version>current_version) { *idx_path=(char**)malloc(sizeof(char**)*inc_idx_num); for(i=0;id_name)+1+1; (*idx_path)[i]=(char*)malloc(path_len); snprintf((*idx_path)[i],path_len,"%s/%s",file_dir,namelist[inc_file_idx[i]]->d_name); } *idx_num=inc_idx_num; update_type=CM_UPDATE_TYPE_INC; } else { update_type=CM_UPDATE_TYPE_NONE; } free(inc_file_idx); for(i=0;i=0)//jump over empty line { i++; } if(i==size) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor ,"Too much lines in %s",path); break; } } fclose(fp); return i; } int cm_read_table_file(struct cm_table_info_t* index, int (*update)(const char*,const char*,void*), void* u_para, const unsigned char* key, void* logger) { int cfg_num=0,i=0; int ret=0; char line[MAX_CONFIG_LINE]={0},*ret_str=NULL; unsigned char* decrypt_buff=NULL; int decrypt_len=0,do_decrypt=0,decrypt_offset=0; FILE*fp=fopen(index->cfg_path,"r"); if(fp==NULL) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor,"update error,open %s failed.",index->cfg_path); return -1; } if(strlen(index->encryp_algorithm)>0) { if(key==NULL||strlen((const char*)key)==0) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor,"update error,no key to decrypt %s.",index->cfg_path); return -1; } decrypt_len=decrypt_open(fp, key,index->encryp_algorithm, &decrypt_buff,logger); if(decrypt_len==0) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor,"update error,%s decrypt failed.",index->cfg_path); return -1; } read_nxt_line_from_buff(decrypt_buff, decrypt_len, &decrypt_offset, line, sizeof(line)); sscanf(line,"%d\n",&cfg_num); do_decrypt=1; } else { fscanf(fp,"%d\n",&cfg_num); } if(cfg_num!=index->cfg_num) { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor ,"file %s config num not matched",index->cfg_path); fclose(fp); return -1; } for(i=0;icfg_path,i,cfg_num); break; } if(line[sizeof(line)-1]!='\0') { MESA_handle_runtime_log(logger,RLOG_LV_FATAL,module_config_monitor , "update error,line size more than %u at of file %s:%d", sizeof(line),index->cfg_path,i); continue; } ret=update(index->table_name,line,u_para); if(ret<0) { break; } } fclose(fp); if(decrypt_buff!=NULL) { free(decrypt_buff); } return 0; } const char* path2filename(const char*path) { int i=0; for(i=strlen(path);i>0;i--) { if(path[i]=='/') { break; } } return path+i+1; } void config_monitor_traverse(unsigned int version,const char*idx_dir, void (*start)(unsigned int ,int ,void*), int (*update)(const char* ,const char*,void* ), void (*finish)(void*), void* u_para, const unsigned char* dec_key, void* logger) { int update_type=CM_UPDATE_TYPE_NONE; unsigned int new_version=0; char**idx_path_array=NULL; const char* table_filename=NULL; char str_not_care[256]={0}; int idx_num=0,table_num=0,i=0,j=0; struct cm_table_info_t table_array[CM_MAX_TABLE_NUM]; update_type=get_new_idx_path(version, idx_dir,logger, &idx_path_array, &idx_num); if(update_type==CM_UPDATE_TYPE_FULL||update_type==CM_UPDATE_TYPE_INC) { for(i=0;i