[server] add stronger 'no -C' support for firewalld systems (issue #162)
This commit is contained in:
parent
72f03ae99c
commit
3c8e03d062
@ -59,28 +59,28 @@ zero_cmd_buffers(void)
|
|||||||
|
|
||||||
static int pid_status = 0;
|
static int pid_status = 0;
|
||||||
|
|
||||||
static void
|
|
||||||
chop_newline(char *str)
|
|
||||||
{
|
|
||||||
if(str[0] != 0x0 && str[strlen(str)-1] == 0x0a)
|
|
||||||
str[strlen(str)-1] = 0x0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rule_exists_no_chk_support(const fko_srv_options_t * const opts,
|
rule_exists_no_chk_support(const fko_srv_options_t * const opts,
|
||||||
const struct fw_chain * const fwc, const unsigned int proto,
|
const struct fw_chain * const fwc,
|
||||||
const char * const srcip, const char * const dstip,
|
const unsigned int proto,
|
||||||
const unsigned int port, const unsigned int exp_ts)
|
const char * const srcip,
|
||||||
|
const char * const dstip,
|
||||||
|
const unsigned int port,
|
||||||
|
const char * const natip,
|
||||||
|
const unsigned int nat_port,
|
||||||
|
const unsigned int exp_ts)
|
||||||
{
|
{
|
||||||
int rule_exists=0;
|
int rule_exists=0;
|
||||||
char cmd_buf[CMD_BUFSIZE] = {0};
|
char fw_line_buf[CMD_BUFSIZE] = {0};
|
||||||
char target_search[CMD_BUFSIZE] = {0};
|
char target_search[CMD_BUFSIZE] = {0};
|
||||||
char proto_search[CMD_BUFSIZE] = {0};
|
char proto_search[CMD_BUFSIZE] = {0};
|
||||||
char srcip_search[CMD_BUFSIZE] = {0};
|
char srcip_search[CMD_BUFSIZE] = {0};
|
||||||
char dstip_search[CMD_BUFSIZE] = {0};
|
char dstip_search[CMD_BUFSIZE] = {0};
|
||||||
char port_search[CMD_BUFSIZE] = {0};
|
char natip_search[CMD_BUFSIZE] = {0};
|
||||||
char exp_ts_search[CMD_BUFSIZE] = {0};
|
char port_search[CMD_BUFSIZE] = {0};
|
||||||
|
char nat_port_search[CMD_BUFSIZE] = {0};
|
||||||
|
char exp_ts_search[CMD_BUFSIZE] = {0};
|
||||||
|
char *ndx = NULL;
|
||||||
|
|
||||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_LIST_RULES_ARGS,
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_LIST_RULES_ARGS,
|
||||||
opts->fw_config->fw_command,
|
opts->fw_config->fw_command,
|
||||||
@ -108,30 +108,75 @@ rule_exists_no_chk_support(const fko_srv_options_t * const opts,
|
|||||||
else
|
else
|
||||||
snprintf(proto_search, CMD_BUFSIZE-1, " %u ", proto);
|
snprintf(proto_search, CMD_BUFSIZE-1, " %u ", proto);
|
||||||
|
|
||||||
snprintf(port_search, CMD_BUFSIZE-1, ":%u ", port);
|
snprintf(port_search, CMD_BUFSIZE-1, "dpt:%u ", port);
|
||||||
|
snprintf(nat_port_search, CMD_BUFSIZE-1, ":%u", nat_port);
|
||||||
snprintf(target_search, CMD_BUFSIZE-1, " %s ", fwc->target);
|
snprintf(target_search, CMD_BUFSIZE-1, " %s ", fwc->target);
|
||||||
snprintf(srcip_search, CMD_BUFSIZE-1, " %s ", srcip);
|
|
||||||
|
if (srcip != NULL)
|
||||||
|
snprintf(srcip_search, CMD_BUFSIZE-1, " %s ", srcip);
|
||||||
|
|
||||||
if (dstip != NULL)
|
if (dstip != NULL)
|
||||||
{
|
|
||||||
snprintf(dstip_search, CMD_BUFSIZE-1, " %s ", dstip);
|
snprintf(dstip_search, CMD_BUFSIZE-1, " %s ", dstip);
|
||||||
}
|
|
||||||
|
if (natip != NULL)
|
||||||
|
snprintf(natip_search, CMD_BUFSIZE-1, " to:%s ", natip);
|
||||||
|
|
||||||
snprintf(exp_ts_search, CMD_BUFSIZE-1, "%u ", exp_ts);
|
snprintf(exp_ts_search, CMD_BUFSIZE-1, "%u ", exp_ts);
|
||||||
|
|
||||||
/* search for each of the substrings - yes, matches from different
|
/* search for each of the substrings - the rule expiration time is the
|
||||||
* rules may get triggered here, but the expiration time is the
|
|
||||||
* primary search method
|
* primary search method
|
||||||
*/
|
*/
|
||||||
if(search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, exp_ts_search, &pid_status, opts)
|
if(search_extcmd_getline(cmd_buf, fw_line_buf,
|
||||||
&& search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, proto_search, &pid_status, opts)
|
CMD_BUFSIZE, NO_TIMEOUT, exp_ts_search, &pid_status, opts))
|
||||||
&& search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, srcip_search, &pid_status, opts)
|
{
|
||||||
&& (dstip == NULL) ? 1 : search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, dstip_search, &pid_status, opts)
|
chop_newline(fw_line_buf);
|
||||||
&& search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, target_search, &pid_status, opts)
|
/* we have an iptables policy rule that matches the
|
||||||
&& search_extcmd(cmd_buf, WANT_STDERR, NO_TIMEOUT, port_search, &pid_status, opts))
|
* expiration time, so make sure this rule matches the
|
||||||
rule_exists = 1;
|
* other fields too. If not, then it is for different
|
||||||
|
* access requested by a separate SPA packet.
|
||||||
|
*/
|
||||||
|
if(((proto == ANY_PROTO) ? 1 : (strstr(fw_line_buf, proto_search) != NULL))
|
||||||
|
&& ((srcip == NULL) ? 1 : (strstr(fw_line_buf, srcip_search) != NULL))
|
||||||
|
&& ((dstip == NULL) ? 1 : (strstr(fw_line_buf, dstip_search) != NULL))
|
||||||
|
&& ((natip == NULL) ? 1 : (strstr(fw_line_buf, natip_search) != NULL))
|
||||||
|
&& (strstr(fw_line_buf, target_search) != NULL)
|
||||||
|
&& ((port == ANY_PORT) ? 1 : (strstr(fw_line_buf, port_search) != NULL)))
|
||||||
|
{
|
||||||
|
rule_exists = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is a nat port, we have to qualify it as part
|
||||||
|
* of the 'to:<ip>:<port>' portion of the rule (at the end)
|
||||||
|
*/
|
||||||
|
if(rule_exists && nat_port != NAT_ANY_PORT)
|
||||||
|
{
|
||||||
|
ndx = strstr(fw_line_buf, " to:");
|
||||||
|
/* Make sure there isn't a duplicate " to:" string (i.e. if someone
|
||||||
|
* was trying to be tricky with the iptables comment match).
|
||||||
|
*/
|
||||||
|
if(ndx != NULL && (strstr((ndx+strlen(" to:")), " to:") == NULL))
|
||||||
|
{
|
||||||
|
ndx = strstr((ndx+strlen(" to:")), nat_port_search);
|
||||||
|
if (ndx == NULL)
|
||||||
|
{
|
||||||
|
rule_exists = 0;
|
||||||
|
}
|
||||||
|
else if((*(ndx+strlen(nat_port_search)) != '\0')
|
||||||
|
&& (*(ndx+strlen(nat_port_search)) != ' '))
|
||||||
|
{
|
||||||
|
rule_exists = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rule_exists = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(rule_exists)
|
if(rule_exists)
|
||||||
log_msg(LOG_DEBUG,
|
log_msg(LOG_DEBUG,
|
||||||
"rule_exists_no_chk_support() %s %u -> %s expires: %u rule (already exists",
|
"rule_exists_no_chk_support() %s %u -> %s expires: %u rule already exists",
|
||||||
proto_search, port, srcip, exp_ts);
|
proto_search, port, srcip, exp_ts);
|
||||||
else
|
else
|
||||||
log_msg(LOG_DEBUG,
|
log_msg(LOG_DEBUG,
|
||||||
@ -157,18 +202,21 @@ rule_exists_chk_support(const fko_srv_options_t * const opts,
|
|||||||
WANT_STDERR, NO_TIMEOUT, &pid_status, opts);
|
WANT_STDERR, NO_TIMEOUT, &pid_status, opts);
|
||||||
chop_newline(err_buf);
|
chop_newline(err_buf);
|
||||||
|
|
||||||
log_msg(LOG_DEBUG, "rule_exists_chk_support() CMD: '%s' (res: %d, err: %s)",
|
log_msg(LOG_DEBUG,
|
||||||
cmd_buf, res, err_buf);
|
"rule_exists_chk_support() CMD: '%s' (res: %d, err: %s)",
|
||||||
|
cmd_buf, res, err_buf);
|
||||||
|
|
||||||
if(strncmp(err_buf, "success", strlen("success")) == 0)
|
if(strncmp(err_buf, "success", strlen("success")) == 0)
|
||||||
{
|
{
|
||||||
rule_exists = 1;
|
rule_exists = 1;
|
||||||
log_msg(LOG_DEBUG, "rule_exists_chk_support() Rule : '%s' in %s already exists",
|
log_msg(LOG_DEBUG,
|
||||||
|
"rule_exists_chk_support() Rule : '%s' in %s already exists",
|
||||||
rule, chain);
|
rule, chain);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_msg(LOG_DEBUG, "rule_exists_chk_support() Rule : '%s' in %s does not exist",
|
log_msg(LOG_DEBUG,
|
||||||
|
"rule_exists_chk_support() Rule : '%s' in %s does not exist",
|
||||||
rule, chain);
|
rule, chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,9 +225,14 @@ rule_exists_chk_support(const fko_srv_options_t * const opts,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
rule_exists(const fko_srv_options_t * const opts,
|
rule_exists(const fko_srv_options_t * const opts,
|
||||||
const struct fw_chain * const fwc, const char * const rule,
|
const struct fw_chain * const fwc,
|
||||||
const unsigned int proto, const char * const srcip,
|
const char * const rule,
|
||||||
const char * const dstip, const unsigned int port,
|
const unsigned int proto,
|
||||||
|
const char * const srcip,
|
||||||
|
const char * const dstip,
|
||||||
|
const unsigned int port,
|
||||||
|
const char * const nat_ip,
|
||||||
|
const unsigned int nat_port,
|
||||||
const unsigned int exp_ts)
|
const unsigned int exp_ts)
|
||||||
{
|
{
|
||||||
int rule_exists = 0;
|
int rule_exists = 0;
|
||||||
@ -187,7 +240,9 @@ rule_exists(const fko_srv_options_t * const opts,
|
|||||||
if(have_firewd_chk_support == 1)
|
if(have_firewd_chk_support == 1)
|
||||||
rule_exists = rule_exists_chk_support(opts, fwc->to_chain, rule);
|
rule_exists = rule_exists_chk_support(opts, fwc->to_chain, rule);
|
||||||
else
|
else
|
||||||
rule_exists = rule_exists_no_chk_support(opts, fwc, proto, srcip, (opts->fw_config->use_destination ? dstip : NULL), port, exp_ts);
|
rule_exists = rule_exists_no_chk_support(opts, fwc, proto, srcip,
|
||||||
|
(opts->fw_config->use_destination ? dstip : NULL), port,
|
||||||
|
nat_ip, nat_port, exp_ts);
|
||||||
|
|
||||||
if(rule_exists == 1)
|
if(rule_exists == 1)
|
||||||
log_msg(LOG_DEBUG, "rule_exists() Rule : '%s' in %s already exists",
|
log_msg(LOG_DEBUG, "rule_exists() Rule : '%s' in %s already exists",
|
||||||
@ -429,10 +484,10 @@ jump_rule_exists_chk_support(const fko_srv_options_t * const opts, const int cha
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
jump_rule_exists_no_chk_support(const fko_srv_options_t * const opts, const int chain_num)
|
jump_rule_exists_no_chk_support(const fko_srv_options_t * const opts,
|
||||||
|
const int chain_num)
|
||||||
{
|
{
|
||||||
int exists = 0;
|
int exists = 0;
|
||||||
char cmd_buf[CMD_BUFSIZE] = {0};
|
|
||||||
char chain_search[CMD_BUFSIZE] = {0};
|
char chain_search[CMD_BUFSIZE] = {0};
|
||||||
|
|
||||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_LIST_RULES_ARGS,
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_LIST_RULES_ARGS,
|
||||||
@ -880,6 +935,14 @@ fw_initialize(const fko_srv_options_t * const opts)
|
|||||||
{
|
{
|
||||||
int res = 1;
|
int res = 1;
|
||||||
|
|
||||||
|
/* See if firewalld offers the '-C' argument (older versions don't). If not,
|
||||||
|
* then switch to parsing firewalld -L output to find rules.
|
||||||
|
*/
|
||||||
|
if(opts->firewd_disable_check_support)
|
||||||
|
have_firewd_chk_support = 0;
|
||||||
|
else
|
||||||
|
firewd_chk_support(opts);
|
||||||
|
|
||||||
/* Flush the chains (just in case) so we can start fresh.
|
/* Flush the chains (just in case) so we can start fresh.
|
||||||
*/
|
*/
|
||||||
if(strncasecmp(opts->config[CONF_FLUSH_FIREWD_AT_INIT], "Y", 1) == 0)
|
if(strncasecmp(opts->config[CONF_FLUSH_FIREWD_AT_INIT], "Y", 1) == 0)
|
||||||
@ -909,14 +972,6 @@ fw_initialize(const fko_srv_options_t * const opts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if firewalld offers the '-C' argument (older versions don't). If not,
|
|
||||||
* then switch to parsing firewalld -L output to find rules.
|
|
||||||
*/
|
|
||||||
if(opts->firewd_disable_check_support)
|
|
||||||
have_firewd_chk_support = 0;
|
|
||||||
else
|
|
||||||
firewd_chk_support(opts);
|
|
||||||
|
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -963,11 +1018,17 @@ static void
|
|||||||
firewd_rule(const fko_srv_options_t * const opts,
|
firewd_rule(const fko_srv_options_t * const opts,
|
||||||
const char * const complete_rule_buf,
|
const char * const complete_rule_buf,
|
||||||
const char * const fw_rule_macro,
|
const char * const fw_rule_macro,
|
||||||
const char * const srcip, const char * const dstip,
|
const char * const srcip,
|
||||||
const unsigned int proto, const unsigned int port,
|
const char * const dstip,
|
||||||
|
const unsigned int proto,
|
||||||
|
const unsigned int port,
|
||||||
|
const char * const nat_ip,
|
||||||
|
const unsigned int nat_port,
|
||||||
struct fw_chain * const chain,
|
struct fw_chain * const chain,
|
||||||
const unsigned int exp_ts, const time_t now,
|
const unsigned int exp_ts,
|
||||||
const char * const msg, const char * const access_msg)
|
const time_t now,
|
||||||
|
const char * const msg,
|
||||||
|
const char * const access_msg)
|
||||||
{
|
{
|
||||||
char rule_buf[CMD_BUFSIZE] = {0};
|
char rule_buf[CMD_BUFSIZE] = {0};
|
||||||
|
|
||||||
@ -994,8 +1055,8 @@ firewd_rule(const fko_srv_options_t * const opts,
|
|||||||
*/
|
*/
|
||||||
mk_chain(opts, chain->type);
|
mk_chain(opts, chain->type);
|
||||||
|
|
||||||
if(rule_exists(opts, chain, rule_buf,
|
if(rule_exists(opts, chain, rule_buf, proto, srcip,
|
||||||
proto, srcip, dstip, port, exp_ts) == 0)
|
dstip, port, nat_ip, nat_port, exp_ts) == 0)
|
||||||
{
|
{
|
||||||
if(create_rule(opts, chain->to_chain, rule_buf))
|
if(create_rule(opts, chain->to_chain, rule_buf))
|
||||||
{
|
{
|
||||||
@ -1048,17 +1109,16 @@ static void forward_access_rule(const fko_srv_options_t * const opts,
|
|||||||
/* Make a global ACCEPT rule for all ports/protocols
|
/* Make a global ACCEPT rule for all ports/protocols
|
||||||
*/
|
*/
|
||||||
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
||||||
NULL, ANY_PROTO, ANY_PORT, fwd_chain, exp_ts, now,
|
NULL, ANY_PROTO, ANY_PORT, NULL, NAT_ANY_PORT,
|
||||||
"FORWARD ALL", "*/*");
|
fwd_chain, exp_ts, now, "FORWARD ALL", "*/*");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Make the FORWARD access rule
|
/* Make the FORWARD access rule
|
||||||
*/
|
*/
|
||||||
firewd_rule(opts, NULL, FIREWD_FWD_RULE_ARGS, spadat->use_src_ip,
|
firewd_rule(opts, NULL, FIREWD_FWD_RULE_ARGS, spadat->use_src_ip,
|
||||||
nat_ip, fst_proto, nat_port, fwd_chain, exp_ts, now,
|
nat_ip, fst_proto, nat_port, NULL, NAT_ANY_PORT,
|
||||||
"FORWARD", spadat->spa_message_remain);
|
fwd_chain, exp_ts, now, "FORWARD", spadat->spa_message_remain);
|
||||||
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1095,8 +1155,8 @@ static void dnat_rule(const fko_srv_options_t * const opts,
|
|||||||
/* Make a global DNAT rule for all ports/protocols
|
/* Make a global DNAT rule for all ports/protocols
|
||||||
*/
|
*/
|
||||||
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
||||||
NULL, ANY_PROTO, ANY_PORT, dnat_chain, exp_ts, now,
|
NULL, ANY_PROTO, ANY_PORT, NULL, NAT_ANY_PORT,
|
||||||
"DNAT ALL", "*/*");
|
dnat_chain, exp_ts, now, "DNAT ALL", "*/*");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1116,8 +1176,8 @@ static void dnat_rule(const fko_srv_options_t * const opts,
|
|||||||
|
|
||||||
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
||||||
(fwc.use_destination ? spadat->pkt_destination_ip : FIREWD_ANY_IP),
|
(fwc.use_destination ? spadat->pkt_destination_ip : FIREWD_ANY_IP),
|
||||||
fst_proto, fst_port, dnat_chain, exp_ts, now, "DNAT",
|
fst_proto, fst_port, nat_ip, nat_port, dnat_chain, exp_ts, now,
|
||||||
spadat->spa_message_remain);
|
"DNAT", spadat->spa_message_remain);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1177,8 +1237,8 @@ static void snat_rule(const fko_srv_options_t * const opts,
|
|||||||
);
|
);
|
||||||
|
|
||||||
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
||||||
NULL, ANY_PROTO, ANY_PORT, snat_chain, exp_ts, now,
|
NULL, ANY_PROTO, ANY_PORT, NULL, NAT_ANY_PORT,
|
||||||
"SNAT ALL", "*/*");
|
snat_chain, exp_ts, now, "SNAT ALL", "*/*");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1228,7 +1288,8 @@ static void snat_rule(const fko_srv_options_t * const opts,
|
|||||||
);
|
);
|
||||||
|
|
||||||
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
firewd_rule(opts, rule_buf, NULL, spadat->use_src_ip,
|
||||||
NULL, fst_proto, nat_port, snat_chain, exp_ts, now, "SNAT",
|
NULL, fst_proto, nat_port, nat_ip, nat_port,
|
||||||
|
snat_chain, exp_ts, now, "SNAT",
|
||||||
spadat->spa_message_remain);
|
spadat->spa_message_remain);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -1329,8 +1390,8 @@ process_spa_request(const fko_srv_options_t * const opts,
|
|||||||
{
|
{
|
||||||
firewd_rule(opts, NULL, FIREWD_RULE_ARGS, spadat->use_src_ip,
|
firewd_rule(opts, NULL, FIREWD_RULE_ARGS, spadat->use_src_ip,
|
||||||
(fwc.use_destination ? spadat->pkt_destination_ip : FIREWD_ANY_IP),
|
(fwc.use_destination ? spadat->pkt_destination_ip : FIREWD_ANY_IP),
|
||||||
fst_proto, nat_port, in_chain, exp_ts, now, "local NAT",
|
fst_proto, nat_port, nat_ip, nat_port, in_chain, exp_ts,
|
||||||
spadat->spa_message_remain);
|
now, "local NAT", spadat->spa_message_remain);
|
||||||
}
|
}
|
||||||
else if(strlen(fwd_chain->to_chain))
|
else if(strlen(fwd_chain->to_chain))
|
||||||
{
|
{
|
||||||
@ -1360,8 +1421,8 @@ process_spa_request(const fko_srv_options_t * const opts,
|
|||||||
{
|
{
|
||||||
firewd_rule(opts, NULL, FIREWD_RULE_ARGS, spadat->use_src_ip,
|
firewd_rule(opts, NULL, FIREWD_RULE_ARGS, spadat->use_src_ip,
|
||||||
(fwc.use_destination ? spadat->pkt_destination_ip : FIREWD_ANY_IP),
|
(fwc.use_destination ? spadat->pkt_destination_ip : FIREWD_ANY_IP),
|
||||||
ple->proto, ple->port, in_chain, exp_ts, now, "access",
|
ple->proto, ple->port, NULL, NAT_ANY_PORT,
|
||||||
spadat->spa_message_remain);
|
in_chain, exp_ts, now, "access", spadat->spa_message_remain);
|
||||||
|
|
||||||
/* We need to make a corresponding OUTPUT rule if out_chain target
|
/* We need to make a corresponding OUTPUT rule if out_chain target
|
||||||
* is not NULL.
|
* is not NULL.
|
||||||
@ -1370,8 +1431,8 @@ process_spa_request(const fko_srv_options_t * const opts,
|
|||||||
{
|
{
|
||||||
firewd_rule(opts, NULL, FIREWD_OUT_RULE_ARGS, spadat->use_src_ip,
|
firewd_rule(opts, NULL, FIREWD_OUT_RULE_ARGS, spadat->use_src_ip,
|
||||||
(fwc.use_destination ? spadat->pkt_destination_ip : FIREWD_ANY_IP),
|
(fwc.use_destination ? spadat->pkt_destination_ip : FIREWD_ANY_IP),
|
||||||
ple->proto, ple->port, out_chain, exp_ts, now, "OUTPUT",
|
ple->proto, ple->port, NULL, NAT_ANY_PORT,
|
||||||
spadat->spa_message_remain);
|
out_chain, exp_ts, now, "OUTPUT", spadat->spa_message_remain);
|
||||||
}
|
}
|
||||||
ple = ple->next;
|
ple = ple->next;
|
||||||
}
|
}
|
||||||
@ -1384,18 +1445,152 @@ process_spa_request(const fko_srv_options_t * const opts,
|
|||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rm_expired_rules(const fko_srv_options_t * const opts,
|
||||||
|
const char * const fw_output_buf,
|
||||||
|
char *ndx, struct fw_chain *ch, int cpos, time_t now)
|
||||||
|
{
|
||||||
|
char exp_str[12] = {0};
|
||||||
|
char rule_num_str[6] = {0};
|
||||||
|
char *rn_start, *rn_end, *tmp_mark;
|
||||||
|
|
||||||
|
int res, is_err, rn_offset=0, rule_num;
|
||||||
|
time_t rule_exp, min_exp = 0;
|
||||||
|
|
||||||
|
/* walk the list and process rules as needed.
|
||||||
|
*/
|
||||||
|
while (ndx != NULL) {
|
||||||
|
/* Jump forward and extract the timestamp
|
||||||
|
*/
|
||||||
|
ndx += strlen(EXPIRE_COMMENT_PREFIX);
|
||||||
|
|
||||||
|
/* remember this spot for when we look for the next
|
||||||
|
* rule.
|
||||||
|
*/
|
||||||
|
tmp_mark = ndx;
|
||||||
|
|
||||||
|
strlcpy(exp_str, ndx, sizeof(exp_str));
|
||||||
|
rule_exp = (time_t)atoll(exp_str);
|
||||||
|
|
||||||
|
if(rule_exp <= now)
|
||||||
|
{
|
||||||
|
/* Backtrack and get the rule number and delete it.
|
||||||
|
*/
|
||||||
|
rn_start = ndx;
|
||||||
|
while(--rn_start > fw_output_buf)
|
||||||
|
{
|
||||||
|
if(*rn_start == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*rn_start != '\n')
|
||||||
|
{
|
||||||
|
/* This should not happen. But if it does, complain,
|
||||||
|
* decrement the active rule value, and go on.
|
||||||
|
*/
|
||||||
|
log_msg(LOG_ERR,
|
||||||
|
"Rule parse error while finding rule line start in chain %i",
|
||||||
|
cpos);
|
||||||
|
|
||||||
|
if (ch[cpos].active_rules > 0)
|
||||||
|
ch[cpos].active_rules--;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rn_start++;
|
||||||
|
|
||||||
|
rn_end = strchr(rn_start, ' ');
|
||||||
|
if(rn_end == NULL)
|
||||||
|
{
|
||||||
|
/* This should not happen. But if it does, complain,
|
||||||
|
* decrement the active rule value, and go on.
|
||||||
|
*/
|
||||||
|
log_msg(LOG_ERR,
|
||||||
|
"Rule parse error while finding rule number in chain %i",
|
||||||
|
cpos);
|
||||||
|
|
||||||
|
if (ch[cpos].active_rules > 0)
|
||||||
|
ch[cpos].active_rules--;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(rule_num_str, rn_start, (rn_end - rn_start)+1);
|
||||||
|
|
||||||
|
rule_num = strtol_wrapper(rule_num_str, rn_offset, RCHK_MAX_FIREWD_RULE_NUM,
|
||||||
|
NO_EXIT_UPON_ERR, &is_err);
|
||||||
|
if(is_err != FKO_SUCCESS)
|
||||||
|
{
|
||||||
|
log_msg(LOG_ERR,
|
||||||
|
"Rule parse error while finding rule number in chain %i",
|
||||||
|
cpos);
|
||||||
|
|
||||||
|
if (ch[cpos].active_rules > 0)
|
||||||
|
ch[cpos].active_rules--;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
zero_cmd_buffers();
|
||||||
|
|
||||||
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_DEL_RULE_ARGS,
|
||||||
|
opts->fw_config->fw_command,
|
||||||
|
ch[cpos].table,
|
||||||
|
ch[cpos].to_chain,
|
||||||
|
rule_num - rn_offset /* account for position of previously
|
||||||
|
deleted rule with rn_offset */
|
||||||
|
);
|
||||||
|
|
||||||
|
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE,
|
||||||
|
WANT_STDERR, NO_TIMEOUT, &pid_status, opts);
|
||||||
|
chop_newline(err_buf);
|
||||||
|
|
||||||
|
log_msg(LOG_DEBUG, "check_firewall_rules() CMD: '%s' (res: %d, err: %s)",
|
||||||
|
cmd_buf, res, err_buf);
|
||||||
|
|
||||||
|
if(EXTCMD_IS_SUCCESS(res))
|
||||||
|
{
|
||||||
|
log_msg(LOG_INFO, "Removed rule %s from %s with expire time of %u",
|
||||||
|
rule_num_str, ch[cpos].to_chain, rule_exp
|
||||||
|
);
|
||||||
|
|
||||||
|
rn_offset++;
|
||||||
|
|
||||||
|
if (ch[cpos].active_rules > 0)
|
||||||
|
ch[cpos].active_rules--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Track the minimum future rule expire time.
|
||||||
|
*/
|
||||||
|
if(rule_exp > now)
|
||||||
|
min_exp = (min_exp < rule_exp) ? min_exp : rule_exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Push our tracking index forward beyond (just processed) _exp_
|
||||||
|
* string so we can continue to the next rule in the list.
|
||||||
|
*/
|
||||||
|
ndx = strstr(tmp_mark, EXPIRE_COMMENT_PREFIX);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Iterate over the configure firewall access chains and purge expired
|
/* Iterate over the configure firewall access chains and purge expired
|
||||||
* firewall rules.
|
* firewall rules.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
check_firewall_rules(const fko_srv_options_t * const opts)
|
check_firewall_rules(const fko_srv_options_t * const opts,
|
||||||
|
const int chk_rm_all)
|
||||||
{
|
{
|
||||||
char exp_str[12] = {0};
|
char *ndx;
|
||||||
char rule_num_str[6] = {0};
|
char fw_output_buf[STANDARD_CMD_OUT_BUFSIZE] = {0};
|
||||||
char *ndx, *rn_start, *rn_end, *tmp_mark;
|
|
||||||
|
|
||||||
int i, res, rn_offset, rule_num, is_err;
|
int i, res;
|
||||||
time_t now, rule_exp, min_exp = 0;
|
time_t now, min_exp = 0;
|
||||||
|
|
||||||
struct fw_chain *ch = opts->fw_config->chain;
|
struct fw_chain *ch = opts->fw_config->chain;
|
||||||
|
|
||||||
@ -1408,15 +1603,21 @@ check_firewall_rules(const fko_srv_options_t * const opts)
|
|||||||
/* If there are no active rules or we have not yet
|
/* If there are no active rules or we have not yet
|
||||||
* reached our expected next expire time, continue.
|
* reached our expected next expire time, continue.
|
||||||
*/
|
*/
|
||||||
if(ch[i].active_rules == 0 || ch[i].next_expire > now)
|
if(!chk_rm_all && (ch[i].active_rules == 0 || ch[i].next_expire > now))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(ch[i].table[0] == '\0' || ch[i].to_chain[i] == '\0')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
zero_cmd_buffers();
|
zero_cmd_buffers();
|
||||||
|
memset(fw_output_buf, 0x0, STANDARD_CMD_OUT_BUFSIZE);
|
||||||
|
|
||||||
rn_offset = 0;
|
/* Get the current list of rules for this chain and delete
|
||||||
|
* any that have expired. Note that chk_rm_all puts us in
|
||||||
/* There should be a rule to delete. Get the current list of
|
* garbage collection mode, and allows any rules that have
|
||||||
* rules for this chain and delete the ones that are expired.
|
* been manually added (potentially by a program separate
|
||||||
|
* from fwknopd) to take advantage of fwknopd's timeout
|
||||||
|
* mechanism.
|
||||||
*/
|
*/
|
||||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_LIST_RULES_ARGS,
|
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_LIST_RULES_ARGS,
|
||||||
opts->fw_config->fw_command,
|
opts->fw_config->fw_command,
|
||||||
@ -1424,27 +1625,30 @@ check_firewall_rules(const fko_srv_options_t * const opts)
|
|||||||
ch[i].to_chain
|
ch[i].to_chain
|
||||||
);
|
);
|
||||||
|
|
||||||
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE,
|
res = run_extcmd(cmd_buf, fw_output_buf, STANDARD_CMD_OUT_BUFSIZE,
|
||||||
WANT_STDERR, NO_TIMEOUT, &pid_status, opts);
|
WANT_STDERR, NO_TIMEOUT, &pid_status, opts);
|
||||||
chop_newline(cmd_out);
|
chop_newline(fw_output_buf);
|
||||||
|
|
||||||
log_msg(LOG_DEBUG, "check_firewall_rules() CMD: '%s' (res: %d, cmd_out: %s)",
|
log_msg(LOG_DEBUG,
|
||||||
cmd_buf, res, cmd_out);
|
"check_firewall_rules() CMD: '%s' (res: %d, fw_output_buf: %s)",
|
||||||
|
cmd_buf, res, fw_output_buf);
|
||||||
|
|
||||||
if(!EXTCMD_IS_SUCCESS(res))
|
if(!EXTCMD_IS_SUCCESS(res))
|
||||||
{
|
{
|
||||||
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, cmd_out);
|
log_msg(LOG_ERR,
|
||||||
|
"Error %i from cmd:'%s': %s", res, cmd_buf, fw_output_buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_msg(LOG_DEBUG, "RES=%i, CMD_BUF: %s\nRULES LIST: %s", res, cmd_buf, cmd_out);
|
log_msg(LOG_DEBUG, "RES=%i, CMD_BUF: %s\nRULES LIST: %s",
|
||||||
|
res, cmd_buf, fw_output_buf);
|
||||||
|
|
||||||
ndx = strstr(cmd_out, EXPIRE_COMMENT_PREFIX);
|
ndx = strstr(fw_output_buf, EXPIRE_COMMENT_PREFIX);
|
||||||
if(ndx == NULL)
|
if(ndx == NULL)
|
||||||
{
|
{
|
||||||
/* we did not find an expected rule.
|
/* we did not find a candidate rule to expire
|
||||||
*/
|
*/
|
||||||
log_msg(LOG_ERR,
|
log_msg(LOG_DEBUG,
|
||||||
"Did not find expire comment in rules list %i", i);
|
"Did not find expire comment in rules list %i", i);
|
||||||
|
|
||||||
if (ch[i].active_rules > 0)
|
if (ch[i].active_rules > 0)
|
||||||
@ -1453,121 +1657,7 @@ check_firewall_rules(const fko_srv_options_t * const opts)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* walk the list and process rules as needed.
|
rm_expired_rules(opts, fw_output_buf, ndx, ch, i, now);
|
||||||
*/
|
|
||||||
while (ndx != NULL) {
|
|
||||||
/* Jump forward and extract the timestamp
|
|
||||||
*/
|
|
||||||
ndx += strlen(EXPIRE_COMMENT_PREFIX);
|
|
||||||
|
|
||||||
/* remember this spot for when we look for the next
|
|
||||||
* rule.
|
|
||||||
*/
|
|
||||||
tmp_mark = ndx;
|
|
||||||
|
|
||||||
strlcpy(exp_str, ndx, sizeof(exp_str));
|
|
||||||
rule_exp = (time_t)atoll(exp_str);
|
|
||||||
|
|
||||||
if(rule_exp <= now)
|
|
||||||
{
|
|
||||||
/* Backtrack and get the rule number and delete it.
|
|
||||||
*/
|
|
||||||
rn_start = ndx;
|
|
||||||
while(--rn_start > cmd_out)
|
|
||||||
{
|
|
||||||
if(*rn_start == '\n')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(*rn_start != '\n')
|
|
||||||
{
|
|
||||||
/* This should not happen. But if it does, complain,
|
|
||||||
* decrement the active rule value, and go on.
|
|
||||||
*/
|
|
||||||
log_msg(LOG_ERR,
|
|
||||||
"Rule parse error while finding rule line start in chain %i", i);
|
|
||||||
|
|
||||||
if (ch[i].active_rules > 0)
|
|
||||||
ch[i].active_rules--;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rn_start++;
|
|
||||||
|
|
||||||
rn_end = strchr(rn_start, ' ');
|
|
||||||
if(rn_end == NULL)
|
|
||||||
{
|
|
||||||
/* This should not happen. But if it does, complain,
|
|
||||||
* decrement the active rule value, and go on.
|
|
||||||
*/
|
|
||||||
log_msg(LOG_ERR,
|
|
||||||
"Rule parse error while finding rule number in chain %i", i);
|
|
||||||
|
|
||||||
if (ch[i].active_rules > 0)
|
|
||||||
ch[i].active_rules--;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
strlcpy(rule_num_str, rn_start, (rn_end - rn_start)+1);
|
|
||||||
|
|
||||||
rule_num = strtol_wrapper(rule_num_str, rn_offset, RCHK_MAX_FIREWD_RULE_NUM,
|
|
||||||
NO_EXIT_UPON_ERR, &is_err);
|
|
||||||
if(is_err != FKO_SUCCESS)
|
|
||||||
{
|
|
||||||
log_msg(LOG_ERR,
|
|
||||||
"Rule parse error while finding rule number in chain %i", i);
|
|
||||||
|
|
||||||
if (ch[i].active_rules > 0)
|
|
||||||
ch[i].active_rules--;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
zero_cmd_buffers();
|
|
||||||
|
|
||||||
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " FIREWD_DEL_RULE_ARGS,
|
|
||||||
opts->fw_config->fw_command,
|
|
||||||
ch[i].table,
|
|
||||||
ch[i].to_chain,
|
|
||||||
rule_num - rn_offset
|
|
||||||
);
|
|
||||||
|
|
||||||
res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE,
|
|
||||||
WANT_STDERR, NO_TIMEOUT, &pid_status, opts);
|
|
||||||
chop_newline(err_buf);
|
|
||||||
|
|
||||||
log_msg(LOG_DEBUG, "check_firewall_rules() CMD: '%s' (res: %d, err: %s)",
|
|
||||||
cmd_buf, res, err_buf);
|
|
||||||
|
|
||||||
if(EXTCMD_IS_SUCCESS(res))
|
|
||||||
{
|
|
||||||
log_msg(LOG_INFO, "Removed rule %s from %s with expire time of %u",
|
|
||||||
rule_num_str, ch[i].to_chain, rule_exp
|
|
||||||
);
|
|
||||||
|
|
||||||
rn_offset++;
|
|
||||||
|
|
||||||
if (ch[i].active_rules > 0)
|
|
||||||
ch[i].active_rules--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Track the minimum future rule expire time.
|
|
||||||
*/
|
|
||||||
if(rule_exp > now)
|
|
||||||
min_exp = (min_exp < rule_exp) ? min_exp : rule_exp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Push our tracking index forward beyond (just processed) _exp_
|
|
||||||
* string so we can continue to the next rule in the list.
|
|
||||||
*/
|
|
||||||
ndx = strstr(tmp_mark, EXPIRE_COMMENT_PREFIX);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the next pending expire time accordingly. 0 if there are no
|
/* Set the next pending expire time accordingly. 0 if there are no
|
||||||
* more rules, or whatever the next expected (min_exp) time will be.
|
* more rules, or whatever the next expected (min_exp) time will be.
|
||||||
@ -1577,6 +1667,7 @@ check_firewall_rules(const fko_srv_options_t * const opts)
|
|||||||
else if(min_exp)
|
else if(min_exp)
|
||||||
ch[i].next_expire = min_exp;
|
ch[i].next_expire = min_exp;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
@ -64,7 +64,6 @@
|
|||||||
#define IPT_LIST_RULES_ARGS "-t %s -L %s --line-numbers -n" SH_REDIR
|
#define IPT_LIST_RULES_ARGS "-t %s -L %s --line-numbers -n" SH_REDIR
|
||||||
#define IPT_LIST_ALL_RULES_ARGS "-t %s -v -n -L --line-numbers" SH_REDIR
|
#define IPT_LIST_ALL_RULES_ARGS "-t %s -v -n -L --line-numbers" SH_REDIR
|
||||||
#define IPT_ANY_IP "0.0.0.0/0"
|
#define IPT_ANY_IP "0.0.0.0/0"
|
||||||
#define IPT_NAT_ANY_IP IPT_ANY_IP
|
|
||||||
|
|
||||||
int validate_ipt_chain_conf(const char * const chain_str);
|
int validate_ipt_chain_conf(const char * const chain_str);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user