2018-09-14 16:33:36 +08:00
|
|
|
#include "pangu_logger.h"
|
2018-09-14 11:42:22 +08:00
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
#include <tfe_stream.h>
|
|
|
|
|
#include <tfe_utils.h>
|
|
|
|
|
#include <tfe_http.h>
|
2018-09-18 12:01:56 +08:00
|
|
|
#include <tfe_plugin.h>
|
2018-09-12 16:04:04 +08:00
|
|
|
|
|
|
|
|
#include <MESA/Maat_rule.h>
|
|
|
|
|
#include <MESA/MESA_handle_logger.h>
|
|
|
|
|
#include <MESA/MESA_prof_load.h>
|
|
|
|
|
#include <MESA/stream.h>
|
2018-09-09 15:21:26 +08:00
|
|
|
|
2018-09-13 19:28:13 +08:00
|
|
|
#include <event2/event.h>
|
|
|
|
|
#include <event2/buffer.h>
|
|
|
|
|
|
2018-09-15 20:55:31 +08:00
|
|
|
#include <ctemplate/template.h>
|
2018-09-12 16:04:04 +08:00
|
|
|
#include <assert.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
2018-09-13 19:28:13 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <regex.h>
|
|
|
|
|
|
2018-09-25 11:15:00 +08:00
|
|
|
#define MAX_SCAN_RESULT 16
|
|
|
|
|
#define MAX_EDIT_ZONE_NUM 64
|
|
|
|
|
#define MAX_EDIT_MATCHES 16
|
|
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
enum pangu_action//Bigger action number is prior.
|
|
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
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_RATELIMIT = 0x40, /* N/A */
|
|
|
|
|
PG_ACTION_REPLACE = 0x50,
|
|
|
|
|
PG_ACTION_LOOP = 0x60, /* N/A */
|
|
|
|
|
PG_ACTION_WHITELIST = 0x80
|
2018-09-12 16:04:04 +08:00
|
|
|
};
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
enum scan_table
|
|
|
|
|
{
|
|
|
|
|
PXY_CTRL_IP,
|
|
|
|
|
PXY_CTRL_HTTP_URL,
|
|
|
|
|
PXY_CTRL_HTTP_REQ_HDR,
|
|
|
|
|
PXY_CTRL_HTTP_REQ_BODY,
|
|
|
|
|
PXY_CTRL_HTTP_RES_HDR,
|
|
|
|
|
PXY_CTRL_HTTP_RES_BODY,
|
|
|
|
|
__SCAN_TABLE_MAX
|
|
|
|
|
};
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
struct pangu_rt
|
|
|
|
|
{
|
|
|
|
|
Maat_feather_t maat;
|
2018-09-23 20:02:07 +08:00
|
|
|
struct pangu_logger * send_logger;
|
|
|
|
|
void * local_logger;
|
2018-09-12 16:04:04 +08:00
|
|
|
int log_level;
|
|
|
|
|
int thread_num;
|
|
|
|
|
int scan_table_id[__SCAN_TABLE_MAX];
|
2018-09-23 20:02:07 +08:00
|
|
|
ctemplate::Template * tpl_403, * tpl_404, * tpl_451;
|
|
|
|
|
char * reject_page;
|
2018-09-12 16:04:04 +08:00
|
|
|
int page_size;
|
|
|
|
|
};
|
2018-09-23 20:02:07 +08:00
|
|
|
struct pangu_rt * g_pangu_rt;
|
2018-09-25 11:15:00 +08:00
|
|
|
|
|
|
|
|
#define MAAT_INPUT_JSON 0
|
|
|
|
|
#define MAAT_INPUT_REDIS 1
|
|
|
|
|
#define MAAT_INPUT_FILE 2
|
2018-09-18 14:02:39 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
static Maat_feather_t create_maat_feather(const char * profile, const char * section, int max_thread, void * logger)
|
2018-09-09 15:21:26 +08:00
|
|
|
{
|
|
|
|
|
Maat_feather_t target;
|
2018-09-23 20:02:07 +08:00
|
|
|
int input_mode = 0, maat_stat_on = 0, maat_perf_on = 0;
|
|
|
|
|
int ret = 0, scan_detail = 0, effect_interval = 60;
|
|
|
|
|
char table_info[TFE_STRING_MAX] = {0}, inc_cfg_dir[TFE_STRING_MAX] = {0}, ful_cfg_dir[TFE_STRING_MAX] = {0};
|
|
|
|
|
char redis_server[TFE_STRING_MAX] = {0};
|
|
|
|
|
int redis_port = 0;
|
|
|
|
|
int redis_db_idx = 0;
|
|
|
|
|
char json_cfg_file[TFE_STRING_MAX] = {0}, maat_stat_file[TFE_STRING_MAX] = {0};
|
|
|
|
|
const char * instance_name = "pangu";
|
|
|
|
|
MESA_load_profile_int_def(profile, section, "MAAT_INPUT_MODE", &(input_mode), 0);
|
|
|
|
|
MESA_load_profile_int_def(profile, section, "STAT_SWITCH", &(maat_stat_on), 1);
|
|
|
|
|
MESA_load_profile_int_def(profile, section, "PERF_SWITCH", &(maat_perf_on), 1);
|
|
|
|
|
|
|
|
|
|
MESA_load_profile_string_def(profile, section, "TABLE_INFO", table_info, sizeof(table_info), "");
|
|
|
|
|
|
|
|
|
|
MESA_load_profile_string_def(profile, section, "JSON_CFG_FILE", json_cfg_file, sizeof(json_cfg_file), "");
|
|
|
|
|
|
|
|
|
|
MESA_load_profile_string_def(profile, section, "MAAT_REDIS_SERVER", redis_server, sizeof(redis_server), "");
|
|
|
|
|
MESA_load_profile_int_def(profile, section, "MAAT_REDIS_PORT", &(redis_port), 6379);
|
|
|
|
|
MESA_load_profile_int_def(profile, section, "MAAT_REDIS_DB_INDEX", &(redis_db_idx), 0);
|
|
|
|
|
|
|
|
|
|
MESA_load_profile_string_def(profile, section, "INC_CFG_DIR", inc_cfg_dir, sizeof(inc_cfg_dir), "");
|
|
|
|
|
MESA_load_profile_string_def(profile, section, "FULL_CFG_DIR", ful_cfg_dir, sizeof(ful_cfg_dir), "");
|
|
|
|
|
|
|
|
|
|
MESA_load_profile_string_def(profile, section, "STAT_FILE", maat_stat_file, sizeof(maat_stat_file), "");
|
|
|
|
|
MESA_load_profile_int_def(profile, section, "EFFECT_INTERVAL_S", &(effect_interval), 60);
|
|
|
|
|
|
|
|
|
|
effect_interval *= 1000;//convert s to ms
|
|
|
|
|
assert(strlen(inc_cfg_dir) != 0 && strlen(ful_cfg_dir) != 0);
|
|
|
|
|
|
|
|
|
|
target = Maat_feather(max_thread, table_info, logger);
|
|
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_INSTANCE_NAME, instance_name, strlen(instance_name) + 1);
|
|
|
|
|
switch (input_mode)
|
|
|
|
|
{
|
|
|
|
|
case MAAT_INPUT_JSON:
|
|
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_JSON_FILE_PATH, json_cfg_file, strlen(json_cfg_file) + 1);
|
2018-09-18 14:02:39 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
case MAAT_INPUT_REDIS: Maat_set_feather_opt(target, MAAT_OPT_REDIS_IP, redis_server, strlen(redis_server) + 1);
|
|
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_REDIS_PORT, &redis_port, sizeof(redis_port));
|
|
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_REDIS_INDEX, &redis_db_idx, sizeof(redis_db_idx));
|
2018-09-18 14:02:39 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
case MAAT_INPUT_FILE: Maat_set_feather_opt(target, MAAT_OPT_FULL_CFG_DIR, ful_cfg_dir, strlen(ful_cfg_dir) + 1);
|
|
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_INC_CFG_DIR, inc_cfg_dir, strlen(inc_cfg_dir) + 1);
|
2018-09-18 14:02:39 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
default: TFE_LOG_ERROR(logger, "Invalid MAAT Input Mode: %d.", input_mode);
|
2018-09-18 14:02:39 +08:00
|
|
|
goto error_out;
|
|
|
|
|
break;
|
2018-09-09 15:21:26 +08:00
|
|
|
}
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
if (maat_stat_on)
|
2018-09-09 15:21:26 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_STAT_FILE_PATH, maat_stat_file, strlen(maat_stat_file) + 1);
|
2018-09-09 15:21:26 +08:00
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_STAT_ON, NULL, 0);
|
2018-09-23 20:02:07 +08:00
|
|
|
if (maat_perf_on)
|
2018-09-09 15:21:26 +08:00
|
|
|
{
|
|
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_PERF_ON, NULL, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_EFFECT_INVERVAL_MS, &effect_interval, sizeof(effect_interval));
|
|
|
|
|
Maat_set_feather_opt(target, MAAT_OPT_SCAN_DETAIL, &scan_detail, sizeof(scan_detail));
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
ret = Maat_initiate_feather(target);
|
|
|
|
|
if (ret < 0)
|
2018-09-09 15:21:26 +08:00
|
|
|
{
|
2018-09-12 16:04:04 +08:00
|
|
|
TFE_LOG_ERROR(logger, "%s MAAT init failed.", __FUNCTION__);
|
2018-09-18 14:02:39 +08:00
|
|
|
goto error_out;
|
2018-09-09 15:21:26 +08:00
|
|
|
}
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-09 15:21:26 +08:00
|
|
|
return target;
|
2018-09-18 14:02:39 +08:00
|
|
|
error_out:
|
|
|
|
|
Maat_burn_feather(target);
|
|
|
|
|
return NULL;
|
2018-09-09 15:21:26 +08:00
|
|
|
}
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-18 12:01:56 +08:00
|
|
|
int pangu_http_init(struct tfe_proxy * proxy)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
const char * profile = "./pangu_conf/pangu_pxy.conf";
|
|
|
|
|
const char * logfile = "./log/pangu_pxy.log";
|
|
|
|
|
g_pangu_rt = ALLOC(struct pangu_rt, 1);
|
|
|
|
|
g_pangu_rt->thread_num = 16;
|
|
|
|
|
MESA_load_profile_int_def(profile, "DEBUG", "LOG_LEVEL", &(g_pangu_rt->log_level), 0);
|
|
|
|
|
g_pangu_rt->local_logger = MESA_create_runtime_log_handle(logfile, g_pangu_rt->log_level);
|
|
|
|
|
g_pangu_rt->send_logger = pangu_log_handle_create(profile, "LOG", g_pangu_rt->local_logger);
|
|
|
|
|
if (!g_pangu_rt->send_logger)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
|
|
|
|
goto error_out;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
g_pangu_rt->maat = create_maat_feather(profile, "MAAT", g_pangu_rt->thread_num, g_pangu_rt->local_logger);
|
|
|
|
|
if (!g_pangu_rt->maat)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
|
|
|
|
goto error_out;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
const char * table_name[__SCAN_TABLE_MAX];
|
|
|
|
|
table_name[PXY_CTRL_IP] = "PXY_CTRL_IP";
|
|
|
|
|
table_name[PXY_CTRL_HTTP_URL] = "PXY_CTRL_HTTP_URL";
|
|
|
|
|
table_name[PXY_CTRL_HTTP_REQ_HDR] = "PXY_CTRL_HTTP_REQ_HDR";
|
|
|
|
|
table_name[PXY_CTRL_HTTP_REQ_BODY] = "PXY_CTRL_HTTP_REQ_BODY";
|
|
|
|
|
table_name[PXY_CTRL_HTTP_RES_HDR] = "PXY_CTRL_HTTP_RES_HDR";
|
|
|
|
|
table_name[PXY_CTRL_HTTP_RES_BODY] = "PXY_CTRL_HTTP_RES_BODY";
|
|
|
|
|
for (int i = 0; i < __SCAN_TABLE_MAX; i++)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
g_pangu_rt->scan_table_id[i] = Maat_table_register(g_pangu_rt->maat, table_name[i]);
|
|
|
|
|
if (g_pangu_rt->scan_table_id[i] < 0)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-14 16:33:36 +08:00
|
|
|
TFE_LOG_ERROR(NULL, "Pangu HTTP Maat table %s register failed.", table_name[i]);
|
2018-09-12 16:04:04 +08:00
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
|
2018-09-15 20:55:31 +08:00
|
|
|
char page_path[256];
|
2018-09-18 14:15:23 +08:00
|
|
|
memset(page_path, 0, sizeof(page_path));
|
2018-09-23 20:02:07 +08:00
|
|
|
MESA_load_profile_string_def(profile, "TEMPLATE", "PAGE_403", page_path, sizeof(page_path),
|
|
|
|
|
"./pangu_conf/template/HTTP403.html");
|
|
|
|
|
g_pangu_rt->tpl_403 = ctemplate::Template::GetTemplate(page_path, ctemplate::DO_NOT_STRIP);
|
2018-09-18 14:15:23 +08:00
|
|
|
memset(page_path, 0, sizeof(page_path));
|
2018-09-23 20:02:07 +08:00
|
|
|
MESA_load_profile_string_def(profile, "TEMPLATE", "PAGE_404", page_path, sizeof(page_path),
|
|
|
|
|
"./pangu_conf/template/HTTP404.html");
|
|
|
|
|
g_pangu_rt->tpl_404 = ctemplate::Template::GetTemplate(page_path, ctemplate::DO_NOT_STRIP);
|
2018-09-18 14:15:23 +08:00
|
|
|
memset(page_path, 0, sizeof(page_path));
|
2018-09-23 20:02:07 +08:00
|
|
|
MESA_load_profile_string_def(profile, "TEMPLATE", "PAGE_451", page_path, sizeof(page_path),
|
|
|
|
|
"./pangu_conf/template/HTTP451.html");
|
|
|
|
|
g_pangu_rt->tpl_451 = ctemplate::Template::GetTemplate(page_path, ctemplate::DO_NOT_STRIP);
|
|
|
|
|
|
2018-09-14 16:33:36 +08:00
|
|
|
TFE_LOG_INFO(NULL, "Pangu HTTP init success.");
|
2018-09-18 12:01:56 +08:00
|
|
|
return 0;
|
2018-09-23 20:02:07 +08:00
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
error_out:
|
2018-09-14 16:33:36 +08:00
|
|
|
TFE_LOG_ERROR(NULL, "Pangu HTTP init failed.");
|
2018-09-18 12:01:56 +08:00
|
|
|
return -1;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
|
|
|
|
static void _wrap_std_field_write(struct tfe_http_half * half, enum tfe_http_std_field field_id, const char * value)
|
|
|
|
|
{
|
|
|
|
|
struct http_field_name tmp_name;
|
2018-09-23 20:02:07 +08:00
|
|
|
tmp_name.field_id = field_id;
|
|
|
|
|
tmp_name.field_name = NULL;
|
2018-09-14 16:33:36 +08:00
|
|
|
tfe_http_field_write(half, &tmp_name, value);
|
2018-09-12 16:04:04 +08:00
|
|
|
return;
|
|
|
|
|
}
|
2018-09-14 16:33:36 +08:00
|
|
|
#if 0
|
2018-09-12 16:04:04 +08:00
|
|
|
static void _wrap_non_std_field_write(struct tfe_http_half * half, const char* field_name, const char * value)
|
|
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
struct http_field_name tmp_name;
|
|
|
|
|
tmp_name.field_id=TFE_HTTP_UNKNOWN_FIELD;
|
|
|
|
|
//todo remove force convert after tfe_http.h improved.
|
|
|
|
|
tmp_name.field_name=(char*)field_name;
|
|
|
|
|
tfe_http_field_write(half, &tmp_name, value);
|
|
|
|
|
return;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-14 16:33:36 +08:00
|
|
|
#endif
|
2018-09-13 19:28:13 +08:00
|
|
|
enum replace_zone
|
|
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
kZoneRequestUri = 0,
|
2018-09-13 19:28:13 +08:00
|
|
|
kZoneRequestHeaders,
|
|
|
|
|
kZoneRequestBody,
|
|
|
|
|
kZoneResponseHeader,
|
|
|
|
|
kZoneResponseBody,
|
|
|
|
|
kZoneMax
|
|
|
|
|
};
|
|
|
|
|
struct replace_rule
|
|
|
|
|
{
|
|
|
|
|
enum replace_zone zone;
|
2018-09-23 20:02:07 +08:00
|
|
|
char * find;
|
|
|
|
|
char * replace_with;
|
2018-09-13 19:28:13 +08:00
|
|
|
};
|
|
|
|
|
struct replace_ctx
|
|
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
struct replace_rule * rule;
|
2018-09-13 19:28:13 +08:00
|
|
|
size_t n_rule;
|
|
|
|
|
struct tfe_http_half * replacing;
|
2018-09-23 20:02:07 +08:00
|
|
|
struct evbuffer * http_body;
|
2018-09-13 19:28:13 +08:00
|
|
|
size_t body_size;
|
|
|
|
|
};
|
2018-09-23 20:02:07 +08:00
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
struct pangu_http_ctx
|
|
|
|
|
{
|
|
|
|
|
enum pangu_action action;
|
2018-09-23 20:02:07 +08:00
|
|
|
char * action_para;
|
2018-09-12 16:04:04 +08:00
|
|
|
scan_status_t mid;
|
|
|
|
|
stream_para_t sp;
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
struct Maat_rule_t * enforce_rules;
|
2018-09-15 17:52:06 +08:00
|
|
|
size_t n_enforce;
|
2018-09-23 20:02:07 +08:00
|
|
|
char * enforce_para;
|
|
|
|
|
|
|
|
|
|
struct replace_ctx * rep_ctx;
|
2018-09-12 16:04:04 +08:00
|
|
|
int thread_id;
|
|
|
|
|
};
|
2018-09-13 19:28:13 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
static struct pangu_http_ctx * pangu_http_ctx_new(unsigned int thread_id)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
struct pangu_http_ctx * ctx = ALLOC(struct pangu_http_ctx, 1);
|
|
|
|
|
ctx->mid = NULL;
|
|
|
|
|
ctx->thread_id = (int) thread_id;
|
2018-09-12 16:04:04 +08:00
|
|
|
return ctx;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
static void pangu_http_ctx_free(struct pangu_http_ctx * ctx)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
if (ctx->rep_ctx != NULL)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
for (size_t i = 0; i < ctx->rep_ctx->n_rule; i++)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
|
|
|
|
FREE(&(ctx->rep_ctx->rule[i].find));
|
|
|
|
|
FREE(&(ctx->rep_ctx->rule[i].replace_with));
|
|
|
|
|
}
|
|
|
|
|
evbuffer_free(ctx->rep_ctx->http_body);
|
2018-09-23 20:02:07 +08:00
|
|
|
ctx->rep_ctx->http_body = NULL;
|
2018-09-13 19:28:13 +08:00
|
|
|
//todo destroy http_half;
|
2018-09-23 20:02:07 +08:00
|
|
|
assert(ctx->rep_ctx->replacing == NULL);
|
2018-09-15 17:52:06 +08:00
|
|
|
FREE(&ctx->rep_ctx);
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-15 17:52:06 +08:00
|
|
|
FREE(&ctx->enforce_rules);
|
|
|
|
|
FREE(&ctx->enforce_para);
|
2018-09-12 16:04:04 +08:00
|
|
|
Maat_clean_status(&(ctx->mid));
|
2018-09-23 20:02:07 +08:00
|
|
|
assert(ctx->sp == NULL);
|
|
|
|
|
ctx->mid = NULL;
|
2018-09-15 17:52:06 +08:00
|
|
|
FREE(&ctx);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
inline void addr_tfe2sapp(const struct tfe_stream_addr * tfe_addr, struct ipaddr * sapp_addr)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
sapp_addr->addrtype = tfe_addr->addrtype;
|
|
|
|
|
sapp_addr->paddr = (char *) tfe_addr->paddr;
|
2018-09-12 16:04:04 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 17:52:06 +08:00
|
|
|
//enforce_rules[0] contains execute action.
|
2018-09-23 20:02:07 +08:00
|
|
|
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)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
size_t n_monit = 0, exist_enforce_num = 0, i = 0;
|
|
|
|
|
const struct Maat_rule_t * prior_rule = hit_rules;
|
2018-09-15 17:52:06 +08:00
|
|
|
struct Maat_rule_t monit_rule[n_hit];
|
2018-09-23 20:02:07 +08:00
|
|
|
enum pangu_action prior_action = PG_ACTION_NONE;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n_hit; i++)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
if ((enum pangu_action) hit_rules[i].action == PG_ACTION_MONIT)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
memcpy(monit_rule + n_monit, hit_rules + i, sizeof(struct Maat_rule_t));
|
2018-09-15 17:52:06 +08:00
|
|
|
n_monit++;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if ((enum pangu_action) hit_rules[i].action > prior_action)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
prior_rule = hit_rules + i;
|
|
|
|
|
prior_action = (enum pangu_action) hit_rules[i].action;
|
2018-09-15 17:52:06 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
else if ((enum pangu_action) hit_rules[i].action == prior_action)
|
2018-09-15 17:52:06 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
if (hit_rules[i].config_id < prior_rule->config_id)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
prior_rule = hit_rules + i;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
if (prior_action == PG_ACTION_WHITELIST)
|
2018-09-15 17:52:06 +08:00
|
|
|
{
|
|
|
|
|
return PG_ACTION_WHITELIST;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
exist_enforce_num = *n_enforce;
|
|
|
|
|
if (prior_action == PG_ACTION_MONIT)
|
2018-09-15 17:52:06 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
*n_enforce += n_monit;
|
2018-09-15 17:52:06 +08:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
*n_enforce += n_monit + 1;
|
2018-09-15 17:52:06 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
*enforce_rules = (struct Maat_rule_t *) realloc(*enforce_rules, sizeof(struct Maat_rule_t) * (*n_enforce));
|
|
|
|
|
|
|
|
|
|
if (prior_action == PG_ACTION_MONIT)
|
|
|
|
|
{
|
|
|
|
|
memcpy(*enforce_rules + exist_enforce_num, monit_rule, n_monit * sizeof(struct Maat_rule_t));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
memcpy(*enforce_rules + exist_enforce_num, prior_rule, sizeof(struct Maat_rule_t));
|
|
|
|
|
memcpy(*enforce_rules + exist_enforce_num + 1, monit_rule, n_monit * sizeof(struct Maat_rule_t));
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-15 17:52:06 +08:00
|
|
|
return prior_action;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-14 16:33:36 +08:00
|
|
|
//https://github.com/AndiDittrich/HttpErrorPages
|
2018-09-25 11:15:00 +08:00
|
|
|
static void html_generate(int cfg_id, int status_code, char ** page_buff, size_t * page_size)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-15 20:55:31 +08:00
|
|
|
ctemplate::TemplateDictionary dict("pg_page_dict");
|
|
|
|
|
dict.SetIntValue("cfg_id", cfg_id);
|
|
|
|
|
std::string output;
|
2018-09-23 20:02:07 +08:00
|
|
|
ctemplate::Template * tpl = NULL;
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
switch (status_code)
|
2018-09-15 20:55:31 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
case 403: tpl = g_pangu_rt->tpl_403;
|
2018-09-15 20:55:31 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
case 404: tpl = g_pangu_rt->tpl_404;
|
2018-09-15 20:55:31 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
case 451: tpl = g_pangu_rt->tpl_451;
|
2018-09-15 20:55:31 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
default: return;
|
2018-09-15 20:55:31 +08:00
|
|
|
}
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-15 20:55:31 +08:00
|
|
|
tpl->Expand(&output, &dict);
|
|
|
|
|
//todo: do I need to delete dict?
|
2018-09-23 20:02:07 +08:00
|
|
|
*page_size = output.length();
|
|
|
|
|
*page_buff = ALLOC(char, *page_size);
|
|
|
|
|
memcpy(*page_buff, output.c_str(), *page_size);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
static void html_free(char ** page_buff)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-15 20:55:31 +08:00
|
|
|
FREE(page_buff);
|
2018-09-12 16:04:04 +08:00
|
|
|
return;
|
|
|
|
|
}
|
2018-09-18 12:01:56 +08:00
|
|
|
static int is_http_request(enum tfe_http_event events)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
if ((events & EV_HTTP_REQ_HDR) | (events & EV_HTTP_REQ_BODY_BEGIN) | (events & EV_HTTP_REQ_BODY_END)
|
|
|
|
|
| (events & EV_HTTP_REQ_BODY_CONT))
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-13 19:28:13 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
enum replace_zone zone_name_to_id(const char * name)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
const char * std_name[] = {"http_req_uri",
|
|
|
|
|
"http_req_header",
|
|
|
|
|
"http_req_body",
|
|
|
|
|
"http_resp_header",
|
|
|
|
|
"http_resp_body",
|
|
|
|
|
"http_resp_body"};
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
for (i = 0; i < sizeof(std_name) / sizeof(const char *); i++)
|
|
|
|
|
{
|
|
|
|
|
if (0 == strcasecmp(name, std_name[i]))
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
return (enum replace_zone) i;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
static char * strchr_esc(char * s, const char delim)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
char * token;
|
|
|
|
|
if (s == NULL)
|
2018-09-12 16:04:04 +08:00
|
|
|
return NULL;
|
2018-09-23 20:02:07 +08:00
|
|
|
for (token = s; *token != '\0'; token++)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
if (*token == '\\')
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
|
|
|
|
token++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (*token == delim)
|
2018-09-12 16:04:04 +08:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (*token == '\0')
|
2018-09-23 20:02:07 +08:00
|
|
|
{
|
2018-09-12 16:04:04 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return token;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
static char * strtok_r_esc(char * s, const char delim, char ** save_ptr)
|
|
|
|
|
{
|
|
|
|
|
char * token;
|
|
|
|
|
|
|
|
|
|
if (s == NULL) s = *save_ptr;
|
|
|
|
|
|
|
|
|
|
/* Scan leading delimiters. */
|
|
|
|
|
token = strchr_esc(s, delim);
|
|
|
|
|
if (token == NULL)
|
|
|
|
|
{
|
|
|
|
|
*save_ptr = token;
|
2018-09-12 16:04:04 +08:00
|
|
|
return s;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
/* Find the end of the token. */
|
|
|
|
|
*token = '\0';
|
2018-09-12 16:04:04 +08:00
|
|
|
token++;
|
2018-09-23 20:02:07 +08:00
|
|
|
*save_ptr = token;
|
2018-09-12 16:04:04 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
return s;
|
|
|
|
|
}
|
2018-09-12 16:04:04 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
size_t format_replace_rule(const char * exec_para, struct replace_rule * replace, size_t n_replace)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
|
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
char * tmp = ALLOC(char, strlen(exec_para) + 1);
|
|
|
|
|
char * token = NULL, * sub_token = NULL, * saveptr = NULL, * saveptr2 = NULL;
|
|
|
|
|
size_t idx = 0;
|
|
|
|
|
const char * str_zone = "replace=";
|
|
|
|
|
const char * str_subs = "substitute=";
|
|
|
|
|
memcpy(tmp, exec_para, strlen(exec_para));
|
|
|
|
|
for (token = tmp;; token = NULL)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
sub_token = strtok_r(token, ";", &saveptr);
|
2018-09-12 16:04:04 +08:00
|
|
|
if (sub_token == NULL)
|
|
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
if (0 == strncasecmp(sub_token, str_zone, strlen(str_zone)))
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
replace[idx].zone = zone_name_to_id(sub_token + strlen(str_zone));
|
|
|
|
|
if (replace[idx].zone == kZoneMax)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (0 == strncasecmp(sub_token, str_subs, strlen(str_subs)))
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
sub_token += strlen(str_subs);
|
|
|
|
|
replace[idx].find = tfe_strdup(strtok_r_esc(sub_token, '/', &saveptr2));
|
|
|
|
|
replace[idx].replace_with = tfe_strdup(strtok_r_esc(NULL, '/', &saveptr2));
|
2018-09-12 16:04:04 +08:00
|
|
|
idx++;
|
2018-09-23 20:02:07 +08:00
|
|
|
if (idx == n_replace)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free(tmp);
|
2018-09-23 20:02:07 +08:00
|
|
|
tmp = NULL;
|
2018-09-12 16:04:04 +08:00
|
|
|
return idx;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
size_t select_replace_rule(enum replace_zone zone, const struct replace_rule * replace, size_t n_replace,
|
|
|
|
|
const struct replace_rule ** selected, size_t n_selected)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
size_t i = 0, j = 0;
|
|
|
|
|
for (i = 0; i < n_replace && j < n_selected; i++)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
if (replace[i].zone == zone)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
selected[j] = replace + i;
|
2018-09-13 19:28:13 +08:00
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return j;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
static struct evbuffer * replace_string(const char * in, const struct replace_rule * zone)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
|
|
|
|
//Reference to https://www.lemoda.net/c/unix-regex/
|
|
|
|
|
// Regular Expression test: https://regex101.com/
|
|
|
|
|
regex_t reg;
|
2018-09-23 20:02:07 +08:00
|
|
|
int status = 0, is_replaced = 0;
|
|
|
|
|
struct evbuffer * out = NULL;
|
|
|
|
|
size_t in_sz = strlen(in);
|
|
|
|
|
|
|
|
|
|
size_t replace_len = strlen(zone->replace_with);
|
2018-09-13 19:28:13 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
status = regcomp(®, zone->find, REG_EXTENDED | REG_NEWLINE);
|
|
|
|
|
if (status != 0)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
|
|
|
|
char error_message[TFE_STRING_MAX];
|
2018-09-23 20:02:07 +08:00
|
|
|
regerror(status, ®, error_message, sizeof(error_message));
|
|
|
|
|
TFE_LOG_ERROR(g_pangu_rt->local_logger, "Regex error compiling '%s': %s\n",
|
|
|
|
|
zone->find, error_message);
|
2018-09-14 16:33:36 +08:00
|
|
|
regfree(®);
|
|
|
|
|
return NULL;
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
|
2018-09-13 19:28:13 +08:00
|
|
|
/* "p" is a pointer into the string which points to the end of the previous match. */
|
2018-09-23 20:02:07 +08:00
|
|
|
const char * p = in;
|
2018-09-13 19:28:13 +08:00
|
|
|
/* "pre_sub_expr_end" is a pointer into the string which points to the end of the previous sub expression match. */
|
2018-09-23 20:02:07 +08:00
|
|
|
const char * pre_sub_expr_end = NULL;
|
|
|
|
|
|
2018-09-13 19:28:13 +08:00
|
|
|
/* "N_matches" is the maximum number of matches allowed. */
|
|
|
|
|
const int n_matches = MAX_EDIT_MATCHES;
|
|
|
|
|
/* "M" contains the matches found. */
|
|
|
|
|
regmatch_t m[n_matches];
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
int nomatch = regexec(®, p, n_matches, m, 0);
|
2018-09-13 19:28:13 +08:00
|
|
|
if (nomatch)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (is_replaced == 0)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
out = evbuffer_new();
|
|
|
|
|
is_replaced = 1;
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
assert(m[0].rm_so != -1);
|
|
|
|
|
pre_sub_expr_end = p;
|
|
|
|
|
if (m[1].rm_so == -1)//no sub expr, replace the entire expr.
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
evbuffer_add(out, pre_sub_expr_end, m[0].rm_so - (pre_sub_expr_end - p));
|
2018-09-13 19:28:13 +08:00
|
|
|
evbuffer_add(out, zone->replace_with, replace_len);
|
2018-09-23 20:02:07 +08:00
|
|
|
pre_sub_expr_end = p + m[0].rm_eo;
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
else //have sub expr, replace the sub expr.
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
for (i = 1, pre_sub_expr_end = p; i < n_matches; i++)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
if (m[i].rm_so == -1)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
|
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
}
|
|
|
|
|
evbuffer_add(out, pre_sub_expr_end, m[i].rm_so - (pre_sub_expr_end - p));
|
2018-09-13 19:28:13 +08:00
|
|
|
evbuffer_add(out, zone->replace_with, replace_len);
|
|
|
|
|
pre_sub_expr_end = p + m[i].rm_eo;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p += m[0].rm_eo;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (is_replaced)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
evbuffer_add(out, pre_sub_expr_end, in_sz - (pre_sub_expr_end - p));
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
|
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
regfree(®);
|
2018-09-13 19:28:13 +08:00
|
|
|
return out;
|
2018-09-23 20:02:07 +08:00
|
|
|
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
struct evbuffer * execute_replace_rule(const char * in, size_t in_sz,
|
|
|
|
|
enum replace_zone zone, const struct replace_rule * rules, size_t n_rule)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
const struct replace_rule * todo[MAX_EDIT_ZONE_NUM];
|
|
|
|
|
size_t n_todo = 0, i = 0;
|
|
|
|
|
struct evbuffer * out = NULL;
|
|
|
|
|
const char * interator = NULL;
|
|
|
|
|
struct evbuffer * new_out = NULL, * pre_out = NULL;
|
|
|
|
|
if (in == 0)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
//Do not process buffer that contains '\0'.
|
2018-09-23 20:02:07 +08:00
|
|
|
if (0 != memchr(in, '\0', in_sz))
|
|
|
|
|
{
|
2018-09-13 19:28:13 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
n_todo = select_replace_rule(zone, rules, n_rule, todo, MAX_EDIT_ZONE_NUM);
|
|
|
|
|
interator = in;
|
|
|
|
|
for (i = 0; i < n_todo; i++)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
new_out = replace_string(interator, todo[i]);
|
|
|
|
|
if (new_out != NULL)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
pre_out = out;
|
|
|
|
|
out = new_out;
|
|
|
|
|
interator = (char *) evbuffer_pullup(out, -1);
|
2018-09-13 19:28:13 +08:00
|
|
|
evbuffer_free(pre_out);
|
2018-09-23 20:02:07 +08:00
|
|
|
pre_out = NULL;
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
void http_replace(const struct tfe_stream * stream, const struct tfe_http_session * session,
|
2018-09-23 20:02:07 +08:00
|
|
|
enum tfe_http_event events, const unsigned char * body_frag, size_t frag_size, struct pangu_http_ctx * ctx)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
void * interator = NULL;
|
2018-09-13 19:28:13 +08:00
|
|
|
struct http_field_name tmp_name;
|
2018-09-23 20:02:07 +08:00
|
|
|
const char * buff_in = NULL;
|
|
|
|
|
struct evbuffer * rewrite_url = NULL, * rewrite_buff = NULL;
|
|
|
|
|
struct replace_ctx * rep_ctx = NULL;
|
|
|
|
|
struct tfe_http_session * to_write_sess = NULL;
|
|
|
|
|
|
|
|
|
|
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);
|
2018-09-14 16:33:36 +08:00
|
|
|
tfe_http_session_detach(session);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (ctx->rep_ctx == NULL)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
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);
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (events & EV_HTTP_REQ_HDR)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
rewrite_url = execute_replace_rule(session->req->req_spec.uri, strlen(session->req->req_spec.uri),
|
2018-09-13 19:28:13 +08:00
|
|
|
kZoneRequestUri, rep_ctx->rule, rep_ctx->n_rule);
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if ((events & EV_HTTP_REQ_HDR) | (events & EV_HTTP_RESP_HDR))
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
if (events & EV_HTTP_REQ_HDR)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
rep_ctx->replacing = tfe_http_session_request_create(to_write_sess, session->req->req_spec.method,
|
|
|
|
|
rewrite_url != NULL ? (char *) evbuffer_pullup(rewrite_url, -1) : session->req->req_spec.uri);
|
2018-09-13 19:28:13 +08:00
|
|
|
evbuffer_free(rewrite_url);
|
2018-09-23 20:02:07 +08:00
|
|
|
rewrite_url = NULL;
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
rep_ctx->replacing = tfe_http_session_response_create(to_write_sess, session->resp->resp_spec.resp_code);
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
while (1)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
buff_in = tfe_http_field_iterate(session->req, &interator, &tmp_name);
|
|
|
|
|
if (tmp_name.field_id == TFE_HTTP_CONT_LENGTH)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (buff_in != NULL)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
rewrite_buff = execute_replace_rule(buff_in, strlen(buff_in),
|
|
|
|
|
events & EV_HTTP_REQ_HDR ? kZoneRequestHeaders : kZoneResponseHeader, rep_ctx->rule,
|
|
|
|
|
rep_ctx->n_rule);
|
|
|
|
|
tfe_http_field_write(rep_ctx->replacing, &tmp_name,
|
|
|
|
|
rewrite_buff != NULL ? (char *) evbuffer_pullup(rewrite_buff, -1) : buff_in);
|
2018-09-13 19:28:13 +08:00
|
|
|
evbuffer_free(rewrite_buff);
|
2018-09-23 20:02:07 +08:00
|
|
|
rewrite_buff = NULL;
|
2018-09-13 19:28:13 +08:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if ((events & EV_HTTP_REQ_BODY_BEGIN) | (events & EV_HTTP_RESP_BODY_BEGIN))
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
assert(rep_ctx->http_body == NULL);
|
|
|
|
|
assert(rep_ctx->body_size = 0);
|
|
|
|
|
rep_ctx->http_body = evbuffer_new();
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (body_frag != NULL)
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
|
|
|
|
evbuffer_add(rep_ctx->http_body, body_frag, frag_size);
|
|
|
|
|
rep_ctx->body_size++;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if ((events & EV_HTTP_REQ_BODY_END) | (events & EV_HTTP_RESP_BODY_END))
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
assert(rep_ctx->body_size == evbuffer_get_length(rep_ctx->http_body));
|
|
|
|
|
buff_in = (char *) evbuffer_pullup(rep_ctx->http_body, -1);
|
|
|
|
|
rewrite_buff = execute_replace_rule(buff_in, rep_ctx->body_size,
|
|
|
|
|
events & EV_HTTP_REQ_HDR ? kZoneRequestHeaders : kZoneResponseHeader, rep_ctx->rule, rep_ctx->n_rule);
|
2018-09-13 19:28:13 +08:00
|
|
|
char cont_len_str[TFE_SYMBOL_MAX];
|
2018-09-14 16:33:36 +08:00
|
|
|
snprintf(cont_len_str, sizeof(cont_len_str), "%lu", evbuffer_get_length(rewrite_buff));
|
2018-09-13 19:28:13 +08:00
|
|
|
_wrap_std_field_write(rep_ctx->replacing, TFE_HTTP_CONT_LENGTH, cont_len_str);
|
|
|
|
|
tfe_http_half_append_body(rep_ctx->replacing,
|
2018-09-23 20:02:07 +08:00
|
|
|
(char *) evbuffer_pullup(rewrite_buff, -1), evbuffer_get_length(rewrite_buff), 0);
|
2018-09-13 19:28:13 +08:00
|
|
|
evbuffer_free(rewrite_buff);
|
2018-09-23 20:02:07 +08:00
|
|
|
rewrite_buff = NULL;
|
|
|
|
|
if (is_http_request(events))
|
2018-09-13 19:28:13 +08:00
|
|
|
{
|
2018-09-14 16:33:36 +08:00
|
|
|
tfe_http_session_request_set(to_write_sess, rep_ctx->replacing);
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-09-14 16:33:36 +08:00
|
|
|
tfe_http_session_response_set(to_write_sess, rep_ctx->replacing);
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
rep_ctx->replacing = NULL;//http half's ownership has been transfered to session.
|
|
|
|
|
|
2018-09-13 19:28:13 +08:00
|
|
|
evbuffer_free(rep_ctx->http_body);
|
2018-09-23 20:02:07 +08:00
|
|
|
rep_ctx->http_body = NULL;
|
|
|
|
|
rep_ctx->body_size = 0;
|
2018-09-13 19:28:13 +08:00
|
|
|
}
|
2018-09-14 16:33:36 +08:00
|
|
|
return;
|
2018-09-23 20:02:07 +08:00
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
static void http_reject(const struct tfe_http_session * session, enum tfe_http_event events,
|
|
|
|
|
struct pangu_http_ctx * ctx)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
int resp_code = 0, ret = 0;
|
|
|
|
|
struct tfe_http_half * response = NULL;
|
|
|
|
|
char * page_buff = NULL;
|
|
|
|
|
size_t page_size = 0;
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-13 19:28:13 +08:00
|
|
|
char cont_len_str[TFE_STRING_MAX];
|
2018-09-23 20:02:07 +08:00
|
|
|
struct tfe_http_session * to_write_sess = NULL;
|
2018-09-12 16:04:04 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
ret = sscanf(ctx->enforce_para, "code=%d;", &resp_code);
|
|
|
|
|
if (ret != 1)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
TFE_LOG_ERROR(g_pangu_rt->local_logger, "Invalid reject rule %d paramter %s",
|
2018-09-25 11:15:00 +08:00
|
|
|
ctx->enforce_rules[0].config_id, ctx->enforce_para); goto error_out;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
to_write_sess = tfe_http_session_allow_write(session);
|
|
|
|
|
response = tfe_http_session_response_create(to_write_sess, resp_code);
|
|
|
|
|
|
2018-09-15 20:55:31 +08:00
|
|
|
html_generate(ctx->enforce_rules[0].config_id, resp_code, &page_buff, &page_size);
|
2018-09-12 16:04:04 +08:00
|
|
|
_wrap_std_field_write(response, TFE_HTTP_CONT_TYPE, "text/html; charset=utf-8");
|
2018-09-23 20:02:07 +08:00
|
|
|
snprintf(cont_len_str, sizeof(cont_len_str), "%lu", page_size);
|
2018-09-13 19:28:13 +08:00
|
|
|
_wrap_std_field_write(response, TFE_HTTP_CONT_LENGTH, cont_len_str);
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-13 19:28:13 +08:00
|
|
|
tfe_http_half_append_body(response, page_buff, page_size, 0);
|
2018-09-14 16:33:36 +08:00
|
|
|
tfe_http_session_response_set(to_write_sess, response);
|
2018-09-25 11:15:00 +08:00
|
|
|
tfe_http_session_detach(session);
|
|
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
error_out:
|
2018-09-14 16:33:36 +08:00
|
|
|
html_free(&page_buff);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-25 11:15:00 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
static void http_redirect(const struct tfe_http_session * session, enum tfe_http_event events,
|
|
|
|
|
struct pangu_http_ctx * ctx)
|
|
|
|
|
{
|
|
|
|
|
int resp_code = 0, ret = 0;
|
|
|
|
|
char * url = NULL;
|
2018-09-25 10:17:50 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
struct tfe_http_half * response = NULL;
|
|
|
|
|
struct tfe_http_session * to_write = NULL;
|
2018-09-25 10:17:50 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
url = ALLOC(char, ctx->enforce_rules[0].serv_def_len);
|
2018-09-25 10:17:50 +08:00
|
|
|
ret = sscanf(ctx->enforce_para, "code=%d;url=%[^;]", &resp_code, url);
|
|
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
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);
|
2018-09-12 16:04:04 +08:00
|
|
|
goto error_out;
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
to_write = tfe_http_session_allow_write(session);
|
2018-09-25 10:17:50 +08:00
|
|
|
if (to_write == NULL)
|
|
|
|
|
{
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
response = tfe_http_session_response_create(to_write, resp_code);
|
2018-09-12 16:04:04 +08:00
|
|
|
_wrap_std_field_write(response, TFE_HTTP_LOCATION, url);
|
2018-09-25 10:17:50 +08:00
|
|
|
|
2018-09-13 19:28:13 +08:00
|
|
|
tfe_http_session_response_set(to_write, response);
|
2018-09-25 10:17:50 +08:00
|
|
|
tfe_http_session_detach(session);
|
2018-09-23 20:02:07 +08:00
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
error_out:
|
|
|
|
|
free(url);
|
2018-09-13 19:28:13 +08:00
|
|
|
return;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
|
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
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)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
void * interator = NULL;
|
|
|
|
|
const char * field_val = NULL;
|
2018-09-12 16:04:04 +08:00
|
|
|
struct http_field_name field_name;
|
2018-09-14 16:33:36 +08:00
|
|
|
struct Maat_rule_t result[MAX_SCAN_RESULT];
|
2018-09-23 20:02:07 +08:00
|
|
|
char buff[TFE_STRING_MAX], * p = NULL;
|
|
|
|
|
int scan_ret = 0, table_id = 0, read_rule_ret = 0;
|
|
|
|
|
size_t hit_cnt = 0, i = 0;
|
|
|
|
|
|
|
|
|
|
if (events & EV_HTTP_REQ_HDR)
|
|
|
|
|
{
|
|
|
|
|
const char * str_url = session->req->req_spec.url;
|
|
|
|
|
int str_url_length = (int) (strlen(session->req->req_spec.url));
|
|
|
|
|
|
|
|
|
|
scan_ret = Maat_full_scan_string(g_pangu_rt->maat, g_pangu_rt->scan_table_id[PXY_CTRL_HTTP_URL],
|
|
|
|
|
CHARSET_UTF8, str_url, str_url_length, result, NULL, MAX_SCAN_RESULT, &(ctx->mid), ctx->thread_id);
|
|
|
|
|
|
|
|
|
|
if (scan_ret > 0)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
hit_cnt += scan_ret;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
|
|
|
|
|
if ((events & EV_HTTP_REQ_HDR) || (events & EV_HTTP_RESP_HDR))
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
table_id = events & EV_HTTP_REQ_HDR ? g_pangu_rt->scan_table_id[PXY_CTRL_HTTP_REQ_HDR] : g_pangu_rt
|
|
|
|
|
->scan_table_id[PXY_CTRL_HTTP_RES_HDR];
|
|
|
|
|
while (hit_cnt < MAX_SCAN_RESULT)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
field_val = tfe_http_field_iterate(session->req, &interator, &field_name);
|
|
|
|
|
if (field_val == NULL)
|
2018-09-14 16:33:36 +08:00
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2018-09-18 18:48:21 +08:00
|
|
|
|
|
|
|
|
const char * str_field_name = http_field_to_string(&field_name);
|
2018-09-23 20:02:07 +08:00
|
|
|
scan_ret = Maat_set_scan_status(g_pangu_rt->maat, &(ctx->mid), MAAT_SET_SCAN_DISTRICT,
|
|
|
|
|
str_field_name, strlen(str_field_name));
|
|
|
|
|
|
|
|
|
|
assert(scan_ret == 0);
|
|
|
|
|
scan_ret = Maat_full_scan_string(g_pangu_rt->maat, table_id,
|
|
|
|
|
CHARSET_UTF8, field_val, strlen(field_val),
|
|
|
|
|
result + hit_cnt, NULL, MAX_SCAN_RESULT - hit_cnt, &(ctx->mid), ctx->thread_id);
|
|
|
|
|
if (scan_ret > 0)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
hit_cnt += scan_ret;
|
2018-09-14 16:33:36 +08:00
|
|
|
}
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if ((events & EV_HTTP_REQ_BODY_BEGIN) | (events & EV_HTTP_RESP_BODY_BEGIN))
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
assert(ctx->sp == NULL);
|
|
|
|
|
table_id = events & EV_HTTP_REQ_BODY_BEGIN ? g_pangu_rt->scan_table_id[PXY_CTRL_HTTP_REQ_BODY] : g_pangu_rt
|
|
|
|
|
->scan_table_id[PXY_CTRL_HTTP_RES_BODY];
|
|
|
|
|
ctx->sp = Maat_stream_scan_string_start(g_pangu_rt->maat, table_id, ctx->thread_id);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (body_frag != NULL)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
scan_ret = Maat_stream_scan_string(&(ctx->sp), CHARSET_UTF8, (const char *) body_frag, (int) frag_size,
|
|
|
|
|
result + hit_cnt, NULL, MAX_SCAN_RESULT - hit_cnt, &(ctx->mid));
|
|
|
|
|
if (scan_ret > 0)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
hit_cnt += scan_ret;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if ((events & EV_HTTP_REQ_BODY_END) | (events & EV_HTTP_RESP_BODY_END))
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-14 16:33:36 +08:00
|
|
|
Maat_stream_scan_string_end(&(ctx->sp));
|
2018-09-23 20:02:07 +08:00
|
|
|
ctx->sp = NULL;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-25 10:17:50 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
if (hit_cnt > 0)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
ctx->action = decide_ctrl_action(result, hit_cnt, &ctx->enforce_rules, &ctx->n_enforce);
|
2018-09-25 10:17:50 +08:00
|
|
|
size_t __serv_def_len = (size_t)ctx->enforce_rules[0].serv_def_len;
|
|
|
|
|
ctx->enforce_para = ALLOC(char, __serv_def_len);
|
|
|
|
|
|
|
|
|
|
if (__serv_def_len > MAX_SERVICE_DEFINE_LEN)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-25 10:17:50 +08:00
|
|
|
read_rule_ret = Maat_read_rule(g_pangu_rt->maat, &ctx->enforce_rules[0], MAAT_RULE_SERV_DEFINE,
|
|
|
|
|
ctx->enforce_para, ctx->enforce_rules[0].serv_def_len);
|
2018-09-23 20:02:07 +08:00
|
|
|
assert(read_rule_ret == ctx->enforce_rules[0].serv_def_len);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-25 10:17:50 +08:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy(ctx->enforce_para, ctx->enforce_rules[0].service_defined);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
if (hit_cnt > 1)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
p = buff;
|
|
|
|
|
for (i = 0; i < hit_cnt; i++)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
p += snprintf(p, sizeof(buff) - (p - buff), "%d:", result[i].config_id);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-25 10:17:50 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
*p = '\0';
|
|
|
|
|
TFE_LOG_INFO(g_pangu_rt->local_logger, "Multiple rules matched: url=%s num=%lu ids=%s execute=%d.",
|
|
|
|
|
session->req->req_spec.url, hit_cnt, buff, ctx->enforce_rules[0].config_id);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
2018-09-25 10:17:50 +08:00
|
|
|
|
2018-09-12 16:04:04 +08:00
|
|
|
return ctx->action;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-14 16:33:36 +08:00
|
|
|
void pangu_on_http_begin(const struct tfe_stream * stream,
|
2018-09-12 16:04:04 +08:00
|
|
|
const struct tfe_http_session * session, unsigned int thread_id, void ** pme)
|
|
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
struct pangu_http_ctx * ctx = *(struct pangu_http_ctx **) pme;
|
2018-09-12 16:04:04 +08:00
|
|
|
struct Maat_rule_t result[MAX_SCAN_RESULT];
|
|
|
|
|
struct ipaddr sapp_addr;
|
2018-09-23 20:02:07 +08:00
|
|
|
int hit_cnt = 0;
|
|
|
|
|
assert(ctx == NULL);
|
|
|
|
|
ctx = pangu_http_ctx_new(thread_id);
|
2018-09-14 16:33:36 +08:00
|
|
|
addr_tfe2sapp(stream->addr, &sapp_addr);
|
2018-09-23 20:02:07 +08:00
|
|
|
hit_cnt = Maat_scan_proto_addr(g_pangu_rt->maat, g_pangu_rt->scan_table_id[PXY_CTRL_IP], &sapp_addr, 0,
|
|
|
|
|
result, MAX_SCAN_RESULT, &(ctx->mid), (int) thread_id);
|
|
|
|
|
|
|
|
|
|
if (hit_cnt > 0)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
ctx->action = decide_ctrl_action(result, hit_cnt, &ctx->enforce_rules, &ctx->n_enforce);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
if (ctx->action == PG_ACTION_WHITELIST)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-14 16:33:36 +08:00
|
|
|
tfe_http_session_detach(session);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-18 18:48:21 +08:00
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
*pme = ctx;
|
2018-09-18 12:01:56 +08:00
|
|
|
return;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pangu_on_http_end(const struct tfe_stream * stream,
|
|
|
|
|
const struct tfe_http_session * session, unsigned int thread_id, void ** pme)
|
|
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
struct pangu_http_ctx * ctx = *(struct pangu_http_ctx **) pme;
|
|
|
|
|
struct pangu_log log_msg = {.stream=stream, .http=session, .result=ctx->enforce_rules, .result_num=ctx->n_enforce};
|
|
|
|
|
if (ctx->action != PG_ACTION_NONE)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-18 14:02:39 +08:00
|
|
|
pangu_send_log(g_pangu_rt->send_logger, &log_msg);
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
|
|
|
|
pangu_http_ctx_free(ctx);
|
2018-09-23 20:02:07 +08:00
|
|
|
*pme = NULL;
|
2018-09-12 16:04:04 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-23 20:02:07 +08:00
|
|
|
void pangu_on_http_data(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, void ** pme)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
struct pangu_http_ctx * ctx = *(struct pangu_http_ctx **) pme;
|
|
|
|
|
enum pangu_action hit_action = PG_ACTION_NONE;
|
2018-09-12 16:04:04 +08:00
|
|
|
|
|
|
|
|
Re_Enter:
|
2018-09-23 20:02:07 +08:00
|
|
|
switch (ctx->action)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
2018-09-23 20:02:07 +08:00
|
|
|
case PG_ACTION_NONE: hit_action = http_scan(session, events, body_frag, frag_size, ctx);
|
|
|
|
|
if (hit_action != PG_ACTION_NONE)
|
2018-09-12 16:04:04 +08:00
|
|
|
{
|
|
|
|
|
//ctx->action changed in http_scan.
|
|
|
|
|
goto Re_Enter;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
case PG_ACTION_MONIT:
|
2018-09-12 16:04:04 +08:00
|
|
|
//send log on close.
|
|
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
case PG_ACTION_REJECT: http_reject(session, events, ctx);
|
2018-09-12 16:04:04 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
case PG_ACTION_REDIRECT: http_redirect(session, events, ctx);
|
2018-09-25 10:17:50 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
case PG_ACTION_REPLACE: http_replace(stream, session, events, body_frag, frag_size, ctx);
|
2018-09-12 16:04:04 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
case PG_ACTION_WHITELIST: tfe_http_session_detach(session);
|
2018-09-12 16:04:04 +08:00
|
|
|
break;
|
2018-09-23 20:02:07 +08:00
|
|
|
default: assert(0);
|
2018-09-12 16:04:04 +08:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-13 19:28:13 +08:00
|
|
|
return;
|
2018-09-12 16:04:04 +08:00
|
|
|
}
|
2018-09-23 20:02:07 +08:00
|
|
|
struct tfe_plugin pangu_http_spec = {
|
|
|
|
|
.symbol=NULL,
|
|
|
|
|
.type = TFE_PLUGIN_TYPE_BUSINESS,
|
|
|
|
|
.on_init = pangu_http_init,
|
|
|
|
|
.on_deinit = NULL,
|
|
|
|
|
.on_open = NULL,
|
|
|
|
|
.on_data = NULL,
|
|
|
|
|
.on_close = NULL,
|
|
|
|
|
.on_session_begin=pangu_on_http_begin,
|
|
|
|
|
.on_session_data=pangu_on_http_data,
|
|
|
|
|
.on_session_end=pangu_on_http_end
|
|
|
|
|
};
|
2018-09-18 12:01:56 +08:00
|
|
|
TFE_PLUGIN_REGISTER(pangu_http, pangu_http_spec)
|
2018-09-09 15:21:26 +08:00
|
|
|
|