#include "pattern_replace.h" #include "http_lua.h" #include #include #include #include #include #include #include static const char __attribute__((__unused__))*http_lua_log_get_url(struct tsg_script_ctx *tsg_ctx) { enum tfe_http_event events = tsg_ctx->events; if(events < EV_HTTP_REQ_HDR) { return NULL; } const struct tfe_http_session * session = tsg_ctx->session; if(session == NULL) { return NULL; } struct tfe_http_half * in_req_half = session->req; if(in_req_half == NULL) return NULL; struct tfe_http_req_spec * in_req_spec = &in_req_half->req_spec; if(in_req_spec == NULL) return NULL; if (in_req_spec->url != NULL) { return in_req_spec->url; } return NULL; } static int http_get_param_from_lua(struct elua_vm *vm, struct elua_data **out_lua_argv) { int i=0, out_lua_argc=0; struct elua_data *lua_argv=NULL; out_lua_argc = elua_cbinding_get_input_params_num(vm); if(out_lua_argc <= 0) { return 0; } lua_argv = ALLOC(struct elua_data, out_lua_argc); for (i = 0; i < out_lua_argc; i++) { elua_cbinding_get_input_param(vm, i+1, &lua_argv[i]); } *out_lua_argv = lua_argv; return out_lua_argc; } void http_free_params(struct elua_data *out_lua_argv) { if(out_lua_argv) FREE(&out_lua_argv); } int http_set_string_to_lua(struct elua_vm *vm, const char *buff, size_t len) { struct elua_data edata; edata.type = STRING; edata.buff = (char *)buff; edata.len = len; elua_cbinding_append_output_params(vm, &edata, 1); return 1; } int http_set_num_to_lua(struct elua_vm *vm, long num) { struct elua_data retvalue; retvalue.type = INTEGER; retvalue.len = sizeof(long); retvalue.integer = num; elua_cbinding_append_output_params(vm, &retvalue, 1); return 1; } int http_set_table_to_lua(struct elua_vm *vm, struct elua_table *table) { struct elua_data retvalue; retvalue.type = TABLE; retvalue.table = table; retvalue.len = sizeof(struct elua_data); elua_cbinding_append_output_params(vm, &retvalue, 1); elua_destroy_table(table); return 1; } static int http_lua_log_debug(struct elua_vm *vm) { int out_lua_argc=0, i=0; struct elua_data *out_lua_argv=NULL; struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } out_lua_argc = http_get_param_from_lua(vm, &out_lua_argv); if(out_lua_argc < 1 || out_lua_argv == NULL) { return 0; } char buff[TFE_STRING_MAX]={0}, *p = NULL; p = buff; for(i=0; ilocal_logger, "policy_id:%d, profile_id:%d, message:%20s", tsg_ctx->config_id, tsg_ctx->profile_id, buff); http_free_params(out_lua_argv); return 1; } static int http_lua_log_info(struct elua_vm *vm) { int out_lua_argc=0, i=0; struct elua_data *out_lua_argv=NULL; struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } out_lua_argc = http_get_param_from_lua(vm, &out_lua_argv); if(out_lua_argc < 1 || out_lua_argv == NULL) { return 0; } char buff[TFE_STRING_MAX]={0}, *p = NULL; p = buff; for(i=0; ilocal_logger, "policy_id:%d, profile_id:%d, message:%s", tsg_ctx->config_id, tsg_ctx->profile_id, buff); http_free_params(out_lua_argv); return 1; } static int http_lua_log_error(struct elua_vm *vm) { int out_lua_argc=0, i=0; struct elua_data *out_lua_argv=NULL; struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } out_lua_argc = http_get_param_from_lua(vm, &out_lua_argv); if(out_lua_argc < 1 || out_lua_argv == NULL) { return 0; } char buff[TFE_STRING_MAX]={0}, *p = NULL; p = buff; for(i=0; ilocal_logger, "policy_id:%d, profile_id:%d, message:%s", tsg_ctx->config_id, tsg_ctx->profile_id, buff); http_free_params(out_lua_argv); return 1; } static int http_lua_get_method(struct elua_vm *vm) { struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } enum tfe_http_event events = tsg_ctx->events; if(tfe_http_in_response(events)) { return 0; } const struct tfe_http_session * session = tsg_ctx->session; if(session == NULL) { return 0; } struct tfe_http_half * in_req_half = session->req; struct tfe_http_req_spec * in_req_spec = &in_req_half->req_spec; const char *method_str = http_std_method_to_string(in_req_spec->method); if(method_str != NULL) { http_set_string_to_lua(vm, method_str, strlen(method_str)); } return 1; } static int http_lua_get_uri(struct elua_vm *vm) { struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } enum tfe_http_event events = tsg_ctx->events; if(tfe_http_in_response(events) || !tsg_ctx->http_req_uri) { return 0; } const struct tfe_http_session * session = tsg_ctx->session; if(session == NULL) { return 0; } struct tfe_http_half * in_req_half = session->req; struct tfe_http_req_spec * in_req_spec = &in_req_half->req_spec; if (in_req_spec->uri != NULL) { http_set_string_to_lua(vm, in_req_spec->uri, strlen(in_req_spec->uri)); } return 1; } static int http_lua_set_uri(struct elua_vm *vm) { int out_lua_argc = 0; struct elua_data *out_lua_argv = NULL; out_lua_argc = http_get_param_from_lua(vm, &out_lua_argv); if(out_lua_argc != 1 || out_lua_argv == NULL) { return 0; } char * rewrite_uri = out_lua_argv[0].buff; struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } enum tfe_http_event events = tsg_ctx->events; if(tfe_http_in_response(events) || !tsg_ctx->http_req_uri) { return 0; } const struct tfe_http_session * session = tsg_ctx->session; if(session == NULL) { return 0; } struct tfe_http_half * in_req_half = session->req; struct tfe_http_req_spec * in_req_spec = &in_req_half->req_spec; if (in_req_spec->uri != NULL) { tsg_ctx->execut_lua_sucess=1; tsg_ctx->rewrite_uri = tfe_strdup(rewrite_uri); } http_free_params(out_lua_argv); return 1; } static int http_lua_get_status_code(struct elua_vm *vm) { struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } enum tfe_http_event events = tsg_ctx->events; if(tfe_http_in_request(events)) { return 0; } const struct tfe_http_session * session = tsg_ctx->session; if(session == NULL) { return 0; } struct tfe_http_half * in_resp_half = session->resp; struct tfe_http_resp_spec * in_resp_spec = &in_resp_half->resp_spec; if (in_resp_spec != NULL) { http_set_num_to_lua(vm, in_resp_spec->resp_code); } return 1; } static int http_lua_set_status_code(struct elua_vm *vm) { int out_lua_argc = 0; struct elua_data *out_lua_argv = NULL; out_lua_argc = http_get_param_from_lua(vm, &out_lua_argv); if(out_lua_argc != 1 || out_lua_argv == NULL) { return 0; } int lua_resp_code = out_lua_argv[0].integer; struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } enum tfe_http_event events = tsg_ctx->events; if(tfe_http_in_request(events)) { return 0; } const struct tfe_http_session * session = tsg_ctx->session; if(session == NULL) { return 0; } struct tfe_http_half * in_resp_half = session->resp; struct tfe_http_resp_spec * in_resp_spec = &in_resp_half->resp_spec; if(lua_resp_code != 0) { in_resp_spec->resp_code = lua_resp_code; } http_free_params(out_lua_argv); return 1; } static int http_lua_exit(struct elua_vm *vm) { int out_lua_argc = 0; struct elua_data *out_lua_argv = NULL; out_lua_argc = http_get_param_from_lua(vm, &out_lua_argv); if(out_lua_argc != 1 || out_lua_argv == NULL) { return 0; } int exit_code = out_lua_argv[0].integer; struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } if(exit_code == 0) { tsg_ctx->events = (enum tfe_http_event )0; return 0; } http_free_params(out_lua_argv); return 1; } static int http_lua_get_current_stage(struct elua_vm *vm) { const char * stage_name[] = {"http_req_uri", "http_req_header","http_req_body","http_resp_header","http_resp_body","http_stage_test"}; struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } const struct tfe_http_session * session = tsg_ctx->session; if(session == NULL) { return 0; } enum tfe_http_event events = tsg_ctx->events; //For test_http_lua if(tsg_ctx->http_req_uri==2) { http_set_string_to_lua(vm, stage_name[5], strlen(stage_name[5])); return 1; } if(events & EV_HTTP_REQ_HDR) { if(tsg_ctx->http_req_uri) { http_set_string_to_lua(vm, stage_name[0], strlen(stage_name[0])); } else { http_set_string_to_lua(vm, stage_name[1], strlen(stage_name[1])); } } if((events & EV_HTTP_REQ_BODY_BEGIN) | (events & EV_HTTP_REQ_BODY_END) | (events & EV_HTTP_REQ_BODY_CONT)) { http_set_string_to_lua(vm, stage_name[2], strlen(stage_name[2])); } if(events & EV_HTTP_RESP_HDR) { http_set_string_to_lua(vm, stage_name[3], strlen(stage_name[3])); } if((events & EV_HTTP_RESP_BODY_BEGIN) | (events & EV_HTTP_RESP_BODY_CONT) | (events & EV_HTTP_RESP_BODY_END)) { http_set_string_to_lua(vm, stage_name[4], strlen(stage_name[4])); } return 1; } static int http_lua_get_headers(struct elua_vm *vm) { struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } const struct tfe_http_session * session = tsg_ctx->session; if(session == NULL) { return 0; } enum tfe_http_event events = tsg_ctx->events; struct tfe_http_half * in_req_half = session->req; struct tfe_http_half * in_resp_half = session->resp; struct tfe_http_half * in_half = tfe_http_in_request(events) ? in_req_half : in_resp_half; if(in_half == NULL) { return 0; } struct http_field_name in_header_field{}; const char * in_header_value = NULL; void * iterator = NULL; struct elua_data in_field_name, in_field_value; struct elua_table *table = elua_create_table(vm); in_field_name.type = STRING; in_field_value.type = STRING; while (true) { if ((in_header_value = tfe_http_field_iterate(in_half, &iterator, &in_header_field)) == NULL) { break; } in_field_name.buff = (char *)http_field_name_to_string(&in_header_field); in_field_name.len = strlen(http_field_name_to_string(&in_header_field)); in_field_value.buff = (char *)in_header_value; in_field_value.len = strlen(in_header_value); elua_add_table(table, &in_field_name, &in_field_value); } http_set_table_to_lua(vm, table); return 1; } static int http_lua_set_headers(struct elua_vm *vm) { int actually_write=0; struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } const struct tfe_http_session * session = tsg_ctx->session; if(session == NULL) { return 0; } enum tfe_http_event events = tsg_ctx->events; struct tfe_http_half * in_req_half = session->req; struct tfe_http_half * in_resp_half = session->resp; struct tfe_http_half * in_half = tfe_http_in_request(events) ? in_req_half : in_resp_half; if(in_half == NULL) { return 0; } struct http_field_name in_header_field{}; const char * in_header_value = NULL; void * iterator = NULL; int out_lua_argc = 0; struct elua_data *out_lua_argv = NULL; const char *in_field_name; out_lua_argc = http_get_param_from_lua(vm, &out_lua_argv); if(out_lua_argc != 2 || out_lua_argv == NULL) { return 0; } char *field_name=out_lua_argv[0].buff, *field_value=out_lua_argv[1].buff; if(field_name == NULL || field_value == NULL) { return 0; } while (true) { if ((in_header_value = tfe_http_field_iterate(in_half, &iterator, &in_header_field)) == NULL) { break; } in_field_name = http_field_name_to_string(&in_header_field); if(strcasecmp(in_field_name, field_name)==0 && strcasecmp(field_value, "nil")!=0) { if(in_header_field.field_id == TFE_HTTP_UNKNOWN_FIELD) { continue; } tfe_http_std_field_write(in_half, in_header_field.field_id, NULL); tfe_http_std_field_write(in_half, in_header_field.field_id, field_value); actually_write=1; break; } if(strcasecmp(http_field_name_to_string(&in_header_field), field_name)==0 && strcasecmp(field_value, "nil")==0) { if(in_header_field.field_id == TFE_HTTP_UNKNOWN_FIELD) { continue; } tfe_http_std_field_write(in_half, in_header_field.field_id, NULL); actually_write=1; break; } } if(actually_write ==1) { tsg_ctx->execut_lua_sucess=1; } if(actually_write!=1 && strcasecmp(field_value, "nil")!=0) { tfe_http_nonstd_field_write(in_half, field_name, field_value); tsg_ctx->execut_lua_sucess=1; } http_free_params(out_lua_argv); return 0; } static int http_lua_get_body(struct elua_vm *vm) { struct tsg_script_ctx *tsg_ctx = (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } if(tsg_ctx->http_body == NULL) { TFE_LOG_ERROR(tsg_ctx->local_logger, "policy_id:%d, profile_id:%d, message:%s", tsg_ctx->config_id, tsg_ctx->profile_id, "Can't to get req/resp body data"); return 0; } char * __http_body = (char *) evbuffer_pullup(tsg_ctx->http_body, -1); size_t __http_body_len = evbuffer_get_length(tsg_ctx->http_body); http_set_string_to_lua(vm, __http_body, __http_body_len); return 1; } static int http_lua_set_body(struct elua_vm *vm) { int i=0; struct tsg_script_ctx *tsg_ctx= (struct tsg_script_ctx *)elua_get_execute_userdata(vm); if(tsg_ctx == NULL) { return 0; } int out_lua_argc = 0; struct elua_data *out_lua_argv = NULL; out_lua_argc=http_get_param_from_lua(vm, &out_lua_argv); if(out_lua_argc < 1 || out_lua_argv == NULL) { return 0; } tsg_ctx->http_lua_body = evbuffer_new(); for(i=0; ihttp_lua_body, in, in_sz); } http_free_params(out_lua_argv); return 0; } struct elua_context *http_lua_ctx_new(struct tsg_lua_script *lua_script, unsigned int thread_id) { return elua_create_context(lua_script->http_lua_handle[thread_id], "context"); } struct elua_script *http_lua_map_cache_script(struct elua_vm *vm, const char *script, size_t script_len, size_t timeout_ms) { return elua_cache_script(vm, script, script_len, timeout_ms); } void http_lua_ctx_free(struct tsg_lua_script *lua_script, unsigned int thread_id, struct elua_context *elua_ctx) { if(elua_ctx) elua_destroy_context(elua_ctx); } void http_lua_inject_http_consts(struct elua_vm *vm) { elua_register_cbinding(vm, NULL, "get_current_stage", http_lua_get_current_stage); elua_register_cbinding(vm, NULL, "log_debug", http_lua_log_debug); elua_register_cbinding(vm, NULL, "log_info", http_lua_log_info); elua_register_cbinding(vm, NULL, "log_error", http_lua_log_error); elua_register_cbinding(vm, NULL, "exit", http_lua_exit); } void http_lua_inject_req_header_api(struct elua_vm *vm) { elua_register_cbinding(vm, "req", "get_method", http_lua_get_method); elua_register_cbinding(vm, "req", "get_uri", http_lua_get_uri); elua_register_cbinding(vm, "req", "set_uri", http_lua_set_uri); elua_register_cbinding(vm, "req", "get_headers", http_lua_get_headers); elua_register_cbinding(vm, "req", "set_header", http_lua_set_headers); } void http_lua_inject_req_body_api(struct elua_vm *vm) { elua_register_cbinding(vm, "req", "get_body_data", http_lua_get_body); elua_register_cbinding(vm, "req", "set_body_data", http_lua_set_body); } void http_lua_inject_resp_header_api(struct elua_vm *vm) { elua_register_cbinding(vm, "resp", "get_status_code", http_lua_get_status_code); elua_register_cbinding(vm, "resp", "set_status_code", http_lua_set_status_code); elua_register_cbinding(vm, "resp", "get_headers", http_lua_get_headers); elua_register_cbinding(vm, "resp", "set_header", http_lua_set_headers); } void http_lua_inject_resp_body_api(struct elua_vm *vm) { elua_register_cbinding(vm, "resp", "get_body_data", http_lua_get_body); elua_register_cbinding(vm, "resp", "set_body_data", http_lua_set_body); } void http_lua_inject_api(struct elua_vm *vm) { http_lua_inject_http_consts(vm); http_lua_inject_req_header_api(vm); http_lua_inject_req_body_api(vm); http_lua_inject_resp_header_api(vm); http_lua_inject_resp_body_api(vm); } int http_lua_handle_create(struct tsg_lua_script *lua_script, int thread_num, const char *name_space) { int id=0; struct elua_vm **http_lua_handle = NULL; http_lua_handle = ALLOC(struct elua_vm *, thread_num); if(http_lua_handle == NULL) { return 0; } for(id=0; id < thread_num; id++) { http_lua_handle[id] = elua_create_vm(name_space); if(http_lua_handle[id] == NULL) { goto finish; } http_lua_inject_api(http_lua_handle[id]); } lua_script->http_lua_handle=http_lua_handle; return 1; finish: for(id=0; id < thread_num; id++) { if(http_lua_handle[id]) FREE(&http_lua_handle[id]) } free(http_lua_handle); return 0; } size_t execute_lua_script_rule(struct tsg_lua_script *lua_script, int profile_id, struct elua_context *elua_ctx, unsigned int thread_id, void *user_data) { int ret=0; struct elua_script **escript=NULL; ret=lua_script->http_lua_profile(profile_id, &escript); if(ret<0) { return ret; } const char *input="tfe"; size_t input_len=strlen(input); ret=elua_execute_script(escript[thread_id], input, input_len, user_data, elua_ctx, NULL); if(ret !=0 ) { struct tsg_script_ctx *tsg_ctx= (struct tsg_script_ctx *)user_data; if(tsg_ctx != NULL && tsg_ctx->local_logger != NULL) { TFE_LOG_ERROR(tsg_ctx->local_logger, "policy_id:%d, profile_id:%d, error_code:%d, error: %s", tsg_ctx->config_id, tsg_ctx->profile_id, ret, elua_get_last_error_string(lua_script->http_lua_handle[thread_id])); } } return ret; }