Add port field to Dst Host filter rules, and refactor for code reuse

Now the target IP address filters can use port specs too.
Refactor for code reuse, create filter_action struct used by rules,
sites, and ports.
Also, improve code and documentation.
pull/48/head
Soner Tari 3 years ago
parent dc34bc1ccf
commit c8f09d162a

@ -5,15 +5,17 @@
(Divert|Split|Pass|Block|Match)
([from (
user (username|$macro|*) [desc keyword]|
ip (clientaddr|$macro|*)|
user (username|$macro|*) [desc (keyword|$macro|*)]|
desc (keyword|$macro|*)|
ip (clientip|$macro|*)|
*)]
[to (
sni (servername[*]|$macro|*)|
cn (commonname[*]|$macro|*)|
host (host[*]|$macro|*)|
uri (uri[*]|$macro|*)|
ip (serveraddr|$macro|*)|
ip (serverip[*]|$macro|*) [port (serverport[*]|$macro|*)]|
port (serverport[*]|$macro|*)|
*)]
[log ([[!]connect] [[!]master] [[!]cert]
[[!]content] [[!]pcap] [[!]mirror] [$macro]|*|!*)]

@ -295,15 +295,17 @@ The syntax of filtering rules is as follows:
(Divert|Split|Pass|Block|Match)
([from (
user (username|$macro|*) [desc keyword]|
ip (clientaddr|$macro|*)|
user (username|$macro|*) [desc (keyword|$macro|*)]|
desc (keyword|$macro|*)|
ip (clientip|$macro|*)|
*)]
[to (
sni (servername[*]|$macro|*)|
cn (commonname[*]|$macro|*)|
host (host[*]|$macro|*)|
uri (uri[*]|$macro|*)|
ip (serveraddr|$macro|*)|
ip (serverip[*]|$macro|*) [port (serverport[*]|$macro|*)]|
port (serverport[*]|$macro|*)|
*)]
[log ([[!]connect] [[!]master] [[!]cert]
[[!]content] [[!]pcap] [[!]mirror] [$macro]|*|!*)]
@ -318,7 +320,7 @@ user or description keyword, or `*` for all.
- The `to` part defines destination filter based on server IP address, SNI or
Common Names of SSL connections, Host or URI fields in HTTP Request headers, or
`*` for all.
+ Dst Host type of rules use `ip` site field
+ Dst Host type of rules use `ip` and `port` site fields
+ SSL type of rules use `sni` and `cn` site fields
+ HTTP type of rules use `host` and `uri` site fields
- The proxyspec handling the connection defines the protocol filter for the

@ -217,6 +217,8 @@ opts_free_filter_rules(opts_t *opts)
while (rule) {
filter_rule_t *next = rule->next;
free(rule->site);
if (rule->port)
free(rule->port);
if (rule->ip)
free(rule->ip);
#ifndef WITHOUT_USERAUTH
@ -231,11 +233,23 @@ opts_free_filter_rules(opts_t *opts)
opts->filter_rules = NULL;
}
static void
opts_free_filter_port(filter_port_t *port)
{
while (port) {
filter_port_t *p = port->next;
free(port->port);
free(port);
port = p;
}
}
static filter_site_t *
opts_free_filter_site(filter_site_t *site)
{
filter_site_t *s = site->next;
free(site->site);
opts_free_filter_port(site->port);
free(site);
return s;
}
@ -879,64 +893,60 @@ clone_global_opts(global_t *global, const char *argv0, tmp_global_opts_t *tmp_gl
filter_rule_t *rule = global->opts->filter_rules;
while (rule) {
filter_rule_t *fr = malloc(sizeof(filter_rule_t));
if (!fr)
filter_rule_t *r = malloc(sizeof(filter_rule_t));
if (!r)
return oom_return_null(argv0);
memset(fr, 0, sizeof(filter_rule_t));
memset(r, 0, sizeof(filter_rule_t));
if (rule->site) {
fr->site = strdup(rule->site);
if (!fr->site)
r->all_conns = rule->all_conns;
#ifndef WITHOUT_USERAUTH
r->all_users = rule->all_users;
if (rule->user) {
r->user = strdup(rule->user);
if (!r->user)
return oom_return_null(argv0);
}
fr->exact = rule->exact;
if (rule->ip) {
fr->ip = strdup(rule->ip);
if (!fr->ip)
if (rule->keyword) {
r->keyword = strdup(rule->keyword);
if (!r->keyword)
return oom_return_null(argv0);
}
#ifndef WITHOUT_USERAUTH
if (rule->user) {
fr->user = strdup(rule->user);
if (!fr->user)
#endif /* !WITHOUT_USERAUTH */
if (rule->ip) {
r->ip = strdup(rule->ip);
if (!r->ip)
return oom_return_null(argv0);
}
if (rule->keyword) {
fr->keyword = strdup(rule->keyword);
if (!fr->keyword)
if (rule->site) {
r->site = strdup(rule->site);
if (!r->site)
return oom_return_null(argv0);
}
r->all_sites = rule->all_sites;
r->exact = rule->exact;
fr->all_users = rule->all_users;
#endif /* !WITHOUT_USERAUTH */
fr->all_conns = rule->all_conns;
fr->all_sites = rule->all_sites;
fr->divert = rule->divert;
fr->split = rule->split;
fr->pass = rule->pass;
fr->block = rule->block;
fr->match = rule->match;
fr->log_connect = rule->log_connect;
fr->log_master = rule->log_master;
fr->log_cert = rule->log_cert;
fr->log_content = rule->log_content;
fr->log_pcap = rule->log_pcap;
#ifndef WITHOUT_MIRROR
fr->log_mirror = rule->log_mirror;
#endif /* !WITHOUT_MIRROR */
if (rule->port) {
r->port = strdup(rule->port);
if (!r->port)
return oom_return_null(argv0);
}
r->all_ports = rule->all_ports;
r->exact_port = rule->exact_port;
fr->dstip = rule->dstip;
fr->sni = rule->sni;
fr->cn = rule->cn;
fr->host = rule->host;
fr->uri = rule->uri;
r->dstip = rule->dstip;
r->sni = rule->sni;
r->cn = rule->cn;
r->host = rule->host;
r->uri = rule->uri;
fr->precedence = rule->precedence;
r->action = rule->action;
opts_append_to_filter_rules(&opts->filter_rules, fr);
opts_append_to_filter_rules(&opts->filter_rules, r);
rule = rule->next;
}
@ -1345,7 +1355,7 @@ filter_rule_str(filter_rule_t *rule)
int count = 0;
while (rule) {
char *p;
if (asprintf(&p, "site=%s, %s, ip=%s"
if (asprintf(&p, "site=%s, %s, port=%s, %s, ip=%s"
#ifndef WITHOUT_USERAUTH
", user=%s, keyword=%s"
#endif /* !WITHOUT_USERAUTH */
@ -1353,12 +1363,14 @@ filter_rule_str(filter_rule_t *rule)
#ifndef WITHOUT_USERAUTH
"|%s"
#endif /* !WITHOUT_USERAUTH */
"|%s, action=%s|%s|%s|%s|%s, log=%s|%s|%s|%s|%s"
"|%s|%s, action=%s|%s|%s|%s|%s, log=%s|%s|%s|%s|%s"
#ifndef WITHOUT_MIRROR
"|%s"
#endif /* !WITHOUT_MIRROR */
", apply to=%s|%s|%s|%s|%s, precedence=%d",
rule->site, rule->exact ? "exact" : "substring", STRORNONE(rule->ip),
rule->site, rule->exact ? "exact" : "substring",
STRORNONE(rule->port), rule->port ? (rule->exact_port ? "exact_port" : "substring_port") : "",
STRORNONE(rule->ip),
#ifndef WITHOUT_USERAUTH
STRORNONE(rule->user), STRORNONE(rule->keyword),
#endif /* !WITHOUT_USERAUTH */
@ -1366,16 +1378,16 @@ filter_rule_str(filter_rule_t *rule)
#ifndef WITHOUT_USERAUTH
rule->all_users ? "users" : "",
#endif /* !WITHOUT_USERAUTH */
rule->all_sites ? "sites" : "",
rule->divert ? "divert" : "", rule->split ? "split" : "", rule->pass ? "pass" : "", rule->block ? "block" : "", rule->match ? "match" : "",
rule->log_connect ? (rule->log_connect == 1 ? "!connect" : "connect") : "", rule->log_master ? (rule->log_master == 1 ? "!master" : "master") : "",
rule->log_cert ? (rule->log_cert == 1 ? "!cert" : "cert") : "", rule->log_content ? (rule->log_content == 1 ? "!content" : "content") : "",
rule->log_pcap ? (rule->log_pcap == 1 ? "!pcap" : "pcap") : "",
rule->all_sites ? "sites" : "", rule->all_ports ? "ports" : "",
rule->action.divert ? "divert" : "", rule->action.split ? "split" : "", rule->action.pass ? "pass" : "", rule->action.block ? "block" : "", rule->action.match ? "match" : "",
rule->action.log_connect ? (rule->action.log_connect == 1 ? "!connect" : "connect") : "", rule->action.log_master ? (rule->action.log_master == 1 ? "!master" : "master") : "",
rule->action.log_cert ? (rule->action.log_cert == 1 ? "!cert" : "cert") : "", rule->action.log_content ? (rule->action.log_content == 1 ? "!content" : "content") : "",
rule->action.log_pcap ? (rule->action.log_pcap == 1 ? "!pcap" : "pcap") : "",
#ifndef WITHOUT_MIRROR
rule->log_mirror ? (rule->log_mirror == 1 ? "!mirror" : "mirror") : "",
rule->action.log_mirror ? (rule->action.log_mirror == 1 ? "!mirror" : "mirror") : "",
#endif /* !WITHOUT_MIRROR */
rule->dstip ? "dstip" : "", rule->sni ? "sni" : "", rule->cn ? "cn" : "", rule->host ? "host" : "", rule->uri ? "uri" : "",
rule->precedence) < 0) {
rule->action.precedence) < 0) {
goto err;
}
char *nfrs;
@ -1401,28 +1413,72 @@ out:
return frs;
}
static char *
filter_port_str(filter_port_t *port)
{
char *s = NULL;
int count = 0;
while (port) {
char *p;
if (asprintf(&p, "%s\n %d: %s (%s%s, action=%s|%s|%s|%s|%s, log=%s|%s|%s|%s|%s"
#ifndef WITHOUT_MIRROR
"|%s"
#endif /* !WITHOUT_MIRROR */
", precedence=%d)", STRORNONE(s), count,
port->port, port->all_ports ? "all_ports, " : "", port->exact ? "exact" : "substring",
port->action.divert ? "divert" : "", port->action.split ? "split" : "", port->action.pass ? "pass" : "", port->action.block ? "block" : "", port->action.match ? "match" : "",
port->action.log_connect ? (port->action.log_connect == 1 ? "!connect" : "connect") : "", port->action.log_master ? (port->action.log_master == 1 ? "!master" : "master") : "",
port->action.log_cert ? (port->action.log_cert == 1 ? "!cert" : "cert") : "", port->action.log_content ? (port->action.log_content == 1 ? "!content" : "content") : "",
port->action.log_pcap ? (port->action.log_pcap == 1 ? "!pcap" : "pcap") : "",
#ifndef WITHOUT_MIRROR
port->action.log_mirror ? (port->action.log_mirror == 1 ? "!mirror" : "mirror") : "",
#endif /* !WITHOUT_MIRROR */
port->action.precedence) < 0) {
goto err;
}
if (s)
free(s);
s = p;
port = port->next;
count++;
}
goto out;
err:
if (s) {
free(s);
s = NULL;
}
out:
return s;
}
static char *
filter_sites_str(filter_site_t *site)
{
char *s = NULL;
char *ports = NULL;
int count = 0;
while (site) {
ports = filter_port_str(site->port);
char *p;
if (asprintf(&p, "%s\n %d: %s (%s%s, action=%s|%s|%s|%s|%s, log=%s|%s|%s|%s|%s"
#ifndef WITHOUT_MIRROR
"|%s"
#endif /* !WITHOUT_MIRROR */
", precedence=%d)", STRORNONE(s), count,
", precedence=%d)%s%s", STRORNONE(s), count,
site->site, site->all_sites ? "all_sites, " : "", site->exact ? "exact" : "substring",
site->divert ? "divert" : "", site->split ? "split" : "", site->pass ? "pass" : "", site->block ? "block" : "", site->match ? "match" : "",
site->log_connect ? (site->log_connect == 1 ? "!connect" : "connect") : "", site->log_master ? (site->log_master == 1 ? "!master" : "master") : "",
site->log_cert ? (site->log_cert == 1 ? "!cert" : "cert") : "", site->log_content ? (site->log_content == 1 ? "!content" : "content") : "",
site->log_pcap ? (site->log_pcap == 1 ? "!pcap" : "pcap") : "",
site->action.divert ? "divert" : "", site->action.split ? "split" : "", site->action.pass ? "pass" : "", site->action.block ? "block" : "", site->action.match ? "match" : "",
site->action.log_connect ? (site->action.log_connect == 1 ? "!connect" : "connect") : "", site->action.log_master ? (site->action.log_master == 1 ? "!master" : "master") : "",
site->action.log_cert ? (site->action.log_cert == 1 ? "!cert" : "cert") : "", site->action.log_content ? (site->action.log_content == 1 ? "!content" : "content") : "",
site->action.log_pcap ? (site->action.log_pcap == 1 ? "!pcap" : "pcap") : "",
#ifndef WITHOUT_MIRROR
site->log_mirror ? (site->log_mirror == 1 ? "!mirror" : "mirror") : "",
site->action.log_mirror ? (site->action.log_mirror == 1 ? "!mirror" : "mirror") : "",
#endif /* !WITHOUT_MIRROR */
site->precedence) < 0) {
site->action.precedence,
ports ? "\n port:" : "", STRORNONE(ports)) < 0) {
goto err;
}
if (s)
@ -1543,6 +1599,10 @@ filter_users_str(filter_user_t *user)
int count = 0;
while (user) {
// Make sure the current user does not have any keyword
if (user->keyword)
goto skip;
list = filter_list_str(user->list);
char *p = NULL;
@ -1559,8 +1619,9 @@ filter_users_str(filter_user_t *user)
if (s)
free(s);
s = p;
user = user->next;
count++;
skip:
user = user->next;
}
goto out;
err:
@ -1616,6 +1677,10 @@ filter_userkeywords_str(filter_user_t *user)
int count = 0;
while (user) {
// Make sure the current user has a keyword
if (!user->keyword)
goto skip;
list = filter_keywords_str(user->keyword);
char *p = NULL;
@ -1628,8 +1693,9 @@ filter_userkeywords_str(filter_user_t *user)
if (s)
free(s);
s = p;
user = user->next;
count++;
skip:
user = user->next;
}
goto out;
err:
@ -2586,11 +2652,11 @@ opts_unset_validate_proto(opts_t *opts)
opts->validate_proto = 0;
}
#ifdef DEBUG_OPTS
static void
opts_dbg_print_filter_rule(filter_rule_t *rule)
{
#ifdef DEBUG_OPTS
log_dbg_printf("Filter rule: %s, %s, %s"
log_dbg_printf("Filter rule: %s, %s, %s, %s, %s"
#ifndef WITHOUT_USERAUTH
", %s, %s"
#endif /* !WITHOUT_USERAUTH */
@ -2598,12 +2664,14 @@ opts_dbg_print_filter_rule(filter_rule_t *rule)
#ifndef WITHOUT_USERAUTH
"%s|"
#endif /* !WITHOUT_USERAUTH */
"%s, action=%s|%s|%s|%s|%s, log=%s|%s|%s|%s|%s"
"%s|%s, action=%s|%s|%s|%s|%s, log=%s|%s|%s|%s|%s"
#ifndef WITHOUT_MIRROR
"|%s"
#endif /* !WITHOUT_MIRROR */
", apply to=%s|%s|%s|%s|%s, precedence=%d\n",
rule->site, rule->exact ? "exact" : "substring", STRORNONE(rule->ip),
rule->site, rule->exact ? "exact" : "substring",
STRORNONE(rule->port), rule->port ? (rule->exact_port ? "exact_port" : "substring_port") : "",
STRORNONE(rule->ip),
#ifndef WITHOUT_USERAUTH
STRORNONE(rule->user), STRORNONE(rule->keyword),
#endif /* !WITHOUT_USERAUTH */
@ -2611,18 +2679,18 @@ opts_dbg_print_filter_rule(filter_rule_t *rule)
#ifndef WITHOUT_USERAUTH
rule->all_users ? "users" : "",
#endif /* !WITHOUT_USERAUTH */
rule->all_sites ? "sites" : "",
rule->divert ? "divert" : "", rule->split ? "split" : "", rule->pass ? "pass" : "", rule->block ? "block" : "", rule->match ? "match" : "",
rule->log_connect ? (rule->log_connect == 1 ? "!connect" : "connect") : "", rule->log_master ? (rule->log_master == 1 ? "!master" : "master") : "",
rule->log_cert ? (rule->log_cert == 1 ? "!cert" : "cert") : "", rule->log_content ? (rule->log_content == 1 ? "!content" : "content") : "",
rule->log_pcap ? (rule->log_pcap == 1 ? "!pcap" : "pcap") : "",
rule->all_sites ? "sites" : "", rule->all_ports ? "ports" : "",
rule->action.divert ? "divert" : "", rule->action.split ? "split" : "", rule->action.pass ? "pass" : "", rule->action.block ? "block" : "", rule->action.match ? "match" : "",
rule->action.log_connect ? (rule->action.log_connect == 1 ? "!connect" : "connect") : "", rule->action.log_master ? (rule->action.log_master == 1 ? "!master" : "master") : "",
rule->action.log_cert ? (rule->action.log_cert == 1 ? "!cert" : "cert") : "", rule->action.log_content ? (rule->action.log_content == 1 ? "!content" : "content") : "",
rule->action.log_pcap ? (rule->action.log_pcap == 1 ? "!pcap" : "pcap") : "",
#ifndef WITHOUT_MIRROR
rule->log_mirror ? (rule->log_mirror == 1 ? "!mirror" : "mirror") : "",
rule->action.log_mirror ? (rule->action.log_mirror == 1 ? "!mirror" : "mirror") : "",
#endif /* !WITHOUT_MIRROR */
rule->dstip ? "dstip" : "", rule->sni ? "sni" : "", rule->cn ? "cn" : "", rule->host ? "host" : "", rule->uri ? "uri" : "",
rule->precedence);
#endif /* DEBUG_OPTS */
rule->action.precedence);
}
#endif /* DEBUG_OPTS */
#define MAX_SITE_LEN 200
@ -2682,7 +2750,7 @@ opts_set_passsite(opts_t *opts, char *value, int line_num)
return oom_return_na();
// precedence can only go up not down
rule->precedence = 0;
rule->action.precedence = 0;
if (argc == 1) {
// Apply filter rule to all conns
@ -2694,14 +2762,14 @@ opts_set_passsite(opts_t *opts, char *value, int line_num)
if (!strcmp(argv[1], "*")) {
#ifndef WITHOUT_USERAUTH
// Apply filter rule to all users perhaps with keyword
rule->precedence++;
rule->action.precedence++;
rule->all_users = 1;
} else if (sys_isuser(argv[1])) {
if (!opts->user_auth) {
fprintf(stderr, "User filter requires user auth on line %d\n", line_num);
return -1;
}
rule->precedence += 2;
rule->action.precedence += 2;
rule->user = strdup(argv[1]);
if (!rule->user)
return oom_return_na();
@ -2710,7 +2778,7 @@ opts_set_passsite(opts_t *opts, char *value, int line_num)
rule->all_conns = 1;
#endif /* WITHOUT_USERAUTH */
} else {
rule->precedence++;
rule->action.precedence++;
rule->ip = strdup(argv[1]);
if (!rule->ip)
return oom_return_na();
@ -2735,21 +2803,23 @@ opts_set_passsite(opts_t *opts, char *value, int line_num)
fprintf(stderr, "Keyword filter requires user auth on line %d\n", line_num);
return -1;
}
rule->precedence++;
rule->action.precedence++;
rule->keyword = strdup(argv[2]);
if (!rule->keyword)
return oom_return_na();
#endif /* !WITHOUT_USERAUTH */
}
rule->precedence++;
rule->action.precedence++;
rule->sni = 1;
rule->cn = 1;
rule->pass = 1;
rule->action.pass = 1;
opts_append_to_filter_rules(&opts->filter_rules, rule);
#ifdef DEBUG_OPTS
opts_dbg_print_filter_rule(rule);
#endif /* DEBUG_OPTS */
return 0;
}
@ -2873,6 +2943,45 @@ opts_set_site(filter_rule_t *rule, const char *site, int line_num)
return 0;
}
static int WUNRES
opts_set_port(filter_rule_t *rule, const char *port, int line_num)
{
#define MAX_PORT_LEN 6
size_t len = strlen(port);
if (len > MAX_PORT_LEN) {
fprintf(stderr, "Filter port too long %zu > %d on line %d\n", len, MAX_PORT_LEN, line_num);
return -1;
}
rule->port = strdup(port);
if (!rule->port)
return oom_return_na();
if (rule->port[len - 1] == '*') {
rule->exact_port = 0;
len--;
rule->port[len] = '\0';
// site == "*" ?
if (len == 0)
rule->all_ports = 1;
} else {
rule->exact_port = 1;
}
// redundant?
if (equal(rule->port, "*"))
rule->all_ports = 1;
if (!rule->site) {
rule->site = strdup("");
if (!rule->site)
return oom_return_na();
}
return 0;
}
static int WUNRES
opts_inc_arg_index(int i, int argc, char *last, int line_num)
{
@ -2889,15 +2998,17 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
{
//(Divert|Split|Pass|Block|Match)
// ([from (
// user (username|$macro|*) [desc keyword]|
// ip (clientaddr|$macro|*)|
// user (username|$macro|*) [desc (keyword|$macro|*)]|
// desc (keyword|$macro|*)|
// ip (clientip|$macro|*)|
// *)]
// [to (
// sni (servername[*]|$macro|*)|
// cn (commonname[*]|$macro|*)|
// host (host[*]|$macro|*)|
// uri (uri[*]|$macro|*)|
// ip (serveraddr|$macro|*)|
// ip (serverip[*]|$macro|*) [port (serverport[*]|$macro|*)]|
// port (serverport[*]|$macro|*)|
// *)]
// [log ([[!]connect] [[!]master] [[!]cert]
// [[!]content] [[!]pcap] [[!]mirror] [$macro]|*|!*)]
@ -2909,18 +3020,18 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
memset(rule, 0, sizeof(filter_rule_t));
if (equal(name, "Divert"))
rule->divert = 1;
rule->action.divert = 1;
else if (equal(name, "Split"))
rule->split = 1;
rule->action.split = 1;
else if (equal(name, "Pass"))
rule->pass = 1;
rule->action.pass = 1;
else if (equal(name, "Block"))
rule->block = 1;
rule->action.block = 1;
else if (equal(name, "Match"))
rule->match = 1;
rule->action.match = 1;
// precedence can only go up not down
rule->precedence = 0;
rule->action.precedence = 0;
int done_from = 0;
int done_to = 0;
@ -2938,12 +3049,12 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
rule->precedence++;
rule->action.precedence++;
if (equal(argv[i], "*")) {
rule->all_users = 1;
} else {
rule->precedence++;
rule->action.precedence++;
rule->user = strdup(argv[i]);
if (!rule->user)
return oom_return_na();
@ -2954,7 +3065,7 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
if (i < argc && equal(argv[i], "desc")) {
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
rule->precedence++;
rule->action.precedence++;
rule->keyword = strdup(argv[i++]);
if (!rule->keyword)
return oom_return_na();
@ -2971,7 +3082,7 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
if (equal(argv[i], "*")) {
rule->all_conns = 1;
} else {
rule->precedence++;
rule->action.precedence++;
rule->ip = strdup(argv[i]);
if (!rule->ip)
return oom_return_na();
@ -2987,8 +3098,8 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
if (equal(argv[i], "sni") || equal(argv[i], "cn") || equal(argv[i], "host") || equal(argv[i], "uri") || equal(argv[i], "ip")) {
rule->precedence++;
if (equal(argv[i], "sni") || equal(argv[i], "cn") || equal(argv[i], "host") || equal(argv[i], "uri")) {
rule->action.precedence++;
if (equal(argv[i], "sni"))
rule->sni = 1;
else if (equal(argv[i], "cn"))
@ -2997,8 +3108,6 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
rule->host = 1;
else if (equal(argv[i], "uri"))
rule->uri = 1;
else if (equal(argv[i], "ip"))
rule->dstip = 1;
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
@ -3008,6 +3117,31 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
done_to = 1;
}
else if (equal(argv[i], "ip") || equal(argv[i], "port")) {
rule->dstip = 1;
if (equal(argv[i], "ip")) {
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
// Just ip spec should not increase rule precedence
if (opts_set_site(rule, argv[i++], line_num) == -1)
return -1;
}
if (i < argc && equal(argv[i], "port")) {
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
rule->action.precedence++;
if (opts_set_port(rule, argv[i++], line_num) == -1)
return -1;
}
done_to = 1;
}
else if (equal(argv[i], "*")) {
i++;
}
@ -3016,7 +3150,7 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
rule->precedence++;
rule->action.precedence++;
if (equal(argv[i], "connect") || equal(argv[i], "master") || equal(argv[i], "cert") || equal(argv[i], "content") || equal(argv[i], "pcap") ||
equal(argv[i], "!connect") || equal(argv[i], "!master") || equal(argv[i], "!cert") || equal(argv[i], "!content") || equal(argv[i], "!pcap")
@ -3026,30 +3160,30 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
) {
do {
if (equal(argv[i], "connect"))
rule->log_connect = 2;
rule->action.log_connect = 2;
else if (equal(argv[i], "master"))
rule->log_master = 2;
rule->action.log_master = 2;
else if (equal(argv[i], "cert"))
rule->log_cert = 2;
rule->action.log_cert = 2;
else if (equal(argv[i], "content"))
rule->log_content = 2;
rule->action.log_content = 2;
else if (equal(argv[i], "pcap"))
rule->log_pcap = 2;
rule->action.log_pcap = 2;
else if (equal(argv[i], "!connect"))
rule->log_connect = 1;
rule->action.log_connect = 1;
else if (equal(argv[i], "!master"))
rule->log_master = 1;
rule->action.log_master = 1;
else if (equal(argv[i], "!cert"))
rule->log_cert = 1;
rule->action.log_cert = 1;
else if (equal(argv[i], "!content"))
rule->log_content = 1;
rule->action.log_content = 1;
else if (equal(argv[i], "!pcap"))
rule->log_pcap = 1;
rule->action.log_pcap = 1;
#ifndef WITHOUT_MIRROR
else if (equal(argv[i], "mirror"))
rule->log_mirror = 2;
rule->action.log_mirror = 2;
else if (equal(argv[i], "!mirror"))
rule->log_mirror = 1;
rule->action.log_mirror = 1;
#endif /* !WITHOUT_MIRROR */
if (++i == argc)
@ -3062,24 +3196,24 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
);
}
else if (equal(argv[i], "*")) {
rule->log_connect = 2;
rule->log_master = 2;
rule->log_cert = 2;
rule->log_content = 2;
rule->log_pcap = 2;
rule->action.log_connect = 2;
rule->action.log_master = 2;
rule->action.log_cert = 2;
rule->action.log_content = 2;
rule->action.log_pcap = 2;
#ifndef WITHOUT_MIRROR
rule->log_mirror = 2;
rule->action.log_mirror = 2;
#endif /* !WITHOUT_MIRROR */
i++;
}
else if (equal(argv[i], "!*")) {
rule->log_connect = 1;
rule->log_master = 1;
rule->log_cert = 1;
rule->log_content = 1;
rule->log_pcap = 1;
rule->action.log_connect = 1;
rule->action.log_master = 1;
rule->action.log_cert = 1;
rule->action.log_content = 1;
rule->action.log_pcap = 1;
#ifndef WITHOUT_MIRROR
rule->log_mirror = 1;
rule->action.log_mirror = 1;
#endif /* !WITHOUT_MIRROR */
i++;
}
@ -3103,7 +3237,9 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
opts_append_to_filter_rules(&opts->filter_rules, rule);
#ifdef DEBUG_OPTS
opts_dbg_print_filter_rule(rule);
#endif /* DEBUG_OPTS */
return 0;
}
@ -3120,7 +3256,7 @@ filter_rule_expand_macro(opts_t *opts, const char *name, int argc, char **argv,
if ((macro = opts_find_macro(opts->macro, argv[i]))) {
value_t *value = macro->value;
while (value) {
// Prevent infinite macro expansion
// Prevent infinite macro expansion, macros do not allow it, but macro expansion should detect it too
if (value->value[0] == '$') {
fprintf(stderr, "Invalid macro value '%s' on line %d\n", value->value, line_num);
return -1;
@ -3250,7 +3386,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
if (equal(argv[i], "sni") || equal(argv[i], "cn") || equal(argv[i], "host") || equal(argv[i], "uri") || equal(argv[i], "ip")) {
if (equal(argv[i], "sni") || equal(argv[i], "cn") || equal(argv[i], "host") || equal(argv[i], "uri")) {
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
@ -3261,6 +3397,30 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
done_to = 1;
}
else if (equal(argv[i], "ip") || equal(argv[i], "port")) {
if (equal(argv[i], "ip")) {
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
if ((rv = filter_rule_expand_macro(opts, name, argc, argv, i, line_num)) != 0) {
return rv;
}
i++;
}
// It is possible to define port without ip (i.e. * or all_sites), hence no 'else' here
if (i < argc && equal(argv[i], "port")) {
if ((i = opts_inc_arg_index(i, argc, argv[i], line_num)) == -1)
return -1;
if ((rv = filter_rule_expand_macro(opts, name, argc, argv, i, line_num)) != 0) {
return rv;
}
i++;
}
done_to = 1;
}
else if (equal(argv[i], "*")) {
i++;
}
@ -3343,6 +3503,88 @@ opts_set_filter_rule(opts_t *opts, const char *name, char *value, int line_num)
return filter_rule_parse(opts, name, argc, argv, line_num);
}
static filter_port_t *
opts_find_port(filter_port_t *port, filter_rule_t *rule)
{
while (port) {
if ((port->exact == rule->exact_port) && !strcmp(port->port, rule->port))
break;
port = port->next;
}
return port;
}
static filter_port_t *
opts_add_port(filter_port_t *port, filter_rule_t *rule)
{
int prepend = 1;
if (port && port->all_ports) {
// all_ports should be at the beginning of the port list for performance reasons
// it effectively disables the rest of the list, but we keep the rest for reporting
prepend = 0;
}
filter_port_t *p = opts_find_port(port, rule);
if (!p) {
p = malloc(sizeof(filter_port_t));
if (!p)
return oom_return_na_null();
memset(p, 0, sizeof(filter_port_t));
p->port = strdup(rule->port);
if (!p->port)
return oom_return_na_null();
if (prepend) {
p->next = port;
} else {
// Insert the new port after the head
// If prepend is 0, port is never NULL
p->next = port->next;
port->next = p;
}
} else {
// If the port exists, we should return the head of the port list
// i.e. we have not prepended anything
prepend = 0;
}
// Do not override the specs of port rules at higher precedence
// precedence can only go up not down
if (rule->action.precedence >= p->action.precedence) {
p->all_ports = rule->all_ports;
p->exact = rule->exact_port;
// Multiple rules can set an action for the same port, hence the bit-wise OR
p->action.divert |= rule->action.divert;
p->action.split |= rule->action.split;
p->action.pass |= rule->action.pass;
p->action.block |= rule->action.block;
p->action.match |= rule->action.match;
// Multiple log actions can be set for the same port
// Multiple rules can enable/disable or don't change a log action for the same port
// 0: don't change, 1: disable, 2: enable
if (rule->action.log_connect)
p->action.log_connect = rule->action.log_connect;
if (rule->action.log_master)
p->action.log_master = rule->action.log_master;
if (rule->action.log_cert)
p->action.log_cert = rule->action.log_cert;
if (rule->action.log_content)
p->action.log_content = rule->action.log_content;
if (rule->action.log_pcap)
p->action.log_pcap = rule->action.log_pcap;
#ifndef WITHOUT_MIRROR
if (rule->action.log_mirror)
p->action.log_mirror = rule->action.log_mirror;
#endif /* !WITHOUT_MIRROR */
p->action.precedence = rule->action.precedence;
}
return prepend ? p : port;
}
static filter_site_t *
opts_find_site(filter_site_t *site, filter_rule_t *rule)
{
@ -3388,38 +3630,44 @@ opts_add_site(filter_site_t *site, filter_rule_t *rule)
prepend = 0;
}
s->all_sites = rule->all_sites;
s->exact = rule->exact;
// Do not override the specs of a site with a port rule
// Port rule is added as a new port under the same site
// hence 'if else', not just 'if'
if (rule->port) {
s->port = opts_add_port(s->port, rule);
}
// Do not override the specs of site rules at higher precedence
// precedence can only go up not down
if (rule->precedence >= s->precedence) {
s->all_sites = rule->all_sites;
s->exact = rule->exact;
else if (rule->action.precedence >= s->action.precedence) {
// Multiple rules can set an action for the same site, hence the bit-wise OR
s->divert |= rule->divert;
s->split |= rule->split;
s->pass |= rule->pass;
s->block |= rule->block;
s->match |= rule->match;
s->action.divert |= rule->action.divert;
s->action.split |= rule->action.split;
s->action.pass |= rule->action.pass;
s->action.block |= rule->action.block;
s->action.match |= rule->action.match;
// Multiple log actions can be set for the same site
// Multiple rules can enable/disable or don't change a log action for the same site
// 0: don't change, 1: disable, 2: enable
if (rule->log_connect)
s->log_connect = rule->log_connect;
if (rule->log_master)
s->log_master = rule->log_master;
if (rule->log_cert)
s->log_cert = rule->log_cert;
if (rule->log_content)
s->log_content = rule->log_content;
if (rule->log_pcap)
s->log_pcap = rule->log_pcap;
if (rule->action.log_connect)
s->action.log_connect = rule->action.log_connect;
if (rule->action.log_master)
s->action.log_master = rule->action.log_master;
if (rule->action.log_cert)
s->action.log_cert = rule->action.log_cert;
if (rule->action.log_content)
s->action.log_content = rule->action.log_content;
if (rule->action.log_pcap)
s->action.log_pcap = rule->action.log_pcap;
#ifndef WITHOUT_MIRROR
if (rule->log_mirror)
s->log_mirror = rule->log_mirror;
if (rule->action.log_mirror)
s->action.log_mirror = rule->action.log_mirror;
#endif /* !WITHOUT_MIRROR */
s->precedence = rule->precedence;
s->action.precedence = rule->action.precedence;
}
return prepend ? s : site;

@ -188,16 +188,7 @@ typedef struct macro {
struct macro *next;
} macro_t;
typedef struct filter_rule {
char *site;
unsigned int all_sites : 1; /* 1 to match all sites == '*' */
unsigned int exact : 1; /* 1 for exact, 0 for substring match */
unsigned int all_conns : 1; /* 1 to apply to all src ips and users */
#ifndef WITHOUT_USERAUTH
unsigned int all_users : 1; /* 1 to apply to all users */
#endif /* !WITHOUT_USERAUTH */
typedef struct filter_action {
// Filter action
unsigned int divert : 1;
unsigned int split : 1;
@ -216,44 +207,66 @@ typedef struct filter_rule {
unsigned int log_mirror : 2;
#endif /* !WITHOUT_MIRROR */
// Conn field to apply filter to
unsigned int dstip : 1; /* 1 to apply to dst ip */
unsigned int host : 1; /* 1 to apply to http host */
unsigned int uri : 1; /* 1 to apply to http uri */
unsigned int sni : 1; /* 1 to apply to sni */
unsigned int cn : 1; /* 1 to apply to common names */
// Precedence is used in rule application
// More specific rules have higher precedence
unsigned int precedence;
} filter_action_t;
typedef struct filter_rule {
// from: source filter
unsigned int all_conns : 1; /* 1 to apply to all src ips and users */
#ifndef WITHOUT_USERAUTH
unsigned int all_users : 1; /* 1 to apply to all users */
char *user;
char *keyword;
#endif /* !WITHOUT_USERAUTH */
char *ip;
// Precedence is used in rule application
// More specific rules have higher precedence
unsigned int precedence;
// to: target filter
char *site;
unsigned int all_sites : 1; /* 1 to match all sites == '*' */
unsigned int exact : 1; /* 1 for exact, 0 for substring match */
// Used with dstip filters only, i.e. if the site is an ip address
// This is not for the src ip in the 'from' part of rules
char *port;
unsigned int all_ports : 1; /* 1 to match all ports == '*' */
unsigned int exact_port : 1; /* 1 for exact, 0 for substring match */
// Conn field to apply filter to
unsigned int dstip : 1; /* 1 to apply to dst ip */
unsigned int host : 1; /* 1 to apply to http host */
unsigned int uri : 1; /* 1 to apply to http uri */
unsigned int sni : 1; /* 1 to apply to sni */
unsigned int cn : 1; /* 1 to apply to common names */
struct filter_action action;
struct filter_rule *next;
} filter_rule_t;
typedef struct filter_port {
char *port;
unsigned int all_ports : 1;
unsigned int exact : 1;
struct filter_action action;
struct filter_port *next;
} filter_port_t;
typedef struct filter_site {
char *site;
unsigned int all_sites : 1;
unsigned int exact : 1;
unsigned int divert : 1;
unsigned int split : 1;
unsigned int pass : 1;
unsigned int block : 1;
unsigned int match : 1;
// Used with dstip filters only, i.e. if the site is an ip address
struct filter_port *port;
unsigned int log_connect : 2;
unsigned int log_master : 2;
unsigned int log_cert : 2;
unsigned int log_content : 2;
unsigned int log_pcap : 2;
#ifndef WITHOUT_MIRROR
unsigned int log_mirror : 2;
#endif /* !WITHOUT_MIRROR */
struct filter_action action;
unsigned int precedence;
struct filter_site *next;
} filter_site_t;

@ -387,12 +387,12 @@ protohttp_filter_request_header_line(const char *line, protohttp_ctx_t *http_ctx
}
static int NONNULL(1,2)
protohttp_match_host(pxy_conn_ctx_t *ctx, filter_site_t *site)
protohttp_filter_match_host(pxy_conn_ctx_t *ctx, filter_site_t *site)
{
protohttp_ctx_t *http_ctx = ctx->protoctx->arg;
if (site->precedence < ctx->filter_precedence) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->precedence, ctx->filter_precedence, site->site, http_ctx->http_host);
if (site->action.precedence < ctx->filter_precedence) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->action.precedence, ctx->filter_precedence, site->site, http_ctx->http_host);
return 0;
}
@ -415,12 +415,12 @@ protohttp_match_host(pxy_conn_ctx_t *ctx, filter_site_t *site)
}
static int NONNULL(1,2)
protohttp_match_uri(pxy_conn_ctx_t *ctx, filter_site_t *site)
protohttp_filter_match_uri(pxy_conn_ctx_t *ctx, filter_site_t *site)
{
protohttp_ctx_t *http_ctx = ctx->protoctx->arg;
if (site->precedence < ctx->filter_precedence) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->precedence, ctx->filter_precedence, site->site, http_ctx->http_uri);
if (site->action.precedence < ctx->filter_precedence) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->action.precedence, ctx->filter_precedence, site->site, http_ctx->http_uri);
return 0;
}
@ -450,7 +450,7 @@ protohttp_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
if (http_ctx->http_host) {
filter_site_t *site = list->host;
while (site) {
if (protohttp_match_host(ctx, site)) {
if (protohttp_filter_match_host(ctx, site)) {
// Do not print the surrounding slashes
log_err_level_printf(LOG_INFO, "Found site: %s for %s:%s, %s:%s"
#ifndef WITHOUT_USERAUTH
@ -462,7 +462,7 @@ protohttp_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
STRORDASH(ctx->user), STRORDASH(ctx->desc),
#endif /* !WITHOUT_USERAUTH */
STRORDASH(http_ctx->http_host));
return pxyconn_set_filter_action(ctx, site);
return pxyconn_set_filter_action(ctx, site->action, site->site);
}
site = site->next;
}
@ -480,7 +480,7 @@ protohttp_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
if (http_ctx->http_uri) {
filter_site_t *site = list->uri;
while (site) {
if (protohttp_match_uri(ctx, site)) {
if (protohttp_filter_match_uri(ctx, site)) {
// Do not print the surrounding slashes
log_err_level_printf(LOG_INFO, "Found site: %s for %s:%s, %s:%s"
#ifndef WITHOUT_USERAUTH
@ -492,7 +492,7 @@ protohttp_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
STRORDASH(ctx->user), STRORDASH(ctx->desc),
#endif /* !WITHOUT_USERAUTH */
STRORDASH(http_ctx->http_uri));
return pxyconn_set_filter_action(ctx, site);
return pxyconn_set_filter_action(ctx, site->action, site->site);
}
site = site->next;
}

@ -591,10 +591,10 @@ protossl_srccert_create(pxy_conn_ctx_t *ctx)
}
static int NONNULL(1,2)
protossl_match_sni(pxy_conn_ctx_t *ctx, filter_site_t *site)
protossl_filter_match_sni(pxy_conn_ctx_t *ctx, filter_site_t *site)
{
if (site->precedence < ctx->filter_precedence) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->precedence, ctx->filter_precedence, site->site, ctx->sslctx->sni);
if (site->action.precedence < ctx->filter_precedence) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->action.precedence, ctx->filter_precedence, site->site, ctx->sslctx->sni);
return 0;
}
@ -617,10 +617,10 @@ protossl_match_sni(pxy_conn_ctx_t *ctx, filter_site_t *site)
}
static int NONNULL(1,2)
protossl_match_cn(pxy_conn_ctx_t *ctx, filter_site_t *site)
protossl_filter_match_cn(pxy_conn_ctx_t *ctx, filter_site_t *site)
{
if (site->precedence < ctx->filter_precedence) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->precedence, ctx->filter_precedence, site->site, ctx->sslctx->ssl_names);
if (site->action.precedence < ctx->filter_precedence) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->action.precedence, ctx->filter_precedence, site->site, ctx->sslctx->ssl_names);
return 0;
}
@ -692,8 +692,7 @@ protossl_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
if (ctx->sslctx->sni) {
filter_site_t *site = list->sni;
while (site) {
if (protossl_match_sni(ctx, site)) {
// Do not print the surrounding slashes
if (protossl_filter_match_sni(ctx, site)) {
log_err_level_printf(LOG_INFO, "Found site: %s for %s:%s, %s:%s"
#ifndef WITHOUT_USERAUTH
", %s, %s"
@ -704,7 +703,7 @@ protossl_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
STRORDASH(ctx->user), STRORDASH(ctx->desc),
#endif /* !WITHOUT_USERAUTH */
STRORDASH(ctx->sslctx->sni));
return pxyconn_set_filter_action(ctx, site);
return pxyconn_set_filter_action(ctx, site->action, site->site);
}
site = site->next;
}
@ -722,8 +721,7 @@ protossl_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
if (ctx->sslctx->ssl_names) {
filter_site_t *site = list->cn;
while (site) {
if (protossl_match_cn(ctx, site)) {
// Do not print the surrounding slashes
if (protossl_filter_match_cn(ctx, site)) {
log_err_level_printf(LOG_INFO, "Found site: %s for %s:%s, %s:%s"
#ifndef WITHOUT_USERAUTH
", %s, %s"
@ -734,7 +732,7 @@ protossl_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
STRORDASH(ctx->user), STRORDASH(ctx->desc),
#endif /* !WITHOUT_USERAUTH */
STRORDASH(ctx->sslctx->ssl_names));
return pxyconn_set_filter_action(ctx, site);
return pxyconn_set_filter_action(ctx, site->action, site->site);
}
site = site->next;
}

@ -509,30 +509,79 @@ prototcp_bev_eventcb_connected_dst(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
}
static int NONNULL(1,2)
prototcp_filter_match(pxy_conn_ctx_t *ctx, filter_site_t *site)
prototcp_filter_match_port(pxy_conn_ctx_t *ctx, filter_port_t *port)
{
if (site->precedence < ctx->filter_precedence) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->precedence, ctx->filter_precedence, site->site, ctx->dsthost_str);
if (port->action.precedence < ctx->filter_precedence) {
log_finest_va("Rule port precedence lower than conn filter precedence %d < %d: %s, %s", port->action.precedence, ctx->filter_precedence, port->port, ctx->dsthost_str);
return 0;
}
if (port->all_ports) {
log_finest_va("Match all dst ports: %s, %s", port->port, ctx->dstport_str);
return 1;
}
else if (port->exact) {
if (!strcmp(ctx->dstport_str, port->port)) {
log_finest_va("Match exact with port: %s, %s", port->port, ctx->dstport_str);
return 1;
}
}
else {
if (strstr(ctx->dstport_str, port->port)) {
log_finest_va("Match substring in dst port: %s, %s", port->port, ctx->dstport_str);
return 1;
}
}
return 0;
}
static filter_action_t * NONNULL(1,2)
prototcp_filter_match_ip(pxy_conn_ctx_t *ctx, filter_site_t *site)
{
// Port spec determines the precedence of a site rule, unless the rule does not have any port
if (!site->port && (site->action.precedence < ctx->filter_precedence)) {
log_finest_va("Rule precedence lower than conn filter precedence %d < %d: %s, %s", site->action.precedence, ctx->filter_precedence, site->site, ctx->dsthost_str);
return NULL;
}
filter_action_t *action = NULL;
if (site->all_sites) {
log_finest_va("Match all dst: %s, %s", site->site, ctx->dsthost_str);
return 1;
action = &site->action;
}
else if (site->exact) {
if (!strcmp(ctx->dsthost_str, site->site)) {
log_finest_va("Match exact with dst: %s, %s", site->site, ctx->dsthost_str);
return 1;
action = &site->action;
}
}
else {
if (strstr(ctx->dsthost_str, site->site)) {
log_finest_va("Match substring in dst: %s, %s", site->site, ctx->dsthost_str);
return 1;
action = &site->action;
}
}
return 0;
if (action) {
log_err_level_printf(LOG_INFO, "Found site: %s for %s:%s, %s:%s\n", site->site,
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
if (site->port) {
filter_port_t *port = site->port;
while (port) {
if (prototcp_filter_match_port(ctx, port)) {
log_err_level_printf(LOG_INFO, "Found port: %s for %s:%s, %s:%s\n", port->port,
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
return &port->action;
}
port = port->next;
}
log_finest_va("No filter match with port: %s:%s, %s:%s",
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
}
}
return action;
}
static unsigned int NONNULL(1,2)
@ -541,11 +590,9 @@ prototcp_dsthost_filter(pxy_conn_ctx_t *ctx, filter_list_t *list)
if (ctx->dsthost_str) {
filter_site_t *site = list->ip;
while (site) {
if (prototcp_filter_match(ctx, site)) {
log_err_level_printf(LOG_INFO, "Found site: %s for %s:%s, %s:%s\n", site->site,
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str));
return pxyconn_set_filter_action(ctx, site);
}
filter_action_t *action = prototcp_filter_match_ip(ctx, site);
if (action)
return pxyconn_set_filter_action(ctx, *action, site->site);
site = site->next;
}
log_finest_va("No filter match with ip: %s:%s, %s:%s",

@ -2007,63 +2007,63 @@ pxyconn_apply_deferred_block_action(pxy_conn_ctx_t *ctx)
}
unsigned int
pxyconn_set_filter_action(pxy_conn_ctx_t *ctx, filter_site_t *site)
pxyconn_set_filter_action(pxy_conn_ctx_t *ctx, filter_action_t a, char *site)
{
unsigned int action = FILTER_ACTION_NONE;
if (site->divert) {
log_err_level_printf(LOG_INFO, "Site filter divert action for %s, precedence %d\n", site->site, site->precedence);
if (a.divert) {
log_err_level_printf(LOG_INFO, "Filter divert action for %s, precedence %d\n", site, a.precedence);
action = FILTER_ACTION_DIVERT;
}
else if (site->split) {
log_err_level_printf(LOG_INFO, "Site filter split action for %s, precedence %d\n", site->site, site->precedence);
else if (a.split) {
log_err_level_printf(LOG_INFO, "Filter split action for %s, precedence %d\n", site, a.precedence);
action = FILTER_ACTION_SPLIT;
}
else if (site->pass) {
else if (a.pass) {
// Ignore pass action if already in passthrough mode
if (!ctx->pass) {
log_err_level_printf(LOG_INFO, "Site filter pass action for %s, precedence %d\n", site->site, site->precedence);
log_err_level_printf(LOG_INFO, "Filter pass action for %s, precedence %d\n", site, a.precedence);
action = FILTER_ACTION_PASS;
}
}
else if (site->block) {
log_err_level_printf(LOG_INFO, "Site filter block action for %s, precedence %d\n", site->site, site->precedence);
else if (a.block) {
log_err_level_printf(LOG_INFO, "Filter block action for %s, precedence %d\n", site, a.precedence);
action = FILTER_ACTION_BLOCK;
}
else if (site->match) {
log_err_level_printf(LOG_INFO, "Site filter match action for %s, precedence %d\n", site->site, site->precedence);
else if (a.match) {
log_err_level_printf(LOG_INFO, "Filter match action for %s, precedence %d\n", site, a.precedence);
action = FILTER_ACTION_MATCH;
}
// Multiple log actions can be defined, hence no 'else'
// 0: don't change, 1: disable, 2: enable
if (site->log_connect) {
log_err_level_printf(LOG_INFO, "Site filter %s connect log for %s, precedence %d\n", site->log_connect % 2 ? "disable" : "enable", site->site, site->precedence);
action |= (site->log_connect % 2) ? FILTER_LOG_NOCONNECT : FILTER_LOG_CONNECT;
if (a.log_connect) {
log_err_level_printf(LOG_INFO, "Filter %s connect log for %s, precedence %d\n", a.log_connect % 2 ? "disable" : "enable", site, a.precedence);
action |= (a.log_connect % 2) ? FILTER_LOG_NOCONNECT : FILTER_LOG_CONNECT;
}
if (site->log_master) {
log_err_level_printf(LOG_INFO, "Site filter %s master log for %s, precedence %d\n", site->log_master % 2 ? "disable" : "enable", site->site, site->precedence);
action |= (site->log_master % 2) ? FILTER_LOG_NOMASTER : FILTER_LOG_MASTER;
if (a.log_master) {
log_err_level_printf(LOG_INFO, "Filter %s master log for %s, precedence %d\n", a.log_master % 2 ? "disable" : "enable", site, a.precedence);
action |= (a.log_master % 2) ? FILTER_LOG_NOMASTER : FILTER_LOG_MASTER;
}
if (site->log_cert) {
log_err_level_printf(LOG_INFO, "Site filter %s cert log for %s, precedence %d\n", site->log_cert % 2 ? "disable" : "enable", site->site, site->precedence);
action |= (site->log_cert % 2) ? FILTER_LOG_NOCERT : FILTER_LOG_CERT;
if (a.log_cert) {
log_err_level_printf(LOG_INFO, "Filter %s cert log for %s, precedence %d\n", a.log_cert % 2 ? "disable" : "enable", site, a.precedence);
action |= (a.log_cert % 2) ? FILTER_LOG_NOCERT : FILTER_LOG_CERT;
}
if (site->log_content) {
log_err_level_printf(LOG_INFO, "Site filter %s content log for %s, precedence %d\n", site->log_content % 2 ? "disable" : "enable", site->site, site->precedence);
action |= (site->log_content % 2) ? FILTER_LOG_NOCONTENT : FILTER_LOG_CONTENT;
if (a.log_content) {
log_err_level_printf(LOG_INFO, "Filter %s content log for %s, precedence %d\n", a.log_content % 2 ? "disable" : "enable", site, a.precedence);
action |= (a.log_content % 2) ? FILTER_LOG_NOCONTENT : FILTER_LOG_CONTENT;
}
if (site->log_pcap) {
log_err_level_printf(LOG_INFO, "Site filter %s pcap log for %s, precedence %d\n", site->log_pcap % 2 ? "disable" : "enable", site->site, site->precedence);
action |= (site->log_pcap % 2) ? FILTER_LOG_NOPCAP : FILTER_LOG_PCAP;
if (a.log_pcap) {
log_err_level_printf(LOG_INFO, "Filter %s pcap log for %s, precedence %d\n", a.log_pcap % 2 ? "disable" : "enable", site, a.precedence);
action |= (a.log_pcap % 2) ? FILTER_LOG_NOPCAP : FILTER_LOG_PCAP;
}
#ifndef WITHOUT_MIRROR
if (site->log_mirror) {
log_err_level_printf(LOG_INFO, "Site filter %s mirror log for %s, precedence %d\n", site->log_mirror % 2 ? "disable" : "enable", site->site, site->precedence);
action |= (site->log_mirror % 2) ? FILTER_LOG_NOMIRROR : FILTER_LOG_MIRROR;
if (a.log_mirror) {
log_err_level_printf(LOG_INFO, "Filter %s mirror log for %s, precedence %d\n", a.log_mirror % 2 ? "disable" : "enable", site, a.precedence);
action |= (a.log_mirror % 2) ? FILTER_LOG_NOMIRROR : FILTER_LOG_MIRROR;
}
#endif /* !WITHOUT_MIRROR */
action |= site->precedence;
action |= a.precedence;
return action;
}

@ -444,9 +444,9 @@ int pxy_is_listuser(userlist_t *, const char *
void pxy_classify_user(pxy_conn_ctx_t *) NONNULL(1);
void pxy_userauth(pxy_conn_ctx_t *) NONNULL(1);
#endif /* !WITHOUT_USERAUTH */
int pxyconn_apply_deferred_block_action(pxy_conn_ctx_t *) NONNULL(1);
unsigned int pxyconn_set_filter_action(pxy_conn_ctx_t *, filter_site_t *) NONNULL(1,2);
unsigned int pxyconn_filter(pxy_conn_ctx_t *, proto_filter_func_t) NONNULL(1);
int pxyconn_apply_deferred_block_action(pxy_conn_ctx_t *) NONNULL(1) WUNRES;
unsigned int pxyconn_set_filter_action(pxy_conn_ctx_t *, filter_action_t, char *) NONNULL(1,3) WUNRES;
unsigned int pxyconn_filter(pxy_conn_ctx_t *, proto_filter_func_t) NONNULL(1) WUNRES;
void pxy_conn_setup(evutil_socket_t, struct sockaddr *, int,
pxy_thrmgr_ctx_t *, proxyspec_t *, global_t *,
evutil_socket_t)

@ -308,15 +308,17 @@ The syntax of filtering rules is as follows:
(Divert|Split|Pass|Block|Match)
([from (
user (username|$macro|*) [desc keyword]|
ip (clientaddr|$macro|*)|
user (username|$macro|*) [desc (keyword|$macro|*)]|
desc (keyword|$macro|*)|
ip (clientip|$macro|*)|
*)]
[to (
sni (servername[*]|$macro|*)|
cn (commonname[*]|$macro|*)|
host (host[*]|$macro|*)|
uri (uri[*]|$macro|*)|
ip (serveraddr|$macro|*)|
ip (serverip[*]|$macro|*) [port (serverport[*]|$macro|*)]|
port (serverport[*]|$macro|*)|
*)]
[log ([[!]connect] [[!]master] [[!]cert]
[[!]content] [[!]pcap] [[!]mirror] [$macro]|*|!*)]
@ -331,7 +333,7 @@ user or description keyword, or * for all.
- The to part defines destination filter based on server IP address, SNI or
Common Names of SSL connections, Host or URI fields in HTTP Request headers, or
* for all.
+ Dst Host type of rules use ip site field
+ Dst Host type of rules use ip and port site fields
+ SSL type of rules use sni and cn site fields
+ HTTP type of rules use host and uri site fields
.br

@ -291,15 +291,17 @@ PassUsers admin
#
#(Divert|Split|Pass|Block|Match)
# ([from (
# user (username|$macro|*) [desc keyword]|
# ip (clientaddr|$macro|*)|
# user (username|$macro|*) [desc (keyword|$macro|*)]|
# desc (keyword|$macro|*)|
# ip (clientip|$macro|*)|
# *)]
# [to (
# sni (servername[*]|$macro|*)|
# cn (commonname[*]|$macro|*)|
# host (host[*]|$macro|*)|
# uri (uri[*]|$macro|*)|
# ip (serveraddr|$macro|*)|
# ip (serverip[*]|$macro|*) [port (serverport[*]|$macro|*)]|
# port (serverport[*]|$macro|*)|
# *)]
# [log ([[!]connect] [[!]master] [[!]cert]
# [[!]content] [[!]pcap] [[!]mirror] [$macro]|*|!*)]

@ -353,15 +353,17 @@ The syntax of filtering rules is as follows:
(Divert|Split|Pass|Block|Match)
([from (
user (username|$macro|*) [desc keyword]|
ip (clientaddr|$macro|*)|
user (username|$macro|*) [desc (keyword|$macro|*)]|
desc (keyword|$macro|*)|
ip (clientip|$macro|*)|
*)]
[to (
sni (servername[*]|$macro|*)|
cn (commonname[*]|$macro|*)|
host (host[*]|$macro|*)|
uri (uri[*]|$macro|*)|
ip (serveraddr|$macro|*)|
ip (serverip[*]|$macro|*) [port (serverport[*]|$macro|*)]|
port (serverport[*]|$macro|*)|
*)]
[log ([[!]connect] [[!]master] [[!]cert]
[[!]content] [[!]pcap] [[!]mirror] [$macro]|*|!*)]

@ -452,6 +452,27 @@ START_TEST(set_filter_rule_04)
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port *");
rv = opts_set_filter_rule(opts, "Divert", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port *");
rv = opts_set_filter_rule(opts, "Split", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port *");
rv = opts_set_filter_rule(opts, "Pass", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port *");
rv = opts_set_filter_rule(opts, "Block", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port *");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1");
rv = opts_set_filter_rule(opts, "Divert", s, 0);
fail_unless(rv == 0, "failed to parse rule");
@ -473,28 +494,96 @@ START_TEST(set_filter_rule_04)
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("$macro 192.168.0.1 192.168.0.2");
s = strdup("to ip 192.168.0.1 port *");
rv = opts_set_filter_rule(opts, "Divert", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1 port *");
rv = opts_set_filter_rule(opts, "Split", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1 port *");
rv = opts_set_filter_rule(opts, "Pass", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1 port *");
rv = opts_set_filter_rule(opts, "Block", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1 port *");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port 443");
rv = opts_set_filter_rule(opts, "Divert", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port 443");
rv = opts_set_filter_rule(opts, "Split", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port 443");
rv = opts_set_filter_rule(opts, "Pass", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port 443");
rv = opts_set_filter_rule(opts, "Block", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip * port 443");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1 port 443");
rv = opts_set_filter_rule(opts, "Divert", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1 port 443");
rv = opts_set_filter_rule(opts, "Split", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1 port 443");
rv = opts_set_filter_rule(opts, "Pass", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1 port 443");
rv = opts_set_filter_rule(opts, "Block", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("to ip 192.168.0.1 port 443");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("$macro1 192.168.0.1 192.168.0.2");
rv = opts_set_macro(opts, s, 0);
fail_unless(rv == 0, "failed to set macro");
free(s);
s = strdup("$macro2 443 444");
rv = opts_set_macro(opts, s, 0);
fail_unless(rv == 0, "failed to set macro");
free(s);
s = strdup("to ip $macro");
s = strdup("to ip $macro1 port $macro2");
rv = opts_set_filter_rule(opts, "Divert", s, 0);
fail_unless(rv == 1, "failed to parse rule");
free(s);
s = strdup("to ip $macro");
s = strdup("to ip $macro1 port $macro2");
rv = opts_set_filter_rule(opts, "Split", s, 0);
fail_unless(rv == 1, "failed to parse rule");
free(s);
s = strdup("to ip $macro");
s = strdup("to ip $macro1 port $macro2");
rv = opts_set_filter_rule(opts, "Pass", s, 0);
fail_unless(rv == 1, "failed to parse rule");
free(s);
s = strdup("to ip $macro");
s = strdup("to ip $macro1 port $macro2");
rv = opts_set_filter_rule(opts, "Block", s, 0);
fail_unless(rv == 1, "failed to parse rule");
free(s);
s = strdup("to ip $macro");
s = strdup("to ip $macro1 port $macro2");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 1, "failed to parse rule");
free(s);
@ -1270,12 +1359,12 @@ START_TEST(set_filter_rule_07)
s = filter_rule_str(opts->filter_rules);
fail_unless(!strcmp(s,
"filter rule 0: site=, substring, ip=, user=, keyword=, all=conns||sites, action=divert||||, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=0\n"
"filter rule 1: site=, substring, ip=, user=, keyword=, all=conns||sites, action=|split|||, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=0\n"
"filter rule 2: site=, substring, ip=, user=, keyword=, all=conns||sites, action=||pass||, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=0\n"
"filter rule 3: site=, substring, ip=, user=, keyword=, all=|users|sites, action=|||block|, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=1\n"
"filter rule 4: site=, substring, ip=, user=, keyword=desc, all=|users|sites, action=||||match, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=2\n"
"filter rule 5: site=, substring, ip=, user=, keyword=, all=conns||sites, action=||||match, log=connect|master|cert|content|pcap|mirror, apply to=dstip|sni|cn|host|uri, precedence=1"),
"filter rule 0: site=, substring, port=, , ip=, user=, keyword=, all=conns||sites|, action=divert||||, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=0\n"
"filter rule 1: site=, substring, port=, , ip=, user=, keyword=, all=conns||sites|, action=|split|||, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=0\n"
"filter rule 2: site=, substring, port=, , ip=, user=, keyword=, all=conns||sites|, action=||pass||, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=0\n"
"filter rule 3: site=, substring, port=, , ip=, user=, keyword=, all=|users|sites|, action=|||block|, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=1\n"
"filter rule 4: site=, substring, port=, , ip=, user=, keyword=desc, all=|users|sites|, action=||||match, log=|||||, apply to=dstip|sni|cn|host|uri, precedence=2\n"
"filter rule 5: site=, substring, port=, , ip=, user=, keyword=, all=conns||sites|, action=||||match, log=connect|master|cert|content|pcap|mirror, apply to=dstip|sni|cn|host|uri, precedence=1"),
"failed to parse rule: %s", s);
free(s);
@ -1347,7 +1436,7 @@ START_TEST(set_filter_rule_08)
fail_unless(rv == 0, "failed to parse rule");
free(s);
// Block action at precedence 2 is not applied to a site of the same rule at precedence 3 now
// Block action at precedence 1 is not applied to a site of the same rule at precedence 2 now
s = strdup("from ip 192.168.0.1 to ip 192.168.0.2");
rv = opts_set_filter_rule(opts, "Block", s, 0);
fail_unless(rv == 0, "failed to parse rule");
@ -1386,15 +1475,15 @@ START_TEST(set_filter_rule_08)
s = filter_rule_str(opts->filter_rules);
fail_unless(!strcmp(s,
"filter rule 0: site=192.168.0.2, exact, ip=192.168.0.1, user=, keyword=, all=||, action=divert||||, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 1: site=192.168.0.2, exact, ip=192.168.0.1, user=, keyword=, all=||, action=|split|||, log=connect|master|cert|content|pcap|mirror, apply to=dstip||||, precedence=3\n"
"filter rule 2: site=192.168.0.2, exact, ip=192.168.0.1, user=, keyword=, all=||, action=||pass||, log=!connect||!cert||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 3: site=192.168.0.2, exact, ip=192.168.0.1, user=, keyword=, all=||, action=|||block|, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 4: site=192.168.0.3, exact, ip=192.168.0.1, user=, keyword=, all=||, action=||||match, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 5: site=192.168.0.1, exact, ip=192.168.0.2, user=, keyword=, all=||, action=||||match, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 6: site=, substring, ip=192.168.0.2, user=, keyword=, all=||sites, action=||||match, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 7: site=192.168.0., substring, ip=192.168.0.2, user=, keyword=, all=||, action=||||match, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 8: site=192.168.0.3, exact, ip=192.168.0.2, user=, keyword=, all=||, action=||||match, log=|||||, apply to=dstip||||, precedence=2"),
"filter rule 0: site=192.168.0.2, exact, port=, , ip=192.168.0.1, user=, keyword=, all=|||, action=divert||||, log=|||||, apply to=dstip||||, precedence=1\n"
"filter rule 1: site=192.168.0.2, exact, port=, , ip=192.168.0.1, user=, keyword=, all=|||, action=|split|||, log=connect|master|cert|content|pcap|mirror, apply to=dstip||||, precedence=2\n"
"filter rule 2: site=192.168.0.2, exact, port=, , ip=192.168.0.1, user=, keyword=, all=|||, action=||pass||, log=!connect||!cert||!pcap|, apply to=dstip||||, precedence=2\n"
"filter rule 3: site=192.168.0.2, exact, port=, , ip=192.168.0.1, user=, keyword=, all=|||, action=|||block|, log=|||||, apply to=dstip||||, precedence=1\n"
"filter rule 4: site=192.168.0.3, exact, port=, , ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=|||||, apply to=dstip||||, precedence=1\n"
"filter rule 5: site=192.168.0.1, exact, port=, , ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=|||||, apply to=dstip||||, precedence=1\n"
"filter rule 6: site=, substring, port=, , ip=192.168.0.2, user=, keyword=, all=||sites|, action=||||match, log=|||||, apply to=dstip||||, precedence=1\n"
"filter rule 7: site=192.168.0., substring, port=, , ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=|||||, apply to=dstip||||, precedence=1\n"
"filter rule 8: site=192.168.0.3, exact, port=, , ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=|||||, apply to=dstip||||, precedence=1"),
"failed to parse rule: %s", s);
free(s);
@ -1414,18 +1503,18 @@ START_TEST(set_filter_rule_08)
"ip_filter->\n"
" ip 0 192.168.0.2= \n"
" ip: \n"
" 0: (all_sites, substring, action=||||match, log=|||||, precedence=2)\n"
" 1: 192.168.0.3 (exact, action=||||match, log=|||||, precedence=2)\n"
" 2: 192.168.0. (substring, action=||||match, log=|||||, precedence=2)\n"
" 3: 192.168.0.1 (exact, action=||||match, log=|||||, precedence=2)\n"
" 0: (all_sites, substring, action=||||match, log=|||||, precedence=1)\n"
" 1: 192.168.0.3 (exact, action=||||match, log=|||||, precedence=1)\n"
" 2: 192.168.0. (substring, action=||||match, log=|||||, precedence=1)\n"
" 3: 192.168.0.1 (exact, action=||||match, log=|||||, precedence=1)\n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
" ip 1 192.168.0.1= \n"
" ip: \n"
" 0: 192.168.0.3 (exact, action=||||match, log=|||||, precedence=2)\n"
" 1: 192.168.0.2 (exact, action=divert|split|pass||, log=!connect|master|!cert|content|!pcap|mirror, precedence=3)\n"
" 0: 192.168.0.3 (exact, action=||||match, log=|||||, precedence=1)\n"
" 1: 192.168.0.2 (exact, action=divert|split|pass||, log=!connect|master|!cert|content|!pcap|mirror, precedence=2)\n"
" sni: \n"
" cn: \n"
" host: \n"
@ -1448,6 +1537,135 @@ START_TEST(set_filter_rule_09)
int rv;
opts_t *opts = opts_new();
s = strdup("from ip 192.168.0.1 to ip 192.168.0.2 port 443");
rv = opts_set_filter_rule(opts, "Divert", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("from ip 192.168.0.1 to ip 192.168.0.2 port 443 log connect master cert content pcap mirror");
rv = opts_set_filter_rule(opts, "Split", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = strdup("from ip 192.168.0.1 to ip 192.168.0.2 port 443 log !connect !cert !pcap");
rv = opts_set_filter_rule(opts, "Pass", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
// Block action at precedence 2 is not applied to a port of the same rule at precedence 3 now
s = strdup("from ip 192.168.0.1 to ip 192.168.0.2 port 443");
rv = opts_set_filter_rule(opts, "Block", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
// Add another target, the following port rules should not change this site rule
s = strdup("from ip 192.168.0.1 to ip 192.168.0.3 log !mirror");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
// Add another target port
s = strdup("from ip 192.168.0.1 to ip 192.168.0.3 port 443");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
// Add another target port
s = strdup("from ip 192.168.0.1 to ip 192.168.0.3 port 80");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
// Add another source
s = strdup("from ip 192.168.0.2 to ip 192.168.0.1 port 443");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
// The order of sites does not match the order of rules, it is the reverse
// But all_sites should always be the first element
s = strdup("from ip 192.168.0.2 to ip 192.168.0.1 port *");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
// Search substring
s = strdup("from ip 192.168.0.2 to ip 192.168.0.1 port 80*");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 0, "failed to parse rule");
free(s);
s = filter_rule_str(opts->filter_rules);
fail_unless(!strcmp(s,
"filter rule 0: site=192.168.0.2, exact, port=443, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=divert||||, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 1: site=192.168.0.2, exact, port=443, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=|split|||, log=connect|master|cert|content|pcap|mirror, apply to=dstip||||, precedence=3\n"
"filter rule 2: site=192.168.0.2, exact, port=443, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||pass||, log=!connect||!cert||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 3: site=192.168.0.2, exact, port=443, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=|||block|, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 4: site=192.168.0.3, exact, port=, , ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=|||||!mirror, apply to=dstip||||, precedence=2\n"
"filter rule 5: site=192.168.0.3, exact, port=443, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 6: site=192.168.0.3, exact, port=80, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 7: site=192.168.0.1, exact, port=443, exact_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 8: site=192.168.0.1, exact, port=, substring_port, ip=192.168.0.2, user=, keyword=, all=|||ports, action=||||match, log=|||||, apply to=dstip||||, precedence=2\n"
"filter rule 9: site=192.168.0.1, exact, port=80, substring_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=|||||, apply to=dstip||||, precedence=2"),
"failed to parse rule: %s", s);
free(s);
opts->filter = opts_set_filter(opts->filter_rules);
s = filter_str(opts->filter);
fail_unless(!strcmp(s, "filter=>\n"
"userkeyword_filter->\n"
"user_filter->\n"
"keyword_filter->\n"
"all_user_filter->\n"
" ip: \n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
"ip_filter->\n"
" ip 0 192.168.0.2= \n"
" ip: \n"
" 0: 192.168.0.1 (exact, action=||||, log=|||||, precedence=0)\n"
" port:\n"
" 0: (all_ports, substring, action=||||match, log=|||||, precedence=2)\n"
" 1: 80 (substring, action=||||match, log=|||||, precedence=2)\n"
" 2: 443 (exact, action=||||match, log=|||||, precedence=2)\n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
" ip 1 192.168.0.1= \n"
" ip: \n"
" 0: 192.168.0.3 (exact, action=||||match, log=|||||!mirror, precedence=2)\n"
" port:\n"
" 0: 80 (exact, action=||||match, log=|||||, precedence=2)\n"
" 1: 443 (exact, action=||||match, log=|||||, precedence=2)\n"
" 1: 192.168.0.2 (exact, action=||||, log=|||||, precedence=0)\n"
" port:\n"
" 0: 443 (exact, action=divert|split|pass||, log=!connect|master|!cert|content|!pcap|mirror, precedence=3)\n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
"all_filter->\n"
" ip: \n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"), "failed to translate rule: %s", s);
free(s);
opts_free(opts);
}
END_TEST
START_TEST(set_filter_rule_10)
{
char *s;
int rv;
opts_t *opts = opts_new();
opts->user_auth = 1;
s = strdup("from user root to sni example.com");
@ -1504,15 +1722,15 @@ START_TEST(set_filter_rule_09)
s = filter_rule_str(opts->filter_rules);
fail_unless(!strcmp(s,
"filter rule 0: site=example.com, exact, ip=, user=root, keyword=, all=||, action=divert||||, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 1: site=example.com, exact, ip=, user=root, keyword=, all=||, action=|split|||, log=connect|master|cert|content|pcap|mirror, apply to=|sni|||, precedence=4\n"
"filter rule 2: site=example.com, exact, ip=, user=root, keyword=, all=||, action=||pass||, log=!connect||!cert||!pcap|, apply to=|sni|||, precedence=4\n"
"filter rule 3: site=example.com, exact, ip=, user=root, keyword=, all=||, action=|||block|, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 4: site=example2.com, exact, ip=, user=root, keyword=, all=||, action=||||match, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 5: site=example.com, exact, ip=, user=daemon, keyword=, all=||, action=||||match, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 6: site=, substring, ip=, user=daemon, keyword=, all=||sites, action=||||match, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 7: site=.example.com, substring, ip=, user=daemon, keyword=, all=||, action=||||match, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 8: site=example3.com, exact, ip=, user=daemon, keyword=, all=||, action=||||match, log=|||||, apply to=|sni|||, precedence=3"),
"filter rule 0: site=example.com, exact, port=, , ip=, user=root, keyword=, all=|||, action=divert||||, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 1: site=example.com, exact, port=, , ip=, user=root, keyword=, all=|||, action=|split|||, log=connect|master|cert|content|pcap|mirror, apply to=|sni|||, precedence=4\n"
"filter rule 2: site=example.com, exact, port=, , ip=, user=root, keyword=, all=|||, action=||pass||, log=!connect||!cert||!pcap|, apply to=|sni|||, precedence=4\n"
"filter rule 3: site=example.com, exact, port=, , ip=, user=root, keyword=, all=|||, action=|||block|, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 4: site=example2.com, exact, port=, , ip=, user=root, keyword=, all=|||, action=||||match, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 5: site=example.com, exact, port=, , ip=, user=daemon, keyword=, all=|||, action=||||match, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 6: site=, substring, port=, , ip=, user=daemon, keyword=, all=||sites|, action=||||match, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 7: site=.example.com, substring, port=, , ip=, user=daemon, keyword=, all=|||, action=||||match, log=|||||, apply to=|sni|||, precedence=3\n"
"filter rule 8: site=example3.com, exact, port=, , ip=, user=daemon, keyword=, all=|||, action=||||match, log=|||||, apply to=|sni|||, precedence=3"),
"failed to parse rule: %s", s);
free(s);
@ -1560,7 +1778,7 @@ START_TEST(set_filter_rule_09)
}
END_TEST
START_TEST(set_filter_rule_10)
START_TEST(set_filter_rule_11)
{
char *s;
int rv;
@ -1646,19 +1864,19 @@ START_TEST(set_filter_rule_10)
s = filter_rule_str(opts->filter_rules);
fail_unless(!strcmp(s,
"filter rule 0: site=example.com, exact, ip=, user=root, keyword=desc, all=||, action=divert||||, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 1: site=example.com, exact, ip=, user=root, keyword=desc, all=||, action=|split|||, log=connect|master|cert|content|pcap|mirror, apply to=||cn||, precedence=5\n"
"filter rule 2: site=example.com, exact, ip=, user=root, keyword=desc, all=||, action=||pass||, log=!connect||!cert||!pcap|, apply to=||cn||, precedence=5\n"
"filter rule 3: site=example.com, exact, ip=, user=root, keyword=desc, all=||, action=|||block|, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 4: site=example2.com, exact, ip=, user=root, keyword=desc, all=||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 5: site=example.com, exact, ip=, user=daemon, keyword=desc, all=||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 6: site=, substring, ip=, user=daemon, keyword=desc, all=||sites, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 7: site=.example.com, substring, ip=, user=daemon, keyword=desc, all=||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 8: site=example3.com, exact, ip=, user=daemon, keyword=desc, all=||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 9: site=example4.com, exact, ip=, user=daemon, keyword=desc2, all=||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 10: site=example5.com, exact, ip=, user=, keyword=desc, all=|users|, action=||||match, log=|||||, apply to=||cn||, precedence=3\n"
"filter rule 11: site=, substring, ip=, user=, keyword=desc, all=|users|sites, action=||||match, log=|||||, apply to=|||host|, precedence=3\n"
"filter rule 12: site=example6.com, exact, ip=, user=, keyword=desc3, all=|users|, action=||||match, log=|||||, apply to=||||uri, precedence=3"),
"filter rule 0: site=example.com, exact, port=, , ip=, user=root, keyword=desc, all=|||, action=divert||||, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 1: site=example.com, exact, port=, , ip=, user=root, keyword=desc, all=|||, action=|split|||, log=connect|master|cert|content|pcap|mirror, apply to=||cn||, precedence=5\n"
"filter rule 2: site=example.com, exact, port=, , ip=, user=root, keyword=desc, all=|||, action=||pass||, log=!connect||!cert||!pcap|, apply to=||cn||, precedence=5\n"
"filter rule 3: site=example.com, exact, port=, , ip=, user=root, keyword=desc, all=|||, action=|||block|, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 4: site=example2.com, exact, port=, , ip=, user=root, keyword=desc, all=|||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 5: site=example.com, exact, port=, , ip=, user=daemon, keyword=desc, all=|||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 6: site=, substring, port=, , ip=, user=daemon, keyword=desc, all=||sites|, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 7: site=.example.com, substring, port=, , ip=, user=daemon, keyword=desc, all=|||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 8: site=example3.com, exact, port=, , ip=, user=daemon, keyword=desc, all=|||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 9: site=example4.com, exact, port=, , ip=, user=daemon, keyword=desc2, all=|||, action=||||match, log=|||||, apply to=||cn||, precedence=4\n"
"filter rule 10: site=example5.com, exact, port=, , ip=, user=, keyword=desc, all=|users||, action=||||match, log=|||||, apply to=||cn||, precedence=3\n"
"filter rule 11: site=, substring, port=, , ip=, user=, keyword=desc, all=|users|sites|, action=||||match, log=|||||, apply to=|||host|, precedence=3\n"
"filter rule 12: site=example6.com, exact, port=, , ip=, user=, keyword=desc3, all=|users||, action=||||match, log=|||||, apply to=||||uri, precedence=3"),
"failed to parse rule: %s", s);
free(s);
@ -1695,34 +1913,100 @@ START_TEST(set_filter_rule_10)
" host: \n"
" uri: \n"
"user_filter->\n"
" user 0 daemon= \n"
"keyword_filter->\n"
" keyword 0 desc3= \n"
" ip: \n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
" user 1 root= \n"
" 0: example6.com (exact, action=||||match, log=|||||, precedence=3)\n"
" keyword 1 desc= \n"
" ip: \n"
" sni: \n"
" cn: \n"
" 0: example5.com (exact, action=||||match, log=|||||, precedence=3)\n"
" host: \n"
" 0: (all_sites, substring, action=||||match, log=|||||, precedence=3)\n"
" uri: \n"
"keyword_filter->\n"
" keyword 0 desc3= \n"
"all_user_filter->\n"
" ip: \n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
" 0: example6.com (exact, action=||||match, log=|||||, precedence=3)\n"
" keyword 1 desc= \n"
"ip_filter->\n"
"all_filter->\n"
" ip: \n"
" sni: \n"
" cn: \n"
" 0: example5.com (exact, action=||||match, log=|||||, precedence=3)\n"
" host: \n"
" 0: (all_sites, substring, action=||||match, log=|||||, precedence=3)\n"
" uri: \n"
" uri: \n"), "failed to translate rule: %s", s);
free(s);
opts_free(opts);
}
END_TEST
START_TEST(set_filter_rule_12)
{
char *s;
int rv;
opts_t *opts = opts_new();
s = strdup("$ips 192.168.0.1 192.168.0.2");
rv = opts_set_macro(opts, s, 0);
fail_unless(rv == 0, "failed to set macro");
free(s);
s = strdup("$dstips 192.168.0.3 192.168.0.4");
rv = opts_set_macro(opts, s, 0);
fail_unless(rv == 0, "failed to set macro");
free(s);
s = strdup("$ports 80 443");
rv = opts_set_macro(opts, s, 0);
fail_unless(rv == 0, "failed to set macro");
free(s);
s = strdup("$logs !master !pcap");
rv = opts_set_macro(opts, s, 0);
fail_unless(rv == 0, "failed to set macro");
free(s);
s = strdup("from ip $ips to ip $dstips port $ports log $logs");
rv = opts_set_filter_rule(opts, "Match", s, 0);
fail_unless(rv == 1, "failed to parse rule");
free(s);
s = filter_rule_str(opts->filter_rules);
fail_unless(!strcmp(s,
"filter rule 0: site=192.168.0.4, exact, port=443, exact_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=||||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 1: site=192.168.0.4, exact, port=443, exact_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=|!master||||, apply to=dstip||||, precedence=3\n"
"filter rule 2: site=192.168.0.4, exact, port=80, exact_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=||||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 3: site=192.168.0.4, exact, port=80, exact_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=|!master||||, apply to=dstip||||, precedence=3\n"
"filter rule 4: site=192.168.0.3, exact, port=443, exact_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=||||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 5: site=192.168.0.3, exact, port=443, exact_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=|!master||||, apply to=dstip||||, precedence=3\n"
"filter rule 6: site=192.168.0.3, exact, port=80, exact_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=||||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 7: site=192.168.0.3, exact, port=80, exact_port, ip=192.168.0.2, user=, keyword=, all=|||, action=||||match, log=|!master||||, apply to=dstip||||, precedence=3\n"
"filter rule 8: site=192.168.0.4, exact, port=443, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=||||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 9: site=192.168.0.4, exact, port=443, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=|!master||||, apply to=dstip||||, precedence=3\n"
"filter rule 10: site=192.168.0.4, exact, port=80, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=||||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 11: site=192.168.0.4, exact, port=80, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=|!master||||, apply to=dstip||||, precedence=3\n"
"filter rule 12: site=192.168.0.3, exact, port=443, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=||||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 13: site=192.168.0.3, exact, port=443, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=|!master||||, apply to=dstip||||, precedence=3\n"
"filter rule 14: site=192.168.0.3, exact, port=80, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=||||!pcap|, apply to=dstip||||, precedence=3\n"
"filter rule 15: site=192.168.0.3, exact, port=80, exact_port, ip=192.168.0.1, user=, keyword=, all=|||, action=||||match, log=|!master||||, apply to=dstip||||, precedence=3"),
"failed to parse rule: %s", s);
free(s);
opts->filter = opts_set_filter(opts->filter_rules);
s = filter_str(opts->filter);
fail_unless(!strcmp(s, "filter=>\n"
"userkeyword_filter->\n"
"user_filter->\n"
"keyword_filter->\n"
"all_user_filter->\n"
" ip: \n"
" sni: \n"
@ -1730,6 +2014,34 @@ START_TEST(set_filter_rule_10)
" host: \n"
" uri: \n"
"ip_filter->\n"
" ip 0 192.168.0.1= \n"
" ip: \n"
" 0: 192.168.0.3 (exact, action=||||, log=|||||, precedence=0)\n"
" port:\n"
" 0: 80 (exact, action=||||match, log=|!master|||!pcap|, precedence=3)\n"
" 1: 443 (exact, action=||||match, log=|!master|||!pcap|, precedence=3)\n"
" 1: 192.168.0.4 (exact, action=||||, log=|||||, precedence=0)\n"
" port:\n"
" 0: 80 (exact, action=||||match, log=|!master|||!pcap|, precedence=3)\n"
" 1: 443 (exact, action=||||match, log=|!master|||!pcap|, precedence=3)\n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
" ip 1 192.168.0.2= \n"
" ip: \n"
" 0: 192.168.0.3 (exact, action=||||, log=|||||, precedence=0)\n"
" port:\n"
" 0: 80 (exact, action=||||match, log=|!master|||!pcap|, precedence=3)\n"
" 1: 443 (exact, action=||||match, log=|!master|||!pcap|, precedence=3)\n"
" 1: 192.168.0.4 (exact, action=||||, log=|||||, precedence=0)\n"
" port:\n"
" 0: 80 (exact, action=||||match, log=|!master|||!pcap|, precedence=3)\n"
" 1: 443 (exact, action=||||match, log=|!master|||!pcap|, precedence=3)\n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
"all_filter->\n"
" ip: \n"
" sni: \n"
@ -1742,7 +2054,7 @@ START_TEST(set_filter_rule_10)
}
END_TEST
START_TEST(set_filter_rule_11)
START_TEST(set_filter_rule_13)
{
char *s;
int rv;
@ -1780,30 +2092,30 @@ START_TEST(set_filter_rule_11)
s = filter_rule_str(opts->filter_rules);
fail_unless(!strcmp(s,
"filter rule 0: site=site2, exact, ip=, user=daemon, keyword=desc2, all=||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 1: site=site2, exact, ip=, user=daemon, keyword=desc2, all=||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 2: site=site2, exact, ip=, user=daemon, keyword=desc2, all=||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 3: site=site1, exact, ip=, user=daemon, keyword=desc2, all=||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 4: site=site1, exact, ip=, user=daemon, keyword=desc2, all=||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 5: site=site1, exact, ip=, user=daemon, keyword=desc2, all=||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 6: site=site2, exact, ip=, user=daemon, keyword=desc1, all=||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 7: site=site2, exact, ip=, user=daemon, keyword=desc1, all=||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 8: site=site2, exact, ip=, user=daemon, keyword=desc1, all=||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 9: site=site1, exact, ip=, user=daemon, keyword=desc1, all=||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 10: site=site1, exact, ip=, user=daemon, keyword=desc1, all=||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 11: site=site1, exact, ip=, user=daemon, keyword=desc1, all=||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 12: site=site2, exact, ip=, user=root, keyword=desc2, all=||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 13: site=site2, exact, ip=, user=root, keyword=desc2, all=||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 14: site=site2, exact, ip=, user=root, keyword=desc2, all=||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 15: site=site1, exact, ip=, user=root, keyword=desc2, all=||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 16: site=site1, exact, ip=, user=root, keyword=desc2, all=||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 17: site=site1, exact, ip=, user=root, keyword=desc2, all=||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 18: site=site2, exact, ip=, user=root, keyword=desc1, all=||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 19: site=site2, exact, ip=, user=root, keyword=desc1, all=||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 20: site=site2, exact, ip=, user=root, keyword=desc1, all=||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 21: site=site1, exact, ip=, user=root, keyword=desc1, all=||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 22: site=site1, exact, ip=, user=root, keyword=desc1, all=||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 23: site=site1, exact, ip=, user=root, keyword=desc1, all=||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5"),
"filter rule 0: site=site2, exact, port=, , ip=, user=daemon, keyword=desc2, all=|||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 1: site=site2, exact, port=, , ip=, user=daemon, keyword=desc2, all=|||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 2: site=site2, exact, port=, , ip=, user=daemon, keyword=desc2, all=|||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 3: site=site1, exact, port=, , ip=, user=daemon, keyword=desc2, all=|||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 4: site=site1, exact, port=, , ip=, user=daemon, keyword=desc2, all=|||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 5: site=site1, exact, port=, , ip=, user=daemon, keyword=desc2, all=|||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 6: site=site2, exact, port=, , ip=, user=daemon, keyword=desc1, all=|||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 7: site=site2, exact, port=, , ip=, user=daemon, keyword=desc1, all=|||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 8: site=site2, exact, port=, , ip=, user=daemon, keyword=desc1, all=|||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 9: site=site1, exact, port=, , ip=, user=daemon, keyword=desc1, all=|||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 10: site=site1, exact, port=, , ip=, user=daemon, keyword=desc1, all=|||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 11: site=site1, exact, port=, , ip=, user=daemon, keyword=desc1, all=|||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 12: site=site2, exact, port=, , ip=, user=root, keyword=desc2, all=|||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 13: site=site2, exact, port=, , ip=, user=root, keyword=desc2, all=|||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 14: site=site2, exact, port=, , ip=, user=root, keyword=desc2, all=|||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 15: site=site1, exact, port=, , ip=, user=root, keyword=desc2, all=|||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 16: site=site1, exact, port=, , ip=, user=root, keyword=desc2, all=|||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 17: site=site1, exact, port=, , ip=, user=root, keyword=desc2, all=|||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 18: site=site2, exact, port=, , ip=, user=root, keyword=desc1, all=|||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 19: site=site2, exact, port=, , ip=, user=root, keyword=desc1, all=|||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 20: site=site2, exact, port=, , ip=, user=root, keyword=desc1, all=|||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5\n"
"filter rule 21: site=site1, exact, port=, , ip=, user=root, keyword=desc1, all=|||, action=||||match, log=|||||mirror, apply to=|sni|||, precedence=5\n"
"filter rule 22: site=site1, exact, port=, , ip=, user=root, keyword=desc1, all=|||, action=||||match, log=|||content||, apply to=|sni|||, precedence=5\n"
"filter rule 23: site=site1, exact, port=, , ip=, user=root, keyword=desc1, all=|||, action=||||match, log=connect|||||, apply to=|sni|||, precedence=5"),
"failed to parse rule: %s", s);
free(s);
@ -1847,18 +2159,6 @@ START_TEST(set_filter_rule_11)
" host: \n"
" uri: \n"
"user_filter->\n"
" user 0 root= \n"
" ip: \n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
" user 1 daemon= \n"
" ip: \n"
" sni: \n"
" cn: \n"
" host: \n"
" uri: \n"
"keyword_filter->\n"
"all_user_filter->\n"
" ip: \n"
@ -1898,6 +2198,8 @@ filter_suite(void)
tcase_add_test(tc, set_filter_rule_09);
tcase_add_test(tc, set_filter_rule_10);
tcase_add_test(tc, set_filter_rule_11);
tcase_add_test(tc, set_filter_rule_12);
tcase_add_test(tc, set_filter_rule_13);
suite_add_tcase(s, tc);
return s;

@ -649,7 +649,7 @@ START_TEST(opts_set_passsite_01)
ps = filter_rule_str(opts->filter_rules);
#ifndef WITHOUT_USERAUTH
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, ip=, user=, keyword=, all=conns||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=1"), "failed parsing passite example.com: %s", ps);
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, port=, , ip=, user=, keyword=, all=conns|||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=1"), "failed parsing passite example.com: %s", ps);
#else /* WITHOUT_USERAUTH */
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, ip=, all=conns|, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=1"), "failed parsing passite example.com: %s", ps);
#endif /* WITHOUT_USERAUTH */
@ -679,7 +679,7 @@ START_TEST(opts_set_passsite_02)
ps = filter_rule_str(opts->filter_rules);
#ifndef WITHOUT_USERAUTH
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, ip=192.168.0.1, user=, keyword=, all=||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=2"), "failed parsing passite example.com 192.168.0.1: %s", ps);
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, port=, , ip=192.168.0.1, user=, keyword=, all=|||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=2"), "failed parsing passite example.com 192.168.0.1: %s", ps);
#else /* WITHOUT_USERAUTH */
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, ip=192.168.0.1, all=|, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=2"), "failed parsing passite example.com 192.168.0.1: %s", ps);
#endif /* !WITHOUT_USERAUTH */
@ -709,7 +709,7 @@ START_TEST(opts_set_passsite_03)
fail_unless(!opts->filter_rules->next, "next set");
ps = filter_rule_str(opts->filter_rules);
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, ip=, user=root, keyword=, all=||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=3"), "failed parsing passite example.com root: %s", ps);
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, port=, , ip=, user=root, keyword=, all=|||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=3"), "failed parsing passite example.com root: %s", ps);
free(ps);
opts_free(opts);
@ -736,7 +736,7 @@ START_TEST(opts_set_passsite_04)
fail_unless(!opts->filter_rules->next, "next set");
ps = filter_rule_str(opts->filter_rules);
fail_unless(!strcmp(ps, "filter rule 0: site=*.google.com, exact, ip=, user=, keyword=android, all=|users|, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=3"), "failed parsing passite *.google.com * android: %s", ps);
fail_unless(!strcmp(ps, "filter rule 0: site=*.google.com, exact, port=, , ip=, user=, keyword=android, all=|users||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=3"), "failed parsing passite *.google.com * android: %s", ps);
free(ps);
opts_free(opts);
@ -791,11 +791,11 @@ START_TEST(opts_set_passsite_05)
fail_unless(opts->filter_rules->next->next->next, "next->next->next not set");
fail_unless(opts->filter_rules->next->next->next->next, "next->next->next->next not set");
fail_unless(!opts->filter_rules->next->next->next->next->next, "next->next->next->next->next set");
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, ip=, user=, keyword=, all=conns||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=1\n"
"filter rule 1: site=example.com, exact, ip=, user=, keyword=, all=|users|, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=2\n"
"filter rule 2: site=example.com, exact, ip=192.168.0.1, user=, keyword=, all=||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=2\n"
"filter rule 3: site=example.com, exact, ip=, user=root, keyword=, all=||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=3\n"
"filter rule 4: site=*.google.com, exact, ip=, user=, keyword=android, all=|users|, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=3"),
fail_unless(!strcmp(ps, "filter rule 0: site=example.com, exact, port=, , ip=, user=, keyword=, all=conns|||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=1\n"
"filter rule 1: site=example.com, exact, port=, , ip=, user=, keyword=, all=|users||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=2\n"
"filter rule 2: site=example.com, exact, port=, , ip=192.168.0.1, user=, keyword=, all=|||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=2\n"
"filter rule 3: site=example.com, exact, port=, , ip=, user=root, keyword=, all=|||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=3\n"
"filter rule 4: site=*.google.com, exact, port=, , ip=, user=, keyword=android, all=|users||, action=||pass||, log=|||||, apply to=|sni|cn||, precedence=3"),
"failed parsing multiple passites: %s", ps);
#else /* WITHOUT_USERAUTH */
fail_unless(!opts->filter_rules->next->next->next, "next->next->next set");

Loading…
Cancel
Save