From bc58b3a15f251a2065877d25e687dee215fad3e8 Mon Sep 17 00:00:00 2001 From: Michael Rash Date: Mon, 12 Nov 2012 21:48:26 -0500 Subject: [PATCH] Added chain_exists() check to fwknopd SPA rule creation Added chain_exists() check to SPA rule creation so that if any of the fwknop chains are deleted out from under fwknopd they will be recreated on the fly. This mitigates scenarios where fwknopd might be started before a system level firewall policy is applied due to init script ordering, or if an iptables policy is re-applied without restarting fwknopd. --- ChangeLog | 6 ++ server/fw_util_iptables.c | 117 +++++++++++++++++++++++++++----------- server/fw_util_iptables.h | 1 + 3 files changed, 92 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index df0453c6..2a0805d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -66,6 +66,12 @@ fwknop-2.0.4 (11//2012): - [server] Added a new '--pcap-file ' option to allow pcap files to be processed directly by fwknopd instead of sniffing an interface. This feature is mostly intended for debugging purposes. + - [server] Added chain_exists() check to SPA rule creation so that if any + of the fwknop chains are deleted out from under fwknopd they will be + recreated on the fly. This mitigates scenarios where fwknopd might be + started before a system level firewall policy is applied due to init + script ordering, or if an iptables policy is re-applied without + restarting fwknopd. fwknop-2.0.3 (09/03/2012): - [server] Fernando Arnaboldi from IOActive found several DoS/code diff --git a/server/fw_util_iptables.c b/server/fw_util_iptables.c index 929becd4..1f203b09 100644 --- a/server/fw_util_iptables.c +++ b/server/fw_util_iptables.c @@ -147,6 +147,35 @@ add_jump_rule(const fko_srv_options_t *opts, const int chain_num) return res; } +static int +chain_exists(const fko_srv_options_t *opts, const int chain_num) +{ + int res = 0; + + zero_cmd_buffers(); + + snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_CHAIN_EXISTS_ARGS, + fwc.fw_command, + fwc.chain[chain_num].table, + fwc.chain[chain_num].to_chain + ); + + res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0); + + if (opts->verbose) + log_msg(LOG_INFO, "chain_exists() CMD: '%s' (res: %d, err: %s)", + cmd_buf, res, err_buf); + + if(EXTCMD_IS_SUCCESS(res)) + log_msg(LOG_INFO, "'%s' table '%s' chain exists", + fwc.chain[chain_num].table, + fwc.chain[chain_num].to_chain); + else + log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf); + + return res; +} + static int jump_rule_exists(const int chain_num) { @@ -344,49 +373,59 @@ delete_all_chains(const fko_srv_options_t *opts) } } +static int +create_chain(const fko_srv_options_t *opts, const int chain_num) +{ + int res = 0; + + zero_cmd_buffers(); + + /* Create the custom chain. + */ + snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_NEW_CHAIN_ARGS, + fwc.fw_command, + fwc.chain[chain_num].table, + fwc.chain[chain_num].to_chain + ); + + res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0); + + if (opts->verbose) + log_msg(LOG_INFO, "create_chain() CMD: '%s' (res: %d, err: %s)", + cmd_buf, res, err_buf); + + /* Expect full success on this */ + if(! EXTCMD_IS_SUCCESS(res)) + log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf); + + return res; +} + /* Create the fwknop custom chains (at least those that are configured). */ static int create_fw_chains(const fko_srv_options_t *opts) { - int i; - int res, got_err = 0; + int i, got_err = 0; for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++) { if(fwc.chain[i].target[0] == '\0') continue; - zero_cmd_buffers(); - - /* Create the custom chain. - */ - snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_NEW_CHAIN_ARGS, - fwc.fw_command, - fwc.chain[i].table, - fwc.chain[i].to_chain - ); - - res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0); - - if (opts->verbose) - log_msg(LOG_INFO, "create_fw_chains() CMD: '%s' (res: %d, err: %s)", - cmd_buf, res, err_buf); - - /* Expect full success on this */ - if(! EXTCMD_IS_SUCCESS(res)) + if(chain_exists(opts, i) == 0) { - log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf); - got_err++; + + /* Create the chain + */ + if(! EXTCMD_IS_SUCCESS(create_chain(opts, i))) + got_err++; + + /* Then create the jump rule to that chain. + */ + if(! EXTCMD_IS_SUCCESS(add_jump_rule(opts, i))) + got_err++; } - - /* Then create the jump rule to that chain. - */ - res = add_jump_rule(opts, i); - - /* Expect full success on this */ - if(! EXTCMD_IS_SUCCESS(res)) - got_err++; } return(got_err); @@ -612,12 +651,20 @@ process_spa_request(const fko_srv_options_t *opts, const acc_stanza_t *acc, spa_ /* Check to make sure that the jump rules exist for each * required chain */ + if(chain_exists(opts, IPT_INPUT_ACCESS) == 0) + create_chain(opts, IPT_INPUT_ACCESS); + if(jump_rule_exists(IPT_INPUT_ACCESS) == 0) add_jump_rule(opts, IPT_INPUT_ACCESS); if(out_chain->to_chain != NULL && strlen(out_chain->to_chain)) + { + if(chain_exists(opts, IPT_OUTPUT_ACCESS) == 0) + create_chain(opts, IPT_OUTPUT_ACCESS); + if(jump_rule_exists(IPT_OUTPUT_ACCESS) == 0) add_jump_rule(opts, IPT_OUTPUT_ACCESS); + } /* Create an access command for each proto/port for the source ip. */ @@ -776,8 +823,11 @@ process_spa_request(const fko_srv_options_t *opts, const acc_stanza_t *acc, spa_ else if(fwd_chain->to_chain != NULL && strlen(fwd_chain->to_chain)) { /* Make our FORWARD and NAT rules, and make sure the - * required jump rule exists + * required chain and jump rule exists */ + if(chain_exists(opts, IPT_FORWARD_ACCESS) == 0) + create_chain(opts, IPT_FORWARD_ACCESS); + if (jump_rule_exists(IPT_FORWARD_ACCESS) == 0) add_jump_rule(opts, IPT_FORWARD_ACCESS); @@ -823,8 +873,11 @@ process_spa_request(const fko_srv_options_t *opts, const acc_stanza_t *acc, spa_ if(dnat_chain->to_chain != NULL && strlen(dnat_chain->to_chain)) { - /* Make sure the required jump rule exists + /* Make sure the required chain and jump rule exists */ + if(chain_exists(opts, IPT_DNAT_ACCESS) == 0) + create_chain(opts, IPT_DNAT_ACCESS); + if (jump_rule_exists(IPT_DNAT_ACCESS) == 0) add_jump_rule(opts, IPT_DNAT_ACCESS); diff --git a/server/fw_util_iptables.h b/server/fw_util_iptables.h index 9c706e5f..04af2300 100644 --- a/server/fw_util_iptables.h +++ b/server/fw_util_iptables.h @@ -44,6 +44,7 @@ #define IPT_DEL_RULE_ARGS "-t %s -D %s %i 2>&1" #define IPT_NEW_CHAIN_ARGS "-t %s -N %s 2>&1" #define IPT_FLUSH_CHAIN_ARGS "-t %s -F %s 2>&1" +#define IPT_CHAIN_EXISTS_ARGS "-t %s -L %s -n 2>&1" #define IPT_DEL_CHAIN_ARGS "-t %s -X %s 2>&1" #define IPT_ADD_JUMP_RULE_ARGS "-t %s -I %s %i -j %s 2>&1" #define IPT_LIST_RULES_ARGS "-t %s -L %s --line-numbers -n 2>&1"