#include "kni_utils.h" #include "kni_maat.h" extern int g_iThreadNum; /* default action: 1. read kni.conf 2. compile_id = 0 */ enum kni_action g_maat_default_action; int g_maat_default_log_option=1; struct kni_maat_handle{ Maat_feather_t feather; int tableid_intercept_ip; int tableid_intercept_domain; void *logger; }; void kni_maat_destroy(struct kni_maat_handle *handle){ if(handle != NULL){ if(handle->feather != NULL){ Maat_burn_feather(handle->feather); } } FREE(&handle); } void compile_ex_param_new(int idx, const struct Maat_rule_t* rule, const char* srv_def_large, MAAT_RULE_EX_DATA* ad, long argl, void *argp){ void *logger = argp; unsigned char tmp=0; KNI_LOG_DEBUG(logger, "call compile_ex_param_new"); if(rule->config_id == 0){ tmp=(unsigned char)rule->action; enum kni_action action = (enum kni_action)tmp; if(action==KNI_ACTION_INTERCEPT) { g_maat_default_action = KNI_ACTION_INTERCEPT; KNI_LOG_INFO(logger, "Set default intercept action to intercept."); } else { g_maat_default_action = KNI_ACTION_BYPASS; KNI_LOG_INFO(logger, "Set default intercept action to bypass."); } g_maat_default_log_option=rule->do_log; } return; } void compile_ex_param_free(int idx, const struct Maat_rule_t* rule, const char* srv_def_large, MAAT_RULE_EX_DATA* ad, long argl, void *argp){ void *logger = argp; KNI_LOG_DEBUG(logger, "call compile_ex_param_free"); return; } void compile_ex_param_dup(int idx, MAAT_RULE_EX_DATA *to, MAAT_RULE_EX_DATA *from, long argl, void *argp){ void *logger = argp; KNI_LOG_DEBUG(logger, "call compile_ex_param_dup"); return; } struct kni_maat_handle* kni_maat_init(const char* profile, void *logger){ const char *section = "maat"; int readconf_mode; char tableinfo_path[KNI_PATH_MAX]; char tablename_intercept_ip[KNI_SYMBOL_MAX]; char tablename_intercept_domain[KNI_SYMBOL_MAX]; char maatjson_path[KNI_PATH_MAX]; char redis_ip[INET_ADDRSTRLEN]; int redis_port; int redis_index; Maat_feather_t feather = NULL; int effective_interval_ms=1000;//1s int tableid_intercept_ip = -1; int tableid_intercept_domain = -1; struct kni_maat_handle *handle = NULL; int ret = MESA_load_profile_int_nodef(profile, section, "readconf_mode", &readconf_mode); if(ret < 0){ KNI_LOG_ERROR(logger, "MESA_prof_load: readconf_mode not set, profile is %s, section is %s", profile, section); goto error_out; } ret = MESA_load_profile_string_nodef(profile, section, "tableinfo_path", tableinfo_path, sizeof(tableinfo_path)); if(ret < 0){ KNI_LOG_ERROR(logger, "MESA_prof_load: tableinfo_path not set, profile is %s, section is %s", profile, section); goto error_out; } ret = MESA_load_profile_string_nodef(profile, section, "tablename_intercept_ip", tablename_intercept_ip, sizeof(tablename_intercept_ip)); if(ret < 0){ KNI_LOG_ERROR(logger, "MESA_prof_load: tablename_intercept_ip not set, profile is %s, section is %s", profile, section); goto error_out; } ret = MESA_load_profile_string_nodef(profile, section, "tablename_intercept_domain", tablename_intercept_domain, sizeof(tablename_intercept_domain)); if(ret < 0){ KNI_LOG_ERROR(logger, "MESA_prof_load: tablename_intercept_domain not set, profile is %s, section is %s", profile, section); goto error_out; } ret = MESA_load_profile_int_nodef(profile, section, "default_action", (int*)&g_maat_default_action); if(ret < 0){ KNI_LOG_ERROR(logger, "MESA_prof_load: default_action not set, profile is %s, section is %s", profile, section); goto error_out; } KNI_LOG_ERROR(logger, "MESA_prof_load, [%s]:\n readconf_mode: %d\n tableinfo_path: %s\n tablename_intercept_ip: %s\n tablename_intercept_domain: %s\n" "default_action: %d", section, readconf_mode, tableinfo_path, tablename_intercept_ip, tablename_intercept_domain, g_maat_default_action); feather = Maat_feather(g_iThreadNum, tableinfo_path, logger); handle = ALLOC(struct kni_maat_handle, 1); handle->feather = feather; if(feather == NULL){ KNI_LOG_ERROR(logger, "Failed at Maat_feather, max_thread_num is %d, tableinfo_path is %s", g_iThreadNum, tableinfo_path); return NULL; } Maat_set_feather_opt(feather, MAAT_OPT_EFFECT_INVERVAL_MS, &effective_interval_ms, sizeof(effective_interval_ms)); switch(readconf_mode){ case KNI_MAAT_READCONF_JSON: ret = MESA_load_profile_string_nodef(profile, section, "maatjson_path", maatjson_path, sizeof(maatjson_path)); if(ret < 0){ KNI_LOG_ERROR(logger, "MESA_prof_load: maatjson_path not set, profile is %s, section is %s", profile, section); goto error_out; } KNI_LOG_ERROR(logger, "MESA_prof_load, [%s]:\n maatjson_path: %s", section, maatjson_path); Maat_set_feather_opt(feather, MAAT_OPT_JSON_FILE_PATH, maatjson_path, strlen(maatjson_path)); break; case KNI_MAAT_READCONF_IRIS: break; case KNI_MAAT_READCONF_REDIS: ret = MESA_load_profile_string_nodef(profile, section, "redis_ip", redis_ip, sizeof(redis_ip)); if(ret < 0){ KNI_LOG_ERROR(logger, "MESA_prof_load: redis_ip not set, profile is %s, section is %s", profile, section); goto error_out; } ret = MESA_load_profile_int_nodef(profile, section, "redis_port", &redis_port); if(ret < 0){ KNI_LOG_ERROR(logger, "MESA_prof_load: redis_port not set, profile is %s, section is %s", profile, section); goto error_out; } ret = MESA_load_profile_int_nodef(profile, section, "redis_index", &redis_index); if(ret < 0){ KNI_LOG_ERROR(logger, "MESA_prof_load: redis_index not set, profile is %s, section is %s", profile, section); goto error_out; } KNI_LOG_ERROR(logger, "MESA_prof_load, [%s]:\n redis_ip: %s\n redis_port: %d\n redis_index: %d", section, redis_ip, redis_port, redis_index); Maat_set_feather_opt(feather, MAAT_OPT_REDIS_IP, (void*)redis_ip, strlen(redis_ip) + 1); Maat_set_feather_opt(feather, MAAT_OPT_REDIS_PORT, (void*)&redis_port, sizeof(redis_port)); Maat_set_feather_opt(feather, MAAT_OPT_REDIS_INDEX, (void*)&redis_index, sizeof(redis_index)); break; default: break; } ret = Maat_initiate_feather(feather); if(ret < 0){ KNI_LOG_ERROR(logger, "Failed at Maat_initiate_feather"); goto error_out; } tableid_intercept_ip = Maat_table_register(feather, tablename_intercept_ip); tableid_intercept_domain = Maat_table_register(feather, tablename_intercept_domain); if(tableid_intercept_ip < 0){ KNI_LOG_ERROR(logger, "Failed at Maat_table_register, tablename is %d, ret is %d", tablename_intercept_ip, tableid_intercept_ip); goto error_out; } if(tableid_intercept_domain < 0){ KNI_LOG_ERROR(logger, "Failed at Maat_table_register, tablename is %d, ret is %d", tablename_intercept_domain, tableid_intercept_domain); goto error_out; } ret = Maat_rule_get_ex_new_index(feather, "PXY_INTERCEPT_COMPILE", compile_ex_param_new, compile_ex_param_free, compile_ex_param_dup, 0, logger); if(ret < 0){ KNI_LOG_ERROR(logger, "Failed at Maat_rule_get_ex_new_index, ret is %d", ret); kni_maat_destroy(handle); goto error_out; } handle->tableid_intercept_ip = tableid_intercept_ip; handle->tableid_intercept_domain = tableid_intercept_domain; handle->logger = logger; return handle; error_out: kni_maat_destroy(handle); return NULL; } static int index_of_enforce_policy(struct Maat_rule_t* result, size_t size) { size_t i = 0; int biggest_intercept_policy_id = -1, ret_intercept_idx; int biggest_bypass_policy_id = -1, ret_bypass_idx; for(i = 0; i < size; i++) { if((unsigned char)result[i].action == KNI_ACTION_BYPASS) { if(result[i].config_id > biggest_bypass_policy_id) { biggest_bypass_policy_id = result[i].config_id; ret_bypass_idx = i; } } else { if(result[i].config_id > biggest_intercept_policy_id) { biggest_intercept_policy_id = result[i].config_id; ret_intercept_idx = i; } } } if(biggest_bypass_policy_id != -1) { return ret_bypass_idx; } else { return ret_intercept_idx; } } enum kni_action intercept_policy_scan(struct kni_maat_handle* handle, struct ipaddr *addr, char *domain, int domain_len, int thread_seq, int *policy_id, int *do_log, int *is_hit_policy){ //return KNI_ACTION_INTERCEPT; Maat_feather_t maat_feather=handle->feather; int table_intercept_ip=handle->tableid_intercept_ip; int table_intercept_domain=handle->tableid_intercept_domain; struct Maat_rule_t result[KNI_MAAT_RULE_NUM_MAX]; scan_status_t scan_mid = NULL; int scan_ret=0, hit_policy_cnt=0, enforced_policy_idx=0; //tcp: 6, udp: 17, can't be 0 scan_ret = Maat_scan_proto_addr(maat_feather, table_intercept_ip, addr, 6, result+hit_policy_cnt, KNI_MAAT_RULE_NUM_MAX-hit_policy_cnt, &scan_mid, thread_seq); if(scan_ret>0) { hit_policy_cnt+=scan_ret; } scan_ret = Maat_full_scan_string(maat_feather, table_intercept_domain, CHARSET_UTF8, domain, domain_len, result+hit_policy_cnt, NULL, KNI_MAAT_RULE_NUM_MAX-hit_policy_cnt, &scan_mid, thread_seq); if(scan_ret>0) { hit_policy_cnt+=scan_ret; } Maat_clean_status(&scan_mid); if(hit_policy_cnt>0) { enforced_policy_idx=index_of_enforce_policy(result, hit_policy_cnt); *policy_id = result[enforced_policy_idx].config_id; *do_log = result[enforced_policy_idx].do_log; *is_hit_policy=1; unsigned char action = (unsigned char)result[enforced_policy_idx].action; return (enum kni_action)action; } else { *policy_id=0; *do_log=g_maat_default_log_option; return g_maat_default_action; } } /* action 0x00: none 0x01: monitor 0x02: intercept 0x10: reject 0x30: Manipulate 0x60: steer 0x80: bypass */ char* kni_maat_action_trans(enum kni_action action){ switch(action){ case 0x00: return (char*)"none"; case 0x01: return (char*)"monitor"; case 0x02: return (char*)"intercept"; case 0x10: return (char*)"reject"; case 0x30: return (char*)"manipulate"; case 0x60: return (char*)"steer"; case 0x80: return (char*)"bypass"; default: return (char*)"unknown"; } }