diff --git a/common/include/tfe_http.h b/common/include/tfe_http.h index 99480c6..ce352cc 100644 --- a/common/include/tfe_http.h +++ b/common/include/tfe_http.h @@ -453,6 +453,18 @@ static inline int tfe_http_in_response(enum tfe_http_event events) return !(tfe_http_in_request(events)); } +static inline int tfe_http_in_hdr(enum tfe_http_event events) +{ + if ((events & EV_HTTP_REQ_HDR) | (events & EV_HTTP_REQ_END)) + { + return 1; + } + else + { + return 0; + } +} + static inline struct tfe_http_half* tfe_http_session_request_duplicate(struct tfe_http_session * session) { struct http_field_name in_header_field{}; diff --git a/plugin/business/pangu-http/src/pangu_http.cpp b/plugin/business/pangu-http/src/pangu_http.cpp index bd8dbab..4e144a4 100644 --- a/plugin/business/pangu-http/src/pangu_http.cpp +++ b/plugin/business/pangu-http/src/pangu_http.cpp @@ -112,6 +112,7 @@ struct policy_action_param char *message; char *position; + float enforcement_ratio; int profile_id; int status_code; @@ -524,6 +525,15 @@ void policy_action_param_new(int idx, const struct Maat_rule_t* rule, const char { param->message = tfe_strdup(item->valuestring); } + item=cJSON_GetObjectItem(json,"enforcement_ratio"); + if(item && item->type==cJSON_Number) + { + param->enforcement_ratio = item->valueint; + } + else + { + param->enforcement_ratio = 1; + } break; case MA_ACTION_BLOCK: item=cJSON_GetObjectItem(json,"code"); @@ -543,6 +553,15 @@ void policy_action_param_new(int idx, const struct Maat_rule_t* rule, const char } break; case MA_ACTION_REPLACE: + item=cJSON_GetObjectItem(json,"enforcement_ratio"); + if(item && item->type==cJSON_Number) + { + param->enforcement_ratio = item->valueint; + } + else + { + param->enforcement_ratio = 1; + } rules = cJSON_GetObjectItem(json, "rules"); if(rules == NULL) { @@ -571,6 +590,15 @@ void policy_action_param_new(int idx, const struct Maat_rule_t* rule, const char if(item && item->type==cJSON_Number){ param->profile_id = item->valueint; } + item=cJSON_GetObjectItem(json,"enforcement_ratio"); + if(item && item->type==cJSON_Number) + { + param->enforcement_ratio = item->valueint; + } + else + { + param->enforcement_ratio = 1; + } break; case MA_ACTION_INSERT: item=cJSON_GetObjectItem(json,"insert_profile"); @@ -581,6 +609,15 @@ void policy_action_param_new(int idx, const struct Maat_rule_t* rule, const char if(item && item->type==cJSON_String){ param->position = tfe_strdup(item->valuestring); } + item=cJSON_GetObjectItem(json,"enforcement_ratio"); + if(item && item->type==cJSON_Number) + { + param->enforcement_ratio = item->valueint; + } + else + { + param->enforcement_ratio = 1; + } break; default: assert(0); break; @@ -1042,6 +1079,7 @@ struct pangu_http_ctx struct evbuffer* log_req_body, *log_resp_body; size_t inject_sz; + int manipulate_replaced; struct replace_ctx * rep_ctx; struct insert_ctx * ins_ctx; @@ -1114,6 +1152,7 @@ static void pangu_http_ctx_free(struct pangu_http_ctx * ctx) http_ins_ctx_free(ctx->ins_ctx); ctx->ins_ctx = NULL; } + ctx->manipulate_replaced=0; FREE(&ctx->enforce_rules); policy_action_param_free(ctx->param); ctx->param=NULL; @@ -1365,6 +1404,20 @@ static void html_free(char ** page_buff) return; } +static int http_enforcement_ratio(float enforcement_ratio) +{ + int enforcement_ratio_temp = 0; + enforcement_ratio_temp = enforcement_ratio * 10000; + + srand(time(NULL)); + int random = rand() % (10000-1); + if (random >=0 && random <= enforcement_ratio_temp) + { + return 1; + } + return 0; +} + void http_replace(const struct tfe_stream * stream, const struct tfe_http_session * session, enum tfe_http_event events, const unsigned char * body_frag, size_t frag_size, struct pangu_http_ctx * ctx) { @@ -1372,6 +1425,14 @@ void http_replace(const struct tfe_stream * stream, const struct tfe_http_sessio char * rewrite_buff = NULL; size_t rewrite_sz = 0; + struct policy_action_param *param = ctx->param; + int ratio = http_enforcement_ratio(param->enforcement_ratio); + if (ratio != 1) + { + TFE_LOG_DEBUG(g_pangu_rt->local_logger, "enforcement ratio:%f", param->enforcement_ratio); + ctx->action = PG_ACTION_NONE; + return; + } to_write_sess = tfe_http_session_allow_write(session); if (to_write_sess == NULL) //fail to wirte, abandon. { @@ -1575,6 +1636,14 @@ static void http_redirect(const struct tfe_http_session * session, enum tfe_http int resp_code = param->status_code; char *rd_url = param->message; + int ratio = http_enforcement_ratio(param->enforcement_ratio); + if (ratio != 1) + { + TFE_LOG_DEBUG(g_pangu_rt->local_logger, "enforcement ratio:%f", param->enforcement_ratio); + ctx->action = PG_ACTION_NONE; + return; + } + ctx->manipulate_replaced = 1; if (resp_code <= 0 || rd_url == NULL){ TFE_LOG_ERROR(g_pangu_rt->local_logger, "Invalid redirect rule %d paramter", ctx->enforce_rules[0].config_id); @@ -1627,10 +1696,8 @@ static void http_block(const struct tfe_http_session * session, enum tfe_http_ev ctx->action = PG_ACTION_NONE; return; } - struct tfe_http_session * to_write_sess = NULL; - - if(events & EV_HTTP_RESP_HDR || tfe_http_in_request(events)) + if (events & EV_HTTP_RESP_HDR || tfe_http_in_hdr(events)) { to_write_sess = tfe_http_session_allow_write(session); response = tfe_http_session_response_create(to_write_sess, resp_code); @@ -1674,6 +1741,13 @@ static void http_hijack(const struct tfe_http_session * session, enum tfe_http_e return; } + if (http_enforcement_ratio(param->enforcement_ratio) != 1) + { + TFE_LOG_DEBUG(g_pangu_rt->local_logger, "enforcement ratio:%f", param->enforcement_ratio); + ctx->action = PG_ACTION_NONE; + return; + } + ctx->manipulate_replaced = 1; if (tfe_http_in_request(events)) { return; @@ -1765,7 +1839,13 @@ static void http_insert(const struct tfe_stream * stream, const struct tfe_http_ size_t rewrite_sz = 0; struct policy_action_param *param = ctx->param; - + int ratio = http_enforcement_ratio(param->enforcement_ratio); + if (ratio != 1) + { + TFE_LOG_DEBUG(g_pangu_rt->local_logger, "enforcement ratio:%f", param->enforcement_ratio); + ctx->action = PG_ACTION_NONE; + return; + } to_write_sess = tfe_http_session_allow_write(session); if (to_write_sess == NULL) //fail to wirte, abandon. { @@ -2450,6 +2530,21 @@ static inline int ctx_actually_inserted(struct pangu_http_ctx * ctx) } } +static inline int ctx_actually_manipulate(struct pangu_http_ctx * ctx) +{ + if(ctx->action == PG_ACTION_MANIPULATE && + (ctx->param->action == MA_ACTION_REDIRECT || + ctx->param->action == MA_ACTION_HIJACK)&& + ctx->n_enforce==1 && ctx->manipulate_replaced==0) + { + return 1; + } + else + { + return 0; + } +} + void pangu_on_http_end(const struct tfe_stream * stream, const struct tfe_http_session * session, unsigned int thread_id, void ** pme) { @@ -2488,7 +2583,9 @@ void pangu_on_http_end(const struct tfe_stream * stream, if ((ctx->action != PG_ACTION_NONE&& !(ctx_actually_replaced(ctx))) || (ctx->action != PG_ACTION_NONE&& - !(ctx_actually_inserted(ctx)))) + !(ctx_actually_inserted(ctx))) || + (ctx->action != PG_ACTION_NONE&& + !(ctx_actually_manipulate(ctx)))) { ret=pangu_send_log(g_pangu_rt->send_logger, &log_msg); ATOMIC_ADD(&(g_pangu_rt->stat_val[STAT_LOG_NUM]), ret); diff --git a/plugin/business/pangu-http/src/pangu_logger.cpp b/plugin/business/pangu-http/src/pangu_logger.cpp index 3a66b19..8479646 100644 --- a/plugin/business/pangu-http/src/pangu_logger.cpp +++ b/plugin/business/pangu-http/src/pangu_logger.cpp @@ -303,7 +303,7 @@ int pangu_send_log(struct pangu_logger* handle, const struct pangu_log* log_msg) if(log_msg->result[i].action == LG_ACTION_MANIPULATE) { cJSON_AddStringToObject(per_hit_obj, "common_sub_action", manipulate_action_map[log_msg->action]); - cJSON_AddNumberToObject(per_hit_obj, "http_action_file_sz", log_msg->inject_sz); + cJSON_AddNumberToObject(per_hit_obj, "http_action_file_size", log_msg->inject_sz); } else {