diff --git a/plugin/business/pangu-http/src/pangu_http.cpp b/plugin/business/pangu-http/src/pangu_http.cpp
index 58c0c40..75dd1ca 100644
--- a/plugin/business/pangu-http/src/pangu_http.cpp
+++ b/plugin/business/pangu-http/src/pangu_http.cpp
@@ -16,6 +16,8 @@
#include
#include
+#include
+
#include
#include
#include
@@ -27,21 +29,30 @@
#define MAX_SCAN_RESULT 16
#define MAX_EDIT_ZONE_NUM 64
-enum pangu_action//Bigger action number is prior.
+enum pangu_action //Bigger action number is prior.
{
PG_ACTION_NONE = 0x00,
PG_ACTION_MONIT = 0x01,
PG_ACTION_FORWARD = 0x02, /* N/A */
PG_ACTION_REJECT = 0x10,
PG_ACTION_DROP = 0x20, /* N/A */
- PG_ACTION_REDIRECT = 0x30,
+ PG_ACTION_MANIPULATE = 0x30,
PG_ACTION_RATELIMIT = 0x40, /* N/A */
- PG_ACTION_REPLACE = 0x50,
PG_ACTION_LOOP = 0x60, /* N/A */
PG_ACTION_WHITELIST = 0x80,
__PG_ACTION_MAX
};
+enum manipulate_actin
+{
+ MA_ACTION_REDIRECT = 0,
+ MA_ACTION_BLOCK,
+ MA_ACTION_REPLACE,
+ MA_ACTION_HIJACK,
+ MA_ACTION_INSERT,
+ __MA_ACTION_MAX
+};
+
enum scan_table
{
PXY_CTRL_IP,
@@ -63,10 +74,47 @@ enum pangu_http_stat
STAT_ACTION_REDIRECT,
STAT_ACTION_PRE_REPLACE,
STAT_ACTION_REPLACE,
+ STAT_ACTION_HIJACK,
+ STAT_ACTION_INSERT,
STAT_ACTION_WHITELSIT,
STAT_SUSPENDING,
__PG_STAT_MAX
};
+
+enum policy_table
+{
+ POLICY_TABLE_REJECT,
+ POLICY_TABLE_HIJACK,
+ POLICY_TABLE_INSERT,
+ POLICY_TABLE_MAX
+};
+
+struct policy_object
+{
+ int cfg_id;
+ size_t msg_len;
+ char *profile_name;
+ char *profile_msg;
+ char *profile_type;
+ ctemplate::Template * tpl;
+};
+
+struct plolicy_param
+{
+ int ref_cnt;
+ int action;
+
+ char *message;
+ char *position;
+
+ int profile_id;
+ int status_code;
+
+ size_t n_rule;
+ struct replace_rule *rule;
+ pthread_mutex_t lock;
+};
+
struct pangu_rt
{
Maat_feather_t maat;
@@ -77,6 +125,7 @@ struct pangu_rt
int log_level;
int thread_num;
int scan_table_id[__SCAN_TABLE_MAX];
+ int plolicy_table_id[POLICY_TABLE_MAX];
ctemplate::Template * tpl_403, * tpl_404, * tpl_451;
char * reject_page;
int page_size;
@@ -90,9 +139,10 @@ struct pangu_rt
int fs_id[__PG_STAT_MAX];
struct event_base* gc_evbase;
struct event* gcev;
-
+
+ int plolicy_param_idx;
int ca_store_reseting;
-
+
};
struct pangu_rt * g_pangu_rt;
@@ -169,7 +219,7 @@ static Maat_feather_t create_maat_feather(const char * instance_name, const char
break;
}
-
+
Maat_set_feather_opt(target, MAAT_OPT_FOREIGN_CONT_DIR, "./pangu_files", strlen("./pangu_files")+1);
if (maat_stat_on)
{
@@ -200,6 +250,7 @@ error_out:
Maat_burn_feather(target);
return NULL;
}
+
static void pangu_http_gc_cb(evutil_socket_t fd, short what, void * arg)
{
int i=0;
@@ -223,6 +274,8 @@ static void pangu_http_stat_init(struct pangu_rt * pangu_runtime)
spec[STAT_ACTION_REDIRECT]="redirect";
spec[STAT_ACTION_PRE_REPLACE]="pre_replace";
spec[STAT_ACTION_REPLACE]="replace";
+ spec[STAT_ACTION_HIJACK]="hijack";
+ spec[STAT_ACTION_INSERT]="insert";
spec[STAT_ACTION_WHITELSIT]="whitelist";
spec[STAT_SUSPENDING]="suspending";
@@ -250,7 +303,7 @@ void trusted_CA_update_start_cb(int update_type, void* u_para)
}
g_pangu_rt->ca_store_reseting++;
}
-
+
}
void trusted_CA_update_cert_cb(int table_id, const char* table_line, void* u_para)
{
@@ -335,6 +388,7 @@ void trusted_CA_update_finish_cb(void* u_para)
}
}
}
+
static int get_column_pos(const char* line, int column_seq, size_t *offset, size_t *len)
{
const char* seps=" \t";
@@ -370,12 +424,12 @@ void subscribe_id_new_cb(int table_id, const char* key, const char* table_line,
size_t subscribe_id_offset, len;
ret=get_column_pos(table_line, 7, &subscribe_id_offset, &len);
if(ret<0)
- {
+ {
TFE_LOG_ERROR(g_pangu_rt->local_logger, "Add subscribe ID faild: %s", table_line);
return;
- }
+ }
*ad=ALLOC(char, len+1);
- memcpy(*ad, table_line+subscribe_id_offset, len);
+ memcpy(*ad, table_line+subscribe_id_offset, len);
TFE_LOG_INFO(g_pangu_rt->local_logger, "Add subscribe ID: %s", (char*)*ad);
return;
}
@@ -386,12 +440,304 @@ void subscribe_id_free_cb(int table_id, MAAT_PLUGIN_EX_DATA* ad, long argl, void
*ad=NULL;
}
+static
+int to_val_idx(const char *key)
+{
+ const char *clue_action_map[] = {"redirect",
+ "block",
+ "replace",
+ "hijack",
+ "insert"
+ };
+ size_t i = 0;
+
+ for (i = 0; i < sizeof(clue_action_map) / sizeof(const char *); i++)
+ {
+ if (0 == strcasecmp(key, clue_action_map[i]))
+ break;
+ }
+ return i;
+}
+
+void policy_param_new(int idx, const struct Maat_rule_t* rule, const char* srv_def_large,
+ MAAT_RULE_EX_DATA* ad, long argl, void *argp)
+{
+ *ad=NULL;
+ if((unsigned int)rule->serv_def_lenlocal_logger, "invalid policy parameter: id = %d", rule->config_id);
+ return;
+ }
+
+ struct plolicy_param* param=ALLOC(struct plolicy_param, 1);
+
+ param->ref_cnt=1;
+ pthread_mutex_init(&(param->lock), NULL);
+
+ item=cJSON_GetObjectItem(json,"method");
+ if(item && item->type==cJSON_String){
+ param->action =to_val_idx(item->valuestring);
+ }
+
+ switch(param->action)
+ {
+ case MA_ACTION_REDIRECT:
+ item=cJSON_GetObjectItem(json,"code");
+ if(item && item->type==cJSON_Number){
+ param->status_code = item->valueint;
+ }
+ item=cJSON_GetObjectItem(json,"to");
+ if(item && item->type==cJSON_String){
+ param->message = tfe_strdup(item->valuestring);
+ }
+ break;
+ case MA_ACTION_BLOCK:
+ item=cJSON_GetObjectItem(json,"code");
+ if(item && item->type==cJSON_Number){
+ param->status_code = item->valueint;
+ }
+ item=cJSON_GetObjectItem(json,"message");
+ if(item && item->type==cJSON_String){
+ param->message = tfe_strdup(item->valuestring);
+ }
+ item=cJSON_GetObjectItem(json,"html_profile");
+ if(item && item->type==cJSON_Number){
+ param->profile_id = item->valueint;
+ }
+ break;
+ case MA_ACTION_REPLACE:
+ rules = cJSON_GetObjectItem(json, "rules");
+ if(rules)
+ {
+ size_t idx = 0;
+ param->rule = ALLOC(struct replace_rule, MAX_EDIT_ZONE_NUM);
+ for (item = rules->child; item != NULL; item = item->next)
+ {
+ char * search = cJSON_GetObjectItem(item , "search_in")->valuestring;
+ if (search == NULL) break;
+
+ param->rule[idx].zone = zone_name_to_id(search);
+ if (param->rule[idx].zone == kZoneMax)
+ {
+ break;
+ }
+ param->rule[idx].find = tfe_strdup(cJSON_GetObjectItem(item , "find")->valuestring);
+ param->rule[idx].replace_with = tfe_strdup(cJSON_GetObjectItem(item , "replace_with")->valuestring);
+ idx++;
+ }
+ param->n_rule = idx;
+ }
+ break;
+ case MA_ACTION_HIJACK:
+ item=cJSON_GetObjectItem(json,"hijack_profile");
+ if(item && item->type==cJSON_Number){
+ param->profile_id = item->valueint;
+ }
+ break;
+ case MA_ACTION_INSERT:
+ item=cJSON_GetObjectItem(json,"insert_profile");
+ if(item && item->type==cJSON_Number){
+ param->profile_id = item->valueint;
+ }
+ item=cJSON_GetObjectItem(json,"position");
+ if(item && item->type==cJSON_String){
+ param->position = tfe_strdup(item->valuestring);
+ }
+ break;
+ default: assert(0);
+ break;
+ }
+ cJSON_Delete(json);
+ *ad=param;
+ return;
+}
+
+void policy_param_free(int idx, const struct Maat_rule_t* rule, const char* srv_def_large, MAAT_RULE_EX_DATA* ad, long argl, void *argp)
+{
+ unsigned int i=0;
+ if(*ad==NULL)
+ {
+ return;
+ }
+ struct plolicy_param* param=(struct plolicy_param*)*ad;
+ pthread_mutex_lock(&(param->lock));
+ param->ref_cnt--;
+ if(param->ref_cnt>0)
+ {
+ pthread_mutex_unlock(&(param->lock));
+ return;
+ }
+ pthread_mutex_unlock(&(param->lock));
+ pthread_mutex_destroy(&(param->lock));
+ for(i=0; in_rule; i++)
+ {
+ FREE(&(param->rule[i].find));
+ FREE(&(param->rule[i].replace_with));
+ }
+
+ if (param->message)
+ FREE(&(param->message));
+ if (param->position)
+ FREE(&(param->position));
+ FREE(&(param));
+ return;
+}
+
+void policy_param_dup(int idx, MAAT_RULE_EX_DATA *to, MAAT_RULE_EX_DATA *from, long argl, void *argp)
+{
+ struct plolicy_param* from_param=*((struct plolicy_param**)from);
+ pthread_mutex_lock(&(from_param->lock));
+ from_param->ref_cnt++;
+ pthread_mutex_unlock(&(from_param->lock));
+ *((struct plolicy_param**)to)=from_param;
+ return;
+}
+
+void policy_table_new_cb(int table_id, const char* key, const char* table_line, MAAT_PLUGIN_EX_DATA* ad, long argl, void* argp)
+{
+ int ret=0, cfg_id=0, is_valid=0;
+ char profile_name[128]={0}, formate[128]={0};
+ char profile_path[TFE_PATH_MAX]={0};
+
+ ret=sscanf(table_line, "%d\t%s\t%s\t%s\t%d", &cfg_id, profile_name, formate, profile_path, &is_valid);
+ if(ret!=5)
+ {
+ TFE_LOG_ERROR(g_pangu_rt->local_logger, "Policy table parse config failed: %s", table_line);
+ return;
+ }
+ struct policy_object* ply_obj=ALLOC(struct policy_object, 1);
+
+ ply_obj->cfg_id=cfg_id;
+ if(strcasecmp(formate, "template") == 0)
+ {
+ ply_obj->tpl = ctemplate::Template::GetTemplate(profile_path, ctemplate::DO_NOT_STRIP);
+ }else
+ {
+ ply_obj->profile_msg = rt_read_file(profile_path, &ply_obj->msg_len);
+ if (ply_obj->profile_msg == NULL || ply_obj->msg_len == 0)
+ {
+ TFE_LOG_ERROR(g_pangu_rt->local_logger, "Read file failed %d:%s:%s", cfg_id, profile_name, profile_path);
+ }
+ }
+ ply_obj->profile_name=tfe_strdup(profile_name);
+ ply_obj->profile_type=tfe_strdup(formate);
+
+ *ad = ply_obj;
+ return;
+}
+
+void policy_table_free_cb(int table_id, MAAT_PLUGIN_EX_DATA* ad, long argl, void *argp)
+{
+ struct policy_object* ply_obj=(struct policy_object*)(*ad);
+ FREE(&ply_obj->profile_type);
+ FREE(&ply_obj->profile_msg);
+ FREE(&ply_obj->profile_name);
+ FREE(&ply_obj);
+ *ad=NULL;
+}
+
+void policy_table_dup_cb(int table_id, MAAT_PLUGIN_EX_DATA *to, MAAT_PLUGIN_EX_DATA *from, long argl, void *argp)
+{
+ struct policy_object* ply_obj=(struct policy_object*)(*from);
+ *to=ply_obj;
+}
+
+int maat_table_init(const char* table_name,
+ Maat_start_callback_t *start, Maat_update_callback_t *update,Maat_finish_callback_t *finish,
+ void *u_para)
+{
+ int table_id=0;
+
+ table_id=Maat_table_register(g_pangu_rt->maat, table_name);
+ if(table_id<0)
+ {
+ goto finish;
+ }
+ Maat_table_callback_register(g_pangu_rt->maat, table_id,
+ start, update, finish, u_para);
+finish:
+ return table_id;
+}
+
+int maat_table_ex_init(const char* table_name, int policy_id,
+ Maat_plugin_EX_new_func_t* new_func,
+ Maat_plugin_EX_free_func_t* free_func,
+ Maat_plugin_EX_dup_func_t* dup_func)
+{
+ int table_id = 0;
+
+ table_id=g_pangu_rt->plolicy_table_id[policy_id]=Maat_table_register(g_pangu_rt->maat, table_name);
+ if(table_id<0)
+ {
+ goto finish;
+ }
+ table_id=Maat_plugin_EX_register(g_pangu_rt->maat,
+ table_id,
+ new_func,free_func,
+ dup_func,NULL,0,NULL);
+finish:
+ return table_id;
+}
+
+int panggu_policy_init()
+{
+ int table_id=0, policy_id = 0;
+
+ const char *table_name_map[] = {"PXY_PROFILE_RESPONSE_PAGES",
+ "PXY_PROFILE_HIJACK_FILES",
+ "PXY_PROFILE_INSERT_SCRIPTS",
+ };
+
+ table_id = maat_table_init("PXY_OBJ_TRUSTED_CA_CERT",
+ trusted_CA_update_start_cb,
+ trusted_CA_update_cert_cb,
+ trusted_CA_update_finish_cb,
+ g_pangu_rt);
+ if(table_id<0)
+ {
+ TFE_LOG_INFO(NULL, "Pangu HTTP register table PXY_OBJ_TRUSTED_CA_CERT failed.");
+ goto finish;
+ }
+
+ table_id = maat_table_init("PXY_OBJ_TRUSTED_CA_CRL",
+ trusted_CA_update_start_cb,
+ trusted_CA_update_crl_cb,
+ trusted_CA_update_finish_cb,
+ g_pangu_rt);
+ if(table_id<0)
+ {
+ TFE_LOG_INFO(NULL, "Pangu HTTP register table PXY_OBJ_TRUSTED_CA_CRL failed.");
+ goto finish;
+ }
+
+ for (policy_id = 0; policy_id thread_num = tfe_proxy_get_work_thread_count();
g_pangu_rt->gc_evbase=tfe_proxy_get_gc_evbase();
@@ -404,9 +750,7 @@ int pangu_http_init(struct tfe_proxy * proxy)
}
g_pangu_rt->fs_handle = tfe_proxy_get_fs_handle();
pangu_http_stat_init(g_pangu_rt);
-
-
g_pangu_rt->maat = create_maat_feather("static", profile, "MAAT", g_pangu_rt->thread_num, g_pangu_rt->local_logger);
if (!g_pangu_rt->maat)
{
@@ -430,37 +774,24 @@ int pangu_http_init(struct tfe_proxy * proxy)
goto error_out;
}
}
- table_id=Maat_table_register(g_pangu_rt->maat, "PXY_OBJ_TRUSTED_CA_CERT");
- if(table_id<0)
- {
- TFE_LOG_INFO(NULL, "Pangu HTTP register table PXY_OBJ_TRUSTED_CA_CERT failed.");
- goto error_out;
- }
- Maat_table_callback_register(g_pangu_rt->maat, table_id,
- trusted_CA_update_start_cb,
- trusted_CA_update_cert_cb,
- trusted_CA_update_finish_cb,
- g_pangu_rt);
- table_id=Maat_table_register(g_pangu_rt->maat, "PXY_OBJ_TRUSTED_CA_CRL");
+ g_pangu_rt->plolicy_param_idx=Maat_rule_get_ex_new_index(g_pangu_rt->maat, "PXY_CTRL_COMPILE",
+ policy_param_new, policy_param_free, policy_param_dup,
+ 0, NULL);
+
+ table_id = panggu_policy_init();
if(table_id<0)
{
- TFE_LOG_INFO(NULL, "Pangu HTTP register table PXY_OBJ_TRUSTED_CA_CRL failed.");
goto error_out;
}
- Maat_table_callback_register(g_pangu_rt->maat, table_id,
- trusted_CA_update_start_cb,
- trusted_CA_update_crl_cb,
- trusted_CA_update_finish_cb,
- g_pangu_rt);
-
+
g_pangu_rt->dyn_maat = create_maat_feather("dyn", profile, "DYNAMIC_MAAT", g_pangu_rt->thread_num, g_pangu_rt->local_logger);
if (!g_pangu_rt->maat)
{
goto error_out;
}
g_pangu_rt->subscribe_id_table_id=Maat_table_register(g_pangu_rt->dyn_maat, "IPD_DYN_SUBSCRIBE_IP");
- temp=Maat_plugin_EX_register(g_pangu_rt->dyn_maat,
+ temp=Maat_plugin_EX_register(g_pangu_rt->dyn_maat,
g_pangu_rt->subscribe_id_table_id,
subscribe_id_new_cb,
subscribe_id_free_cb,
@@ -487,7 +818,7 @@ int pangu_http_init(struct tfe_proxy * proxy)
MESA_load_profile_string_def(profile, "TEMPLATE", "PAGE_451", page_path, sizeof(page_path),
"./resource/pangu/HTTP451.html");
g_pangu_rt->tpl_451 = ctemplate::Template::GetTemplate(page_path, ctemplate::DO_NOT_STRIP);
-
+
MESA_load_profile_int_def(profile, "TANGO_CACHE", "suspend_max", &(temp), 1024*1024);
g_pangu_rt->suspend_max=temp;
@@ -511,7 +842,6 @@ error_out:
return -1;
}
-
struct replace_ctx
{
struct replace_rule * rule;
@@ -521,6 +851,14 @@ struct replace_ctx
int actually_replaced;
};
+struct insert_ctx
+{
+ struct insert_rule *rule;
+ struct tfe_http_half * replacing;
+ struct evbuffer *http_body;
+ int actually_replaced;
+};
+
struct pangu_http_ctx
{
int magic_num;
@@ -532,14 +870,16 @@ struct pangu_http_ctx
struct Maat_rule_t * enforce_rules;
size_t n_enforce;
char * enforce_para;
+ struct plolicy_param *param;
struct evbuffer* log_req_body, *log_resp_body;
struct replace_ctx * rep_ctx;
-
+ struct insert_ctx * ins_ctx;
+
int (* resumed_cb)(const struct tfe_stream * stream,
const struct tfe_http_session * session, enum tfe_http_event event, const unsigned char * data,
size_t datalen, unsigned int thread_id, struct pangu_http_ctx* ctx);
-
+
enum cache_pending_result pending_result;
struct future *f_cache_pending, *f_cache_query;
struct tfe_http_session * ref_session;
@@ -548,28 +888,35 @@ struct pangu_http_ctx
size_t cache_result_declared_sz, cache_result_actual_sz;
struct cache_write_context* cache_write_ctx;
int cache_wirte_result;
-
+
int thread_id;
};
void http_repl_ctx_free(struct replace_ctx* rep_ctx)
{
- for (size_t i = 0; i < rep_ctx->n_rule; i++)
- {
- FREE(&(rep_ctx->rule[i].find));
- FREE(&(rep_ctx->rule[i].replace_with));
- }
- FREE(&(rep_ctx->rule));
if (rep_ctx->http_body)
{
evbuffer_free(rep_ctx->http_body);
rep_ctx->http_body = NULL;
}
-
FREE(&rep_ctx);
return;
}
+
+void http_ins_ctx_free(struct insert_ctx* ins_ctx)
+{
+ FREE(&(ins_ctx->rule));
+ if (ins_ctx->http_body)
+ {
+ evbuffer_free(ins_ctx->http_body);
+ ins_ctx->http_body = NULL;
+ }
+ FREE(&ins_ctx);
+ return;
+}
+
+
#define HTTP_CTX_MAGIC_NUM 20181021
static struct pangu_http_ctx * pangu_http_ctx_new(unsigned int thread_id)
{
@@ -588,9 +935,14 @@ static void pangu_http_ctx_free(struct pangu_http_ctx * ctx)
http_repl_ctx_free(ctx->rep_ctx);
ctx->rep_ctx = NULL;
}
+ if (ctx->ins_ctx)
+ {
+ http_ins_ctx_free(ctx->ins_ctx);
+ ctx->ins_ctx = NULL;
+ }
FREE(&ctx->enforce_rules);
FREE(&ctx->enforce_para);
- Maat_clean_status(&(ctx->scan_mid));
+ Maat_clean_status(&(ctx->scan_mid));
ctx->scan_mid = NULL;
if(ctx->sp)
@@ -614,7 +966,7 @@ static void pangu_http_ctx_free(struct pangu_http_ctx * ctx)
//Dirty close
ctx->cached_response=NULL;
}
-
+
if(ctx->f_cache_query)
{
future_destroy(ctx->f_cache_query);
@@ -659,10 +1011,9 @@ void __pangu_action_weight_init()
{
pangu_action_weight[PG_ACTION_NONE] = 0;
pangu_action_weight[PG_ACTION_MONIT] = 1;
- pangu_action_weight[PG_ACTION_REPLACE] = 2;
- pangu_action_weight[PG_ACTION_REDIRECT] = 3;
- pangu_action_weight[PG_ACTION_REJECT] = 4;
- pangu_action_weight[PG_ACTION_WHITELIST] = 5;
+ pangu_action_weight[PG_ACTION_MANIPULATE] = 2;
+ pangu_action_weight[PG_ACTION_REJECT] = 3;
+ pangu_action_weight[PG_ACTION_WHITELIST] = 4;
}
static inline int action_cmp(enum pangu_action a1, enum pangu_action a2)
@@ -672,7 +1023,7 @@ static inline int action_cmp(enum pangu_action a1, enum pangu_action a2)
//enforce_rules[0] contains execute action.
static enum pangu_action decide_ctrl_action(const struct Maat_rule_t * hit_rules, size_t n_hit,
- struct Maat_rule_t ** enforce_rules, size_t * n_enforce, char** enforce_para)
+ struct Maat_rule_t ** enforce_rules, size_t * n_enforce, struct plolicy_param **param)
{
size_t n_monit = 0, exist_enforce_num = 0, i = 0;
const struct Maat_rule_t * prior_rule = hit_rules;
@@ -733,26 +1084,17 @@ static enum pangu_action decide_ctrl_action(const struct Maat_rule_t * hit_rules
memcpy(*enforce_rules, prior_rule, sizeof(struct Maat_rule_t));
memcpy(*enforce_rules + exist_enforce_num + 1, monit_rule, n_monit * sizeof(struct Maat_rule_t));
}
- if(*enforce_para!=NULL)
+
+ void *ex_data=Maat_rule_get_ex_data(g_pangu_rt->maat, prior_rule, g_pangu_rt->plolicy_param_idx);
+ if(ex_data!=NULL)
{
- free(*enforce_para);
- }
- size_t __serv_def_len = (size_t)prior_rule->serv_def_len;
- *enforce_para = ALLOC(char, __serv_def_len);
-
- if (__serv_def_len > MAX_SERVICE_DEFINE_LEN)
- {
- Maat_read_rule(g_pangu_rt->maat,prior_rule, MAAT_RULE_SERV_DEFINE, *enforce_para, __serv_def_len);
- }
- else
- {
- strcpy(*enforce_para, prior_rule->service_defined);
+ *param=(struct plolicy_param*)ex_data;
}
return prior_action;
}
//HTML template is downloaded from https://github.com/AndiDittrich/HttpErrorPages
-static void html_generate(int status_code, int cfg_id, const char* msg, char ** page_buff, size_t * page_size)
+static void template_generate(int status_code, int cfg_id, const char* msg, char ** page_buff, size_t * page_size)
{
ctemplate::TemplateDictionary dict("pg_page_dict"); //dict is automatically finalized after function returned.
dict.SetIntValue("cfg_id", cfg_id);
@@ -776,14 +1118,69 @@ static void html_generate(int status_code, int cfg_id, const char* msg, char **
*page_buff = tfe_strdup(output.c_str());
}
+static int html_generate(int cfg_id, const char* msg, char ** page_buff, size_t * page_size)
+{
+#define KEY_LEN 16
+ int ret = 0;
+ struct policy_object* ply_obj=NULL;
+
+ int tables_id = g_pangu_rt->plolicy_table_id[POLICY_TABLE_REJECT];
+
+ char cfg_id_str[KEY_LEN] = {0};
+ snprintf(cfg_id_str, KEY_LEN, "%d", cfg_id);
+
+ ply_obj = (struct policy_object*)Maat_plugin_get_EX_data(g_pangu_rt->maat, tables_id, (const char*)cfg_id_str);
+ if(ply_obj==NULL)
+ {
+ ret=-1;
+ return ret;
+ }
+ if(!strncmp(ply_obj->profile_type, "template", strlen(ply_obj->profile_type)))
+ {
+ ctemplate::TemplateDictionary dict("pg_page_dict"); //dict is automatically finalized after function returned.
+ dict.SetIntValue("cfg_id", cfg_id);
+ dict.SetValue("msg", msg);
+ std::string output;
+
+ ply_obj->tpl->Expand(&output, &dict);
+ *page_size = output.length() + 1;
+ *page_buff = tfe_strdup(output.c_str());
+ }
+ else
+ {
+ *page_size = ply_obj->msg_len;
+ *page_buff = tfe_strdup(ply_obj->profile_msg);
+ }
+ return ret;
+}
+
static void html_free(char ** page_buff)
{
FREE(page_buff);
return;
}
-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)
+static struct policy_object* get_obj_for_id(int cfg_id)
+{
+#define KEY_LEN 16
+ struct policy_object* ply_obj=NULL;
+
+ char cfg_id_str[KEY_LEN] = {0};
+
+ snprintf(cfg_id_str, KEY_LEN, "%d", cfg_id);
+
+ int tables_id = g_pangu_rt->plolicy_table_id[POLICY_TABLE_HIJACK];
+ ply_obj = (struct policy_object*)Maat_plugin_get_EX_data(g_pangu_rt->maat, tables_id, (const char*)cfg_id_str);
+ if(ply_obj==NULL)
+ {
+ goto finish;
+ }
+finish:
+ return ply_obj;
+}
+
+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)
{
struct tfe_http_session * to_write_sess = NULL;
char * rewrite_buff = NULL;
@@ -804,9 +1201,10 @@ void http_replace(const struct tfe_stream * stream, const struct tfe_http_sessio
* the header has been forwarded, only replace the body but not modify header will raise exception */
if ((events & EV_HTTP_REQ_HDR) || (events & EV_HTTP_RESP_HDR))
{
+ struct plolicy_param *param = ctx->param;
ctx->rep_ctx = rep_ctx = ALLOC(struct replace_ctx, 1);
- rep_ctx->rule = ALLOC(struct replace_rule, MAX_EDIT_ZONE_NUM);
- rep_ctx->n_rule = format_replace_rule(ctx->enforce_para, rep_ctx->rule, MAX_EDIT_ZONE_NUM);
+ rep_ctx->rule = param->rule;
+ rep_ctx->n_rule = param->n_rule;
}
else
{
@@ -865,7 +1263,7 @@ void http_replace(const struct tfe_stream * stream, const struct tfe_http_sessio
rewrite_sz=execute_replace_rule(in_header_value,
strlen(in_header_value), zone, rep_ctx->rule, rep_ctx->n_rule, &rewrite_buff);
- if(rewrite_sz>0) rep_ctx->actually_replaced=1;
+ if(rewrite_sz>0) rep_ctx->actually_replaced=1;
tfe_http_field_write(rep_ctx->replacing, &in_header_field, rewrite_sz>0? rewrite_buff : in_header_value);
if(rewrite_buff != NULL)
{
@@ -891,13 +1289,13 @@ void http_replace(const struct tfe_stream * stream, const struct tfe_http_sessio
size_t __http_body_len = evbuffer_get_length(rep_ctx->http_body);
enum replace_zone r_zone = tfe_http_in_request(events) ? kZoneRequestBody : kZoneResponseBody;
-
+
rewrite_buff = NULL;
rewrite_sz = 0;
-
+
rewrite_sz = execute_replace_rule(__http_body, __http_body_len, r_zone,
rep_ctx->rule, rep_ctx->n_rule, &rewrite_buff);
-
+
if (rewrite_sz >0 )
{
@@ -956,7 +1354,7 @@ static void http_reject(const struct tfe_http_session * session, enum tfe_http_e
to_write_sess = tfe_http_session_allow_write(session);
response = tfe_http_session_response_create(to_write_sess, resp_code);
- html_generate(resp_code, ctx->enforce_rules[0].config_id, msg, &page_buff, &page_size);
+ template_generate(resp_code, ctx->enforce_rules[0].config_id, msg, &page_buff, &page_size);
tfe_http_std_field_write(response, TFE_HTTP_CONT_TYPE, "text/html; charset=utf-8");
snprintf(cont_len_str, sizeof(cont_len_str), "%lu", page_size);
tfe_http_std_field_write(response, TFE_HTTP_CONT_LENGTH, cont_len_str);
@@ -976,24 +1374,21 @@ static void http_reject(const struct tfe_http_session * session, enum tfe_http_e
}
static void http_redirect(const struct tfe_http_session * session, enum tfe_http_event events,
- struct pangu_http_ctx * ctx)
+ struct pangu_http_ctx * ctx)
{
- int resp_code = 0, ret = 0;
- char * url = NULL;
-
struct tfe_http_half * response = NULL;
struct tfe_http_session * to_write = NULL;
- url = ALLOC(char, ctx->enforce_rules[0].serv_def_len);
- ret = sscanf(ctx->enforce_para, "code=%d;url=%[^;]", &resp_code, url);
+ struct plolicy_param *param = ctx->param;
- if (ret != 2)
- {
- TFE_LOG_ERROR(g_pangu_rt->local_logger, "Invalid redirect rule %d paramter %s",
- ctx->enforce_rules[0].config_id, ctx->enforce_para);
+ int resp_code = param->status_code;
+ char *rd_url = param->message;
+
+ 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);
goto error_out;
}
-
to_write = tfe_http_session_allow_write(session);
if (to_write == NULL)
{
@@ -1001,7 +1396,7 @@ static void http_redirect(const struct tfe_http_session * session, enum tfe_http
}
response = tfe_http_session_response_create(to_write, resp_code);
- tfe_http_std_field_write(response, TFE_HTTP_LOCATION, url);
+ tfe_http_std_field_write(response, TFE_HTTP_LOCATION, rd_url);
tfe_http_std_field_write(response, TFE_HTTP_CONT_LENGTH, "0");
tfe_http_half_append_body(response, NULL, 0, 0);
@@ -1009,13 +1404,322 @@ static void http_redirect(const struct tfe_http_session * session, enum tfe_http
tfe_http_session_detach(session);
error_out:
- free(url);
+ return;
+}
+
+static void http_block(const struct tfe_http_session * session, enum tfe_http_event events,
+ struct pangu_http_ctx * ctx)
+{
+ int ret = -1;
+ struct tfe_http_half * response = NULL;
+ char * page_buff = NULL;
+ size_t page_size = 0;
+
+ char cont_len_str[16];
+
+ struct plolicy_param *param = ctx->param;
+
+ int resp_code = param->status_code;
+ int cfg_id = param->profile_id;
+ char *message = param->message;
+
+ if (resp_code <= 0 || cfg_id <= 0){
+ TFE_LOG_ERROR(g_pangu_rt->local_logger, "Invalid block rule %d", ctx->enforce_rules[0].config_id);
+ 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))
+ {
+ to_write_sess = tfe_http_session_allow_write(session);
+ response = tfe_http_session_response_create(to_write_sess, resp_code);
+
+ ret = html_generate(cfg_id, message, &page_buff, &page_size);
+ if (ret != 0)
+ {
+ TFE_LOG_ERROR(g_pangu_rt->local_logger, "Failed to get policy table, table_id = %d", cfg_id);
+ ctx->action = PG_ACTION_NONE;
+ }
+ tfe_http_std_field_write(response, TFE_HTTP_CONT_TYPE, "text/html; charset=utf-8");
+ snprintf(cont_len_str, sizeof(cont_len_str), "%lu", page_size);
+ tfe_http_std_field_write(response, TFE_HTTP_CONT_LENGTH, cont_len_str);
+
+ tfe_http_half_append_body(response, page_buff, page_size, 0);
+ tfe_http_half_append_body(response, NULL, 0, 0);
+ tfe_http_session_response_set(to_write_sess, response);
+ tfe_http_session_detach(session);
+ html_free(&page_buff);
+ }
+ else
+ {
+ to_write_sess = tfe_http_session_allow_write(session);
+ tfe_http_session_kill(to_write_sess);
+ }
+ return;
+}
+
+static void http_hijack(const struct tfe_http_session * session, enum tfe_http_event events,
+ struct pangu_http_ctx * ctx)
+{
+ struct plolicy_param *param = ctx->param;
+
+ int cfg_id = param->profile_id;
+
+ if (cfg_id <= 0){
+ TFE_LOG_ERROR(g_pangu_rt->local_logger, "Invalid hijack rule %d",
+ ctx->enforce_rules[0].config_id);
+ ctx->action = PG_ACTION_NONE;
+ return;
+ }
+
+ struct tfe_http_half * response = NULL;
+ char cont_len_str[16];
+
+ struct tfe_http_session * to_write_sess = NULL;
+ if(events & EV_HTTP_RESP_HDR || tfe_http_in_request(events))
+ {
+ to_write_sess = tfe_http_session_allow_write(session);
+ response = tfe_http_session_response_create(to_write_sess, 200);
+
+ struct policy_object* ply_obj=get_obj_for_id(cfg_id);
+ if (NULL == ply_obj){
+ TFE_LOG_ERROR(g_pangu_rt->local_logger, "get table obj faild, table_id = %d", cfg_id);
+ ctx->action = PG_ACTION_NONE;
+ return;
+ }
+ int hijack_len = strlen(ply_obj->profile_name)+strlen("filename=\"\"")+1;
+ char *hijack_name = ALLOC(char, hijack_len);
+ snprintf(hijack_name, hijack_len, "filename=\"%s\"", ply_obj->profile_name);
+ tfe_http_nonstd_field_write(response, "Content-Disposition", hijack_name);
+ FREE(&hijack_name);
+ tfe_http_std_field_write(response, TFE_HTTP_CONT_TYPE, ply_obj->profile_type);
+ snprintf(cont_len_str, sizeof(cont_len_str), "%lu", ply_obj->msg_len);
+ tfe_http_std_field_write(response, TFE_HTTP_CONT_LENGTH, cont_len_str);
+
+ char * page_buff = ply_obj->profile_msg;
+ size_t page_size = ply_obj->msg_len;
+
+ size_t frag_size=8192; size_t sendlen=0;
+ unsigned char body_frag[frag_size];
+
+ tfe_http_session_response_set(to_write_sess, response);
+ tfe_http_half_write_body_begin(response, 1);
+ for (sendlen= 0; sendlen < page_size; sendlen+=frag_size)
+ {
+ memcpy(body_frag, page_buff+sendlen, frag_size);
+ tfe_http_half_write_body_data(response, body_frag, frag_size);
+ memset(body_frag, 0, frag_size);
+ }
+ tfe_http_half_write_body_end(response);
+ tfe_http_session_detach(session);
+ }
+ else
+ {
+ to_write_sess = tfe_http_session_allow_write(session);
+ tfe_http_session_kill(to_write_sess);
+ }
+ return;
+}
+
+static int format_insert_rule(struct plolicy_param *param, int cfg_id, struct insert_rule *rule)
+{
+#define KEY_LEN 16
+ int ret = 0;
+ struct policy_object* ply_obj=NULL;
+
+ int tables_id = g_pangu_rt->plolicy_table_id[POLICY_TABLE_INSERT];
+
+ char cfg_id_str[KEY_LEN] = {0};
+ snprintf(cfg_id_str, KEY_LEN, "%d", cfg_id);
+
+ ply_obj = (struct policy_object*)Maat_plugin_get_EX_data(g_pangu_rt->maat, tables_id, (const char*)cfg_id_str);
+ if(ply_obj==NULL)
+ {
+ ret=-1;
+ return ret;
+ }
+ rule->stype = ply_obj->profile_msg;
+ rule->type = ply_obj->profile_type;
+
+ if (param->position == NULL){
+ rule->position = NULL;
+ }else{
+ rule->position = param->position;
+ }
+ return ret;
+}
+
+static void http_insert(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)
+{
+ struct tfe_http_session * to_write_sess = NULL;
+ char * rewrite_buff = NULL;
+ size_t rewrite_sz = 0;
+
+ struct plolicy_param *param = ctx->param;
+
+ to_write_sess = tfe_http_session_allow_write(session);
+ if (to_write_sess == NULL) //fail to wirte, abandon.
+ {
+ TFE_STREAM_LOG_INFO(stream, "tfe_http_session_allow_write() %s failed.", session->req->req_spec.uri);
+ ctx->action = PG_ACTION_NONE;
+ tfe_http_session_detach(session); return;
+ }
+
+ struct insert_ctx *ins_ctx = ctx->ins_ctx;
+ if (ctx->ins_ctx == NULL)
+ {
+ if ((events & EV_HTTP_REQ_HDR) || (events & EV_HTTP_RESP_HDR))
+ {
+ int cfg_id = param->profile_id;
+ ctx->ins_ctx = ins_ctx = ALLOC(struct insert_ctx, 1);
+ ins_ctx->rule = ALLOC(struct insert_rule, 1);
+ int ret=format_insert_rule(param, cfg_id, ins_ctx->rule);
+ if (ret<0)
+ {
+ TFE_LOG_ERROR(g_pangu_rt->local_logger, "Failed to get policy table, table_id = %d", cfg_id);
+ ctx->action = PG_ACTION_NONE;
+ return;
+ }
+ }
+ else
+ {
+ TFE_STREAM_LOG_INFO(stream, "Can only setup replace on REQ/RESP headers, detached.");
+ ctx->action = PG_ACTION_NONE;
+ tfe_http_session_detach(session); return;
+ }
+ }
+
+ struct tfe_http_half * in_req_half = session->req;
+ struct tfe_http_half * in_resp_half = session->resp;
+ struct tfe_http_req_spec * in_req_spec = &in_req_half->req_spec;
+ struct tfe_http_resp_spec * in_resp_spec = &in_resp_half->resp_spec;
+
+ if ((events & EV_HTTP_REQ_HDR) || (events & EV_HTTP_RESP_HDR))
+ {
+ if (tfe_http_in_request(events))
+ {
+ ins_ctx->replacing = tfe_http_session_request_create(to_write_sess, in_req_spec->method, in_req_spec->uri);
+ tfe_http_session_request_set(to_write_sess, ins_ctx->replacing);
+ }
+ else
+ {
+ ins_ctx->replacing = tfe_http_session_response_create(to_write_sess, in_resp_spec->resp_code);
+ tfe_http_session_response_set(to_write_sess, ins_ctx->replacing);
+ }
+ struct tfe_http_half * in_half = tfe_http_in_request(events) ? in_req_half : in_resp_half;
+
+ struct http_field_name in_header_field{};
+ const char * in_header_value = NULL;
+ void * iterator = NULL;
+
+ while (true)
+ {
+ if ((in_header_value = tfe_http_field_iterate(in_half, &iterator, &in_header_field)) == NULL)
+ {
+ break;
+ }
+ tfe_http_field_write(ins_ctx->replacing, &in_header_field, in_header_value);
+ }
+ }
+
+ if ((events & EV_HTTP_REQ_BODY_BEGIN) || (events & EV_HTTP_RESP_BODY_BEGIN))
+ {
+ assert(ins_ctx->http_body == NULL);
+ ins_ctx->http_body = evbuffer_new();
+ }
+
+ if ((events & EV_HTTP_REQ_BODY_CONT) || (events & EV_HTTP_RESP_BODY_CONT))
+ {
+ evbuffer_add(ins_ctx->http_body, body_frag, frag_size);
+ }
+
+ if ((events & EV_HTTP_REQ_BODY_END) || (events & EV_HTTP_RESP_BODY_END))
+ {
+ char * __http_body = (char *) evbuffer_pullup(ins_ctx->http_body, -1);
+ size_t __http_body_len = evbuffer_get_length(ins_ctx->http_body);
+
+ rewrite_buff = NULL;
+ rewrite_sz = 0;
+
+ rewrite_sz = execute_insert_rule(__http_body, __http_body_len, ins_ctx->rule, &rewrite_buff);
+ if (rewrite_sz >0 )
+ {
+ tfe_http_half_append_body(ins_ctx->replacing, rewrite_buff, rewrite_sz, 0);
+ ins_ctx->actually_replaced=1;
+ }
+ else
+ {
+ tfe_http_half_append_body(ins_ctx->replacing, __http_body, __http_body_len, 0);
+ }
+
+ if (rewrite_buff != NULL)
+ {
+ FREE(&rewrite_buff);
+ }
+
+ if (ins_ctx->http_body != NULL)
+ {
+ evbuffer_free(ins_ctx->http_body);
+ ins_ctx->http_body = NULL;
+ }
+ }
+
+ if ((events & EV_HTTP_REQ_END) || (events & EV_HTTP_RESP_END))
+ {
+ tfe_http_half_append_body(ins_ctx->replacing, NULL, 0, 0);
+ ins_ctx->replacing = NULL;
+ }
+
+ return;
+}
+
+static void http_manipulate(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)
+{
+ struct plolicy_param *param = ctx->param;
+ if (param == NULL)
+ {
+ TFE_LOG_ERROR(g_pangu_rt->local_logger, "Failed to get the json format parsed. config_id = %d",
+ ctx->enforce_rules[0].config_id);
+ ctx->action = PG_ACTION_NONE;
+ return;
+ }
+
+ switch(param->action)
+ {
+ case MA_ACTION_REDIRECT:
+ http_redirect(session, events, ctx);
+ ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_REDIRECT]));
+ break;
+ case MA_ACTION_BLOCK:
+ http_block(session, events, ctx);
+ ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_REJECT]));
+ break;
+ case MA_ACTION_REPLACE:
+ http_replace(stream, session, events, body_frag, frag_size, ctx);
+ ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_PRE_REPLACE]));
+ break;
+ case MA_ACTION_HIJACK:
+ http_hijack(session, events, ctx);
+ ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_HIJACK]));
+ break;
+ case MA_ACTION_INSERT:
+ http_insert(stream, session, events, body_frag, frag_size, ctx);
+ ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_INSERT]));
+ break;
+ default: assert(0);
+ break;
+ }
+ return;
}
enum pangu_action http_scan(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)
{
- void * interator = NULL;
+ void * iterator = NULL;
const char * field_val = NULL;
struct http_field_name field_name;
struct Maat_rule_t result[MAX_SCAN_RESULT];
@@ -1043,7 +1747,7 @@ enum pangu_action http_scan(const struct tfe_http_session * session, enum tfe_ht
->scan_table_id[PXY_CTRL_HTTP_RES_HDR];
while (hit_cnt < MAX_SCAN_RESULT)
{
- field_val = tfe_http_field_iterate(session->req, &interator, &field_name);
+ field_val = tfe_http_field_iterate(session->req, &iterator, &field_name);
if (field_val == NULL)
{
break;
@@ -1090,7 +1794,7 @@ enum pangu_action http_scan(const struct tfe_http_session * session, enum tfe_ht
if (hit_cnt > 0)
{
- ctx->action = decide_ctrl_action(result, hit_cnt, &ctx->enforce_rules, &ctx->n_enforce, &ctx->enforce_para);
+ ctx->action = decide_ctrl_action(result, hit_cnt, &ctx->enforce_rules, &ctx->n_enforce, &ctx->param);
if (ctx->action == PG_ACTION_WHITELIST) goto __out;
if (hit_cnt > 1)
@@ -1112,6 +1816,7 @@ enum pangu_action http_scan(const struct tfe_http_session * session, enum tfe_ht
__out:
return ctx->action;
}
+
void enforce_control_policy(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, unsigned int thread_id,
struct pangu_http_ctx * ctx)
@@ -1129,19 +1834,14 @@ void enforce_control_policy(const struct tfe_stream * stream, const struct tfe_h
ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_MONIT]));
//send log on close.
break;
- case PG_ACTION_REJECT:
+ case PG_ACTION_REJECT:
http_reject(session, events, ctx);
ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_REJECT]));
break;
- case PG_ACTION_REDIRECT:
- http_redirect(session, events, ctx);
- ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_REDIRECT]));
+ case PG_ACTION_MANIPULATE:
+ http_manipulate(stream, session, events, body_frag, frag_size, ctx);
break;
- case PG_ACTION_REPLACE:
- http_replace(stream, session, events, body_frag, frag_size, ctx);
- ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_PRE_REPLACE]));
- break;
- case PG_ACTION_WHITELIST:
+ case PG_ACTION_WHITELIST:
tfe_http_session_detach(session);
ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_ACTION_WHITELSIT]));
break;
@@ -1220,8 +1920,8 @@ static void cache_read_on_succ(future_result_t * result, void * user)
ctx->resumed_cb=dummy_resume;
tfe_http_session_resume(ctx->ref_session);
ATOMIC_DEC(&(g_pangu_rt->stat_val[STAT_SUSPENDING]));
-
- ctx->cached_response=tfe_http_session_response_create(ctx->ref_session, 200);
+
+ ctx->cached_response=tfe_http_session_response_create(ctx->ref_session, 200);
tfe_http_std_field_write(ctx->cached_response, TFE_HTTP_CONT_TYPE, meta->content_type);
tfe_http_std_field_write(ctx->cached_response, TFE_HTTP_LAST_MODIFIED, meta->last_modified);
tfe_http_std_field_write(ctx->cached_response, TFE_HTTP_ETAG, meta->etag);
@@ -1230,12 +1930,12 @@ static void cache_read_on_succ(future_result_t * result, void * user)
snprintf(temp, sizeof(temp), "%lu", meta->content_length);
tfe_http_std_field_write(ctx->cached_response, TFE_HTTP_CONT_LENGTH, temp);
- //Dirty code here.
+ //Dirty code here.
tfe_http_session_response_set(ctx->ref_session, ctx->cached_response);
- //From now, ownership of cached_response has been transfered to http session,
+ //From now, ownership of cached_response has been transfered to http session,
//bussines plugin only hold this pointer as an reference for writing response body.
tfe_http_half_write_body_begin(ctx->cached_response, 1);
-
+
meta=NULL;
break;
case CACHE_QUERY_RESULT_DATA:
@@ -1246,7 +1946,7 @@ static void cache_read_on_succ(future_result_t * result, void * user)
case CACHE_QUERY_RESULT_END:
assert(ctx->cached_response!=NULL);
tfe_http_half_write_body_end(ctx->cached_response);
- //ownership has been transferred to http session, set to NULL.
+ //ownership has been transferred to http session, set to NULL.
ctx->pending_result=PENDING_RESULT_HIT;
ctx->cached_response=NULL;
assert(ctx->cache_result_actual_sz==ctx->cache_result_declared_sz);
@@ -1291,7 +1991,7 @@ static void cache_pend_on_succ(future_result_t * result, void * user)
const struct cached_meta* meta=NULL;
meta=cache_pending_result_read_meta(result, ctx->cmid);
ctx->resumed_cb=dummy_resume;
- tfe_http_session_resume(ctx->ref_session);
+ tfe_http_session_resume(ctx->ref_session);
ATOMIC_DEC(&(g_pangu_rt->stat_val[STAT_SUSPENDING]));
future_destroy(ctx->f_cache_pending);
ctx->f_cache_pending=NULL;
@@ -1309,7 +2009,7 @@ static void cache_pend_on_succ(future_result_t * result, void * user)
struct http_field_name in_field_name;
const char * in_header_value = NULL;
void * iterator = NULL;
- ctx->cache_revalidate_req=tfe_http_session_request_create(ctx->ref_session,
+ ctx->cache_revalidate_req=tfe_http_session_request_create(ctx->ref_session,
ctx->ref_session->req->req_spec.method, ctx->ref_session->req->req_spec.uri);
while (true)
{
@@ -1342,7 +2042,7 @@ static void cache_pend_on_fail(enum e_future_error err, const char * what, void
ctx->resumed_cb=dummy_resume;
future_destroy(ctx->f_cache_pending);
ctx->f_cache_pending=NULL;
-
+
return;
}
@@ -1353,7 +2053,7 @@ void cache_pend(const struct tfe_http_session * session, unsigned int thread_id,
ctx->pending_result=PENDING_RESULT_FOBIDDEN;
return;
}
- ctx->f_cache_pending=future_create("cache_pend", cache_pend_on_succ, cache_pend_on_fail, ctx);
+ ctx->f_cache_pending=future_create("cache_pend", cache_pend_on_succ, cache_pend_on_fail, ctx);
ctx->ref_session=tfe_http_session_allow_write(session);
ctx->pending_result=web_cache_async_pending(g_pangu_rt->cache, thread_id, session->req, &(ctx->cmid), ctx->f_cache_pending);
switch(ctx->pending_result)
@@ -1362,11 +2062,11 @@ void cache_pend(const struct tfe_http_session * session, unsigned int thread_id,
tfe_http_session_suspend(ctx->ref_session);
ATOMIC_INC(&(g_pangu_rt->stat_val[STAT_SUSPENDING]));
break;
- case PENDING_RESULT_ALLOWED:
+ case PENDING_RESULT_ALLOWED:
case PENDING_RESULT_FOBIDDEN:
case PENDING_RESULT_MISS:
future_destroy(ctx->f_cache_pending);
- ctx->f_cache_pending=NULL;
+ ctx->f_cache_pending=NULL;
break;
default:
break;
@@ -1394,7 +2094,7 @@ void cache_read(const struct tfe_http_session * session, unsigned int thread_id,
}
}
-void cache_write(const struct tfe_http_session * session, enum tfe_http_event events,
+void cache_write(const struct tfe_http_session * session, enum tfe_http_event events,
const unsigned char * body_frag, size_t frag_size,
unsigned int thread_id, struct pangu_http_ctx * ctx)
{
@@ -1410,11 +2110,11 @@ void cache_write(const struct tfe_http_session * session, enum tfe_http_event ev
if(events & EV_HTTP_RESP_BODY_END && ctx->cache_write_ctx!=NULL)
{
ctx->cache_wirte_result=web_cache_write_end(ctx->cache_write_ctx);
- ctx->cache_write_ctx=NULL;
+ ctx->cache_write_ctx=NULL;
//printf("cache update success: %s\n", ctx->ref_session->req->req_spec.url);
}
-}
+}
void pangu_on_http_begin(const struct tfe_stream * stream,
const struct tfe_http_session * session, unsigned int thread_id, void ** pme)
@@ -1440,7 +2140,7 @@ void pangu_on_http_begin(const struct tfe_stream * stream,
{
scan_ret = Maat_full_scan_string(g_pangu_rt->maat, g_pangu_rt->scan_table_id[PXY_CTRL_SUBSCRIBE_ID],
CHARSET_UTF8, sip, strlen(sip),
- result+hit_cnt, NULL, MAX_SCAN_RESULT-hit_cnt,
+ result+hit_cnt, NULL, MAX_SCAN_RESULT-hit_cnt,
&(ctx->scan_mid), (int) thread_id);
if(scan_ret>0)
{
@@ -1462,11 +2162,11 @@ void pangu_on_http_begin(const struct tfe_stream * stream,
addr_tfe2sapp(stream->addr, &sapp_addr);
hit_cnt += Maat_scan_proto_addr(g_pangu_rt->maat, g_pangu_rt->scan_table_id[PXY_CTRL_IP], &sapp_addr, 0,
result+hit_cnt, MAX_SCAN_RESULT-hit_cnt, &(ctx->scan_mid), (int) thread_id);
-
+
if (hit_cnt > 0)
{
- ctx->action = decide_ctrl_action(result, hit_cnt, &ctx->enforce_rules, &ctx->n_enforce, &ctx->enforce_para);
+ ctx->action = decide_ctrl_action(result, hit_cnt, &ctx->enforce_rules, &ctx->n_enforce, &ctx->param);
}
if (ctx->action == PG_ACTION_WHITELIST)
{
@@ -1486,11 +2186,12 @@ void pangu_on_http_end(const struct tfe_stream * stream,
struct pangu_http_ctx * ctx = *(struct pangu_http_ctx **) pme;
size_t i=0, j=0;
int ret=0;
- if(ctx->action == PG_ACTION_REPLACE && ctx->rep_ctx->actually_replaced==0)
+
+ if(ctx->action == PG_ACTION_MANIPULATE && ctx->param->action == MA_ACTION_REPLACE && ctx->rep_ctx->actually_replaced==0)
{
for(i=0; i< ctx->n_enforce; i++)
{
- if((unsigned char)ctx->enforce_rules[i].action == PG_ACTION_REPLACE)
+ if((unsigned char)ctx->enforce_rules[i].action == PG_ACTION_MANIPULATE)
{
if(i+1 > ctx->n_enforce)
{
@@ -1508,10 +2209,13 @@ void pangu_on_http_end(const struct tfe_stream * stream,
}
struct pangu_log log_msg = {.stream=stream, .http=session, .result=ctx->enforce_rules, .result_num=ctx->n_enforce,
.req_body= ctx->log_req_body, .resp_body=ctx->log_resp_body};
- if (ctx->action != PG_ACTION_NONE&& !(ctx->action == PG_ACTION_REPLACE && ctx->n_enforce==1 && ctx->rep_ctx->actually_replaced==0))
+ if (ctx->action != PG_ACTION_NONE&&
+ !(ctx->action == PG_ACTION_MANIPULATE &&
+ ctx->param->action == MA_ACTION_REPLACE &&
+ ctx->n_enforce==1 && ctx->rep_ctx->actually_replaced==0))
{
ret=pangu_send_log(g_pangu_rt->send_logger, &log_msg);
- ATOMIC_ADD(&(g_pangu_rt->stat_val[STAT_LOG_NUM]), ret);
+ ATOMIC_ADD(&(g_pangu_rt->stat_val[STAT_LOG_NUM]), ret);
}
if(ctx->rep_ctx && ctx->rep_ctx->actually_replaced==0)
{
@@ -1541,7 +2245,7 @@ void pangu_on_http_data(const struct tfe_stream * stream, const struct tfe_http_
}
return;
}
-
+
enforce_control_policy(stream, session, events, body_frag, frag_size,thread_id, ctx);
if(g_pangu_rt->cache_enabled && ctx->action == PG_ACTION_NONE)
@@ -1570,8 +2274,6 @@ void pangu_on_http_data(const struct tfe_stream * stream, const struct tfe_http_
return;
}
-
-
struct tfe_plugin pangu_http_spec = {
.symbol=NULL,
.type = TFE_PLUGIN_TYPE_BUSINESS,
diff --git a/plugin/business/pangu-http/src/pattern_replace.cpp b/plugin/business/pangu-http/src/pattern_replace.cpp
index e015803..b81da0b 100644
--- a/plugin/business/pangu-http/src/pattern_replace.cpp
+++ b/plugin/business/pangu-http/src/pattern_replace.cpp
@@ -7,6 +7,7 @@
#include
#include
+#include
#include
#include
@@ -30,7 +31,8 @@ enum replace_zone zone_name_to_id(const char * name)
}
return (enum replace_zone) i;
}
-static char * strchr_esc(char * s, const char delim)
+static char *__attribute__((__unused__))
+strchr_esc(char * s, const char delim)
{
char * token;
if (s == NULL)
@@ -54,7 +56,8 @@ static char * strchr_esc(char * s, const char delim)
return token;
}
}
-static char * strtok_r_esc(char * s, const char delim, char ** save_ptr)
+static char *__attribute__((__unused__))
+strtok_r_esc(char * s, const char delim, char ** save_ptr)
{
char * token;
@@ -75,8 +78,26 @@ static char * strtok_r_esc(char * s, const char delim, char ** save_ptr)
return s;
}
+char *rt_read_file(const char* filename, size_t *input_sz)
+{
+ FILE* fp=NULL;
+ struct stat file_info;
+ stat(filename, &file_info);
+ *input_sz=file_info.st_size;
-size_t format_replace_rule(const char * exec_para, struct replace_rule * replace, size_t n_replace)
+ fp=fopen(filename,"r");
+ if(fp==NULL)
+ {
+ return NULL;
+ }
+ char* data=(char*)malloc((*input_sz));
+ fread(data,1,*input_sz,fp);
+ fclose(fp);
+
+ return data;
+}
+size_t __attribute__((__unused__))
+format_replace_rule(const char * exec_para, struct replace_rule * replace, size_t n_replace)
{
char * tmp = ALLOC(char, strlen(exec_para) + 1);
char * token = NULL, * sub_token = NULL, * saveptr = NULL, * saveptr2 = NULL;
@@ -225,15 +246,81 @@ size_t execute_replace_rule(const char * in, size_t in_sz,
return 0;
}
}
+
+size_t insert_string(char * in, size_t in_sz, const char *insert_on, const char *stype, const char *type, char** out)
+{
+ char *target=NULL;
+ size_t outlen=0, target_size=0;
+ char position[]="";
+
+ /* ""*/
+ int js_type_len = 58;
+ /*""*/
+ int css_type_len = 49;
+
+ char* head_string=NULL;
+
+ if (0==strcasecmp(type, "css"))
+ {
+ target_size = in_sz+strlen(stype)+css_type_len;
+ target = ALLOC(char, target_size);
+ }
+
+ if (0==strcasecmp(type, "js"))
+ {
+ target_size = in_sz+strlen(stype)+js_type_len;
+ target = ALLOC(char, target_size);
+ }
+
+ if (insert_on != NULL && 0==strcasecmp(insert_on, "after-page-load"))
+ {
+ memcpy(position, "
+Index of /centos/
../
+2/ 09-Sep-2009 05:18 -
+2.1/ 09-Sep-2009 05:18 -
+3/ 02-Mar-2011 23:44 -
+3.1/ 02-Mar-2011 23:44 -
+3.3/ 02-Mar-2011 23:44 -
+3.4/ 02-Mar-2011 23:44 -
+3.5/ 02-Mar-2011 23:44 -
+3.6/ 02-Mar-2011 23:44 -
+3.7/ 02-Mar-2011 23:44 -
+3.8/ 02-Mar-2011 23:44 -
+3.9/ 02-Mar-2011 23:44 -
+4/ 03-Apr-2017 11:34 -
+4.0/ 18-Jul-2005 21:11 -
+4.1/ 21-Oct-2005 17:54 -
+4.2/ 04-Nov-2006 12:43 -
+4.3/ 10-Nov-2006 22:15 -
+4.4/ 07-Jul-2007 18:21 -
+4.5/ 10-Jan-2008 16:12 -
+4.6/ 31-Mar-2009 11:55 -
+4.7/ 08-Mar-2010 10:56 -
+4.8/ 13-Mar-2012 00:14 -
+4.9/ 03-Apr-2017 11:34 -
+5/ 03-Apr-2017 11:34 -
+5.0/ 16-Oct-2014 13:37 -
+5.1/ 16-Oct-2014 13:37 -
+5.10/ 03-Apr-2017 11:30 -
+5.11/ 03-Apr-2017 11:34 -
+5.2/ 16-Oct-2014 13:37 -
+5.3/ 16-Oct-2014 13:37 -
+5.4/ 16-Oct-2014 13:37 -
+5.5/ 16-Oct-2014 13:37 -
+5.6/ 16-Oct-2014 13:37 -
+5.7/ 16-Oct-2014 13:37 -
+5.8/ 16-Oct-2014 13:37 -
+5.9/ 16-Oct-2014 13:38 -
+6/ 02-Jul-2018 15:32 -
+6.0/ 16-Oct-2014 13:42 -
+6.1/ 16-Oct-2014 13:42 -
+6.10/ 02-Jul-2018 15:32 -
+6.2/ 16-Oct-2014 13:42 -
+6.3/ 16-Oct-2014 13:42 -
+6.4/ 16-Oct-2014 13:42 -
+6.5/ 05-Jan-2015 14:33 -
+6.6/ 12-Aug-2015 12:23 -
+6.7/ 01-Jun-2016 16:09 -
+6.8/ 12-Jun-2017 12:38 -
+6.9/ 25-Jul-2018 15:42 -
+7/ 02-Dec-2018 14:34 -
+7.0.1406/ 07-Apr-2015 14:24 -
+7.1.1503/ 08-Jan-2016 15:25 -
+7.2.1511/ 28-Jan-2017 14:29 -
+7.3.1611/ 25-Oct-2017 14:57 -
+7.4.1708/ 24-May-2018 13:25 -
+7.5.1804/ 04-Jan-2019 16:00 -
+7.6.1810/ 02-Dec-2018 14:34 -
+HEADER.images/ 07-Nov-2013 15:21 -
+build/ 12-Jun-2005 12:56 -
+dostools/ 04-Apr-2007 09:45 -
+graphics/ 12-Jun-2014 11:59 -
+HEADER.html 29-Sep-2014 19:27 1234
+RPM-GPG-KEY-CentOS-3 15-Mar-2004 23:16 1795
+RPM-GPG-KEY-CentOS-4 26-Feb-2005 17:51 1795
+RPM-GPG-KEY-CentOS-5 19-Feb-2007 17:57 1504
+RPM-GPG-KEY-CentOS-6 10-Jul-2011 14:28 1706
+RPM-GPG-KEY-CentOS-7 04-Jul-2014 16:01 1690
+RPM-GPG-KEY-CentOS-Debug-6 10-Jul-2011 14:28 1730
+RPM-GPG-KEY-CentOS-Debug-7 09-Dec-2015 09:59 1004
+RPM-GPG-KEY-CentOS-Security-6 10-Jul-2011 14:28 1730
+RPM-GPG-KEY-CentOS-Testing-6 10-Jul-2011 14:28 1734
+RPM-GPG-KEY-CentOS-Testing-7 09-Dec-2015 09:59 1690
+RPM-GPG-KEY-beta 19-Feb-2007 17:56 1512
+RPM-GPG-KEY-centos4 26-Feb-2005 17:51 1795
+TIME 17-May-2019 05:35 11
+dir_sizes 17-May-2019 05:10 963
+filelist.gz 17-May-2019 05:10 5612272
+timestamp.txt 17-May-2019 05:35 29
+
+
+", sizeof(position));
+ }
+ head_string=strstr(in, position);
+ if (head_string != NULL)
+ {
+ strncat(target, in, MIN((unsigned int)(head_string-in), target_size));
+ size_t style_len = 0; char *style_msg = NULL;
+ if (0==strcasecmp(type, "js"))
+ {
+ style_len = strlen(stype)+js_type_len+1;
+ style_msg = ALLOC(char, style_len);
+ snprintf(style_msg, style_len, "", stype);
+ }
+ if (0==strcasecmp(type, "css"))
+ {
+ style_len = strlen(stype)+css_type_len+1;
+ style_msg = ALLOC(char, style_len);
+ snprintf(style_msg, style_len, "\n", stype);
+ }
+ strncat(target, style_msg, target_size);
+ free(style_msg);
+ style_msg = NULL;
+ strncat(target, head_string, target_size);
+ *out = target;
+ outlen = strlen(target) + 1;
+ }else
+ {
+ free(target);
+ target = NULL;
+ outlen = 0;
+ }
+ return outlen;
+}
+
+size_t execute_insert_rule(char * in, size_t in_sz, const struct insert_rule * rules, char** out)
+{
+ return insert_string(in, in_sz, rules->position, rules->stype, rules->type, out);
+}
+
void simple_replace(const char* find, const char* replacement, const char* input, size_t in_sz, char** output, size_t *output_sz)
{
- char* exec_para=NULL;
- asprintf(&exec_para,"zone=http_resp_body;substitute=/%s/%s", find, replacement);
- size_t n_got_rule=0;
+ size_t n_got_rule=1;
struct replace_rule rules[16];
- n_got_rule=format_replace_rule(exec_para, rules, sizeof(rules)/sizeof(rules[0]));
+ rules[0].zone = kZoneResponseBody;
+ rules[0].find = tfe_strdup(find);
+ rules[0].replace_with = tfe_strdup(replacement);
*output_sz=execute_replace_rule(input, strlen(input), kZoneResponseBody, rules, n_got_rule, output);
- free(exec_para);
return;
}
diff --git a/plugin/business/pangu-http/src/pattern_replace.h b/plugin/business/pangu-http/src/pattern_replace.h
index 3786999..6c89dd7 100644
--- a/plugin/business/pangu-http/src/pattern_replace.h
+++ b/plugin/business/pangu-http/src/pattern_replace.h
@@ -9,6 +9,11 @@ enum replace_zone
kZoneResponseBody,
kZoneMax
};
+
+/**
+ rule type: replace
+ rule type: insert(find: insert on, replace_with: insert content)
+*/
struct replace_rule
{
enum replace_zone zone;
@@ -16,11 +21,22 @@ struct replace_rule
char * replace_with;
};
+struct insert_rule
+{
+ char * stype;
+ char * type;
+ char * position;
+};
//@parm exec_para example input:
//zone=http_req_body; substitute=/中華民國/中华人民共和国;zone=http_resp_header; substitute=/Content-Type:\btext\/html/Content-Type:\bvideo\/mp4
//@return formated rule number.
-size_t format_replace_rule(const char * exec_para, struct replace_rule * replace, size_t n_replace);
size_t execute_replace_rule(const char * in, size_t in_sz, enum replace_zone zone, const struct replace_rule * rules, size_t n_rule, char** out);
+size_t execute_insert_rule(char * in, size_t in_sz, const struct insert_rule * rules, char** out);
+size_t insert_string(char * in, size_t in_sz, const char *insert_on, const char *stype, const char *type, char** out);
void simple_replace(const char* find, const char* replacement, const char* input, size_t in_sz, char** output, size_t *output_sz);
+enum replace_zone zone_name_to_id(const char * name);
+char *rt_read_file(const char* filename, size_t *input_sz);
+
+
diff --git a/plugin/business/pangu-http/src/test_pattern_replace.cpp b/plugin/business/pangu-http/src/test_pattern_replace.cpp
index ba1bc51..b5ef209 100644
--- a/plugin/business/pangu-http/src/test_pattern_replace.cpp
+++ b/plugin/business/pangu-http/src/test_pattern_replace.cpp
@@ -113,6 +113,70 @@ TEST(PatternReplace, UTF8)
return;
}
+TEST(PatternInsert, CSS)
+{
+ const char* filename="./test_data/index_of__centos.html";
+ const char* custom = "h1,h2{color: red;}ul.tabmain a{color: green;}";
+ char *input=NULL, *output=NULL;
+ size_t output_sz=0, input_sz = 0;
+
+ input = rt_read_file(filename, &input_sz);
+ EXPECT_TRUE(input_sz>0);
+
+ output_sz = insert_string(input, input_sz, NULL, custom, "css", &output);
+
+ //printf("output = %s\n", output);
+
+ EXPECT_TRUE(output_sz>0);
+ EXPECT_TRUE(NULL!=strstr(output, custom));
+ free(output);
+ free(input);
+}
+
+TEST(PatternInsert, after_body)
+{
+ const char* filename="./test_data/index_of__centos.html";
+ const char* custom = "var now=new Date();var year=now.getYear()+1900;var month=now.getMonth()+1;var date=now.getDate();var day=now.getDay();\
+ var time=\"curtime\"+year+\"year\"+month+\"month\"+date+\"date\"+week;alert(time);";
+ char *input=NULL, *output=NULL;
+ size_t output_sz=0, input_sz = 0;
+
+ input = rt_read_file(filename, &input_sz);
+ EXPECT_TRUE(input_sz>0);
+
+ output_sz = insert_string(input, input_sz, "after-page-load", custom, "js", &output);
+
+ //printf("%s\n", output);
+
+ EXPECT_TRUE(output_sz>0);
+ EXPECT_TRUE(NULL!=strstr(output, custom));
+
+ free(input);
+ free(output);
+ output = NULL;
+}
+
+TEST(PatternInsert, before_body)
+{
+ const char* filename="./test_data/index_of__centos.html";
+ const char* custom = "var now=new Date();var year=now.getYear()+1900;var month=now.getMonth()+1;var date=now.getDate();var day=now.getDay();\
+ var time=\"curtime\"+year+\"year\"+month+\"month\"+date+\"date\"+week;alert(time);";
+ char *input=NULL, *output=NULL;
+ size_t output_sz=0, input_sz = 0;
+
+ input = rt_read_file(filename, &input_sz);
+ EXPECT_TRUE(input_sz>0);
+
+ output_sz = insert_string(input, input_sz, "before-page-load", custom, "js", &output);
+ //printf("%s\n", output);
+
+ EXPECT_TRUE(output_sz>0);
+ EXPECT_TRUE(NULL!=strstr(output, custom));
+
+ free(input);
+ free(output);
+ output = NULL;
+}
int main(int argc, char ** argv)
{
diff --git a/plugin/business/pangu-http/test_data/index_of__centos.html b/plugin/business/pangu-http/test_data/index_of__centos.html
new file mode 100644
index 0000000..25cdabb
--- /dev/null
+++ b/plugin/business/pangu-http/test_data/index_of__centos.html
@@ -0,0 +1,85 @@
+
+
+