Refactored firewall rule code to separate files by firewall type. Stubbed in ipfw and ipf firewall types. Updated autoconf to set a firewall type and path depending on configure arguments.

git-svn-id: file:///home/mbr/svn/fwknop/trunk@279 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
Damien Stuart
2010-08-10 02:29:09 +00:00
parent c1f67b900d
commit 838b80fd7d
16 changed files with 1455 additions and 946 deletions

View File

@@ -44,6 +44,13 @@
#endif
#if HAVE_NET_ETHERNET_H
#include <net/ethernet.h>
#elif HAVE_SYS_ETHERNET_H
#include <sys/ethernet.h> /* Seems to be where Solaris puts it. */
/* Also probably need to define ETHER_IS_VALID_LEN here */
#ifndef ETHER_IS_VALID_LEN
#define ETHER_IS_VALID_LEN(x) \
((x) >= ETHERMIN && (x) <= ETHERMAX)
#endif
#endif
#endif

View File

@@ -203,21 +203,17 @@ dnl
[AS_HELP_STRING([--with-iptables=/path/to/iptables],
[Specify path to the iptables executable @<:@default=check path@:>@])],
[
AS_IF([ test "x$withval" = x -o "x$withval" = xyes -o "x$withval" = xno ],
AS_IF([ test "x$withval" = xno ], [],
AS_IF([ test "x$withval" = x -o "x$withval" = xyes ],
[AC_MSG_ERROR([--with-iptables requires an argument specifying a path to iptables])],
[ IPTABLES_EXE=$withval ]
)
)
],
[
AC_PATH_PROG(IPTABLES_EXE, [iptables], [], [$APP_PATH])
AC_PATH_PROG(IPTABLES_EXE, [iptables], [], [$APP_PATH])
]
)
AS_IF([test "x$IPTABLES_EXE" != x],
[
AC_DEFINE_UNQUOTED([IPTABLES_EXE], ["$IPTABLES_EXE"], [Path to iptables executable])
iptables_exe=$IPTABLES_EXE
], [ iptables_exe="(not found)"]
)
dnl Check for ipfw
dnl
@@ -225,22 +221,64 @@ dnl
[AS_HELP_STRING([--with-ipfw=/path/to/ipfw],
[Specify path to the ipfw executable @<:@default=check path@:>@])],
[
AS_IF([ test "x$withval" = x -o "x$withval" = xyes -o "x$withval" = xno ],
AS_IF([ test "x$withval" = xno ], [],
AS_IF([ test "x$withval" = x -o "x$withval" = xyes ],
[AC_MSG_ERROR([--with-ipfw requires an argument specifying a path to ipfw])],
[ IPFW_EXE=$withval ]
)
)
],
[
AC_PATH_PROG(IPFW_EXE, [ipfw], [], [$APP_PATH])
AC_PATH_PROG(IPFW_EXE, [ipfw], [], [$APP_PATH])
]
)
AS_IF([test "x$IPFW_EXE" != x],
[
AC_DEFINE_UNQUOTED([IPFW_EXE], ["$IPFW_EXE"], [Path to ipfw executable])
ipfw_exe=$IPFW_EXE
], [ ipfw_exe="(not found)"]
)],
dnl Check for ipf (ipfilter)
dnl
AC_ARG_WITH([ipf],
[AS_HELP_STRING([--with-ipf=/path/to/ipf],
[Specify path to the ipf executable @<:@default=check path@:>@])],
[
AS_IF([ test "x$withval" = xno ], [],
AS_IF([ test "x$withval" = x -o "x$withval" = xyes ],
[AC_MSG_ERROR([--with-ipfw requires an argument specifying a path to ipfw])],
[ IPF_EXE=$withval ]
)
)
],
[
AC_PATH_PROG(IPF_EXE, [ipf], [], [$APP_PATH])
]
)
dnl Determine which firewall exe we use (if we have one).
dnl If iptables was found or specified, it wins, then we fallback to ipfw,
dnl otherwise we try ipf.
dnl
AS_IF([test "x$IPTABLES_EXE" != x], [
FW_DEF="FW_IPTABLES"
FIREWALL_TYPE="iptables"
FIREWALL_EXE=$IPTABLES_EXE
AC_DEFINE_UNQUOTED([FIREWALL_IPTABLES], [1], [The firewall type: iptables.])
],[
AS_IF([test "x$IPFW_EXE" != x], [
FW_DEF="FW_IPFW"
FIREWALL_TYPE="ipfw"
FIREWALL_EXE=$IPFW_EXE
AC_DEFINE_UNQUOTED([FIREWALL_IPFW], [1], [The firewall type: ipfw.])
],[ AS_IF([test "x$IPF_EXE" != x], [
FIREWALL_TYPE="ipf"
FIREWALL_EXE=$IPF_EXE
AC_DEFINE_UNQUOTED([FIREWALL_IPF], [1], [The firewall type: ipf.])
], [AC_MSG_ERROR([No firewall program was found or specified.]) ]
]
]
)))
AC_DEFINE_UNQUOTED([FIREWALL_EXE], ["$FIREWALL_EXE"],
[Path to firewall command executable (it should match the firewall type).])
],
[test "$want_server" = no], [
use_ndbm=no
AM_CONDITIONAL([USE_NDBM], [test x$use_ndbm = xno])
@@ -271,9 +309,9 @@ echo "
Installation prefix: $prefix
"
if [test $want_server = "yes" ]; then
echo " Server support programs:
iptables: $iptables_exe
ipfw: $ipfw_exe
echo " Server support:
firewall type: $FIREWALL_TYPE
firewall program path: $FIREWALL_EXE
"
fi

View File

@@ -7,7 +7,9 @@ fwknopd_SOURCES = fwknopd.c fwknopd.h config_init.c config_init.h \
sig_handler.c sig_handler.h replay_dbm.c replay_dbm.h \
access.c access.h fwknopd_errors.c fwknopd_errors.h \
tcp_server.c tcp_server.h extcmd.c extcmd.h \
fw_util.c fw_util.h
fw_util.c fw_util.h fw_util_ipf.c fw_util_ipf.h \
fw_util_iptables.c fw_util_iptables.h \
fw_util_ipfw.c fw_util_ipfw.h
fwknopd_LDADD = $(top_builddir)/lib/libfko.la -lpcap
if USE_NDBM

View File

@@ -416,11 +416,10 @@ validate_options(fko_srv_options_t *opts)
exit(EXIT_FAILURE);
}
if(opts->config[CONF_EXE_IPTABLES] == NULL
&& opts->config[CONF_EXE_IPFW] == NULL)
if(opts->config[CONF_FIREWALL_EXE] == NULL)
{
fprintf(stderr,
"No firewall command executable is set. Please check fwknopd.conf for EXE_IPTABLES or EXE_IPFW.\n"
"No firewall command executable is set. Please check FIREWALL_EXE in fwknopd.conf.\n"
);
exit(EXIT_FAILURE);
}
@@ -435,13 +434,12 @@ set_preconfig_entries(fko_srv_options_t *opts)
* end up being overwritten via config file or command-line.
*/
/* Setup the local executables based on build-time info.
/* Setup the firewall executable based on build-time info.
* --DSS Note: We will want to either force external script mode, or
* error out if we do not have a firewall executable defined.
*/
#ifdef IPTABLES_EXE
set_config_entry(opts, CONF_EXE_IPTABLES, IPTABLES_EXE);
#endif
#ifdef IPFW_EXE
set_config_entry(opts, CONF_EXE_IPFW, IPFW_EXE);
#ifdef FIREWALL_EXE
set_config_entry(opts, CONF_FIREWALL_EXE, FIREWALL_EXE);
#endif
}

View File

@@ -31,899 +31,8 @@
#include "extcmd.h"
#include "access.h"
#if HAVE_TIME_H
#include <time.h>
#endif
static struct fw_config fwc;
/*
static void
parse_extcmd_error(int retval, int status, char *se_buf)
{
char errmsg[CMD_BUFSIZE];
char *emptr = errmsg;
if(retval < 0)
{
log_msg(LOG_ERR, "Extcmd fork error: %s", strerror(errno));
return;
}
sprintf(emptr, "Extcmd return: %i, command exit status: %i", retval, status);
emptr += strlen(emptr);
if(EXTCMD_EXECUTION_ERROR(retval))
{
sprintf(errmsg, "Extcmd stderr=%s", se_buf);
emptr += strlen(emptr);
}
if(EXTCMD_IS_SUCCESS_PARTIAL_STDOUT(retval))
{
sprintf(errmsg, "\n - Got partial stdout");
emptr += strlen(emptr);
}
if(EXTCMD_IS_SUCCESS_PARTIAL_STDERR(retval))
{
sprintf(errmsg, "\n - Got partial stderr");
emptr += strlen(emptr);
}
if(EXTCMD_STDOUT_READ_ERROR(retval))
{
sprintf(errmsg, "\n - Got read error on stdout");
emptr += strlen(emptr);
}
if(EXTCMD_STDERR_READ_ERROR(retval))
{
sprintf(errmsg, "\n - Got read error on stderr");
emptr += strlen(emptr);
}
log_msg(LOG_WARNING, errmsg);
}
/* --DSS This is a place holder for now. We may put the generalized external
* firewall script code here ( or not).
*/
static int
jump_rule_exists(int chain_num)
{
int num, pos = 0;
char cmd_buf[CMD_BUFSIZE] = {0};
char target[CMD_BUFSIZE] = {0};
char line_buf[CMD_BUFSIZE] = {0};
FILE *ipt;
sprintf(cmd_buf, "%s " IPT_LIST_RULES_ARGS,
fwc.fw_command,
fwc.chain[chain_num].table,
fwc.chain[chain_num].from_chain
);
ipt = popen(cmd_buf, "r");
if(ipt == NULL)
{
log_msg(LOG_ERR,
"Got error %i trying to get rules list.\n", errno);
return(-1);
}
while((fgets(line_buf, CMD_BUFSIZE-1, ipt)) != NULL)
{
/* Get past comments and empty lines (note: we only look at the
* first character).
*/
if(IS_EMPTY_LINE(line_buf[0]))
continue;
if(sscanf(line_buf, "%i %s ", &num, target) == 2)
{
if(strcmp(target, fwc.chain[chain_num].to_chain) == 0)
{
pos = num;
break;
}
}
}
pclose(ipt);
return(pos);
}
/* Print all firewall rules currently instantiated by the running fwknopd
* daemon to stdout.
*/
int
fw_dump_rules(fko_srv_options_t *opts)
{
int i;
int res, got_err = 0;
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
struct fw_chain *ch = opts->fw_config->chain;
printf("Listing rules in fwknop chains...\n");
for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++)
{
if(fwc.chain[i].target[0] == '\0')
continue;
/* Create the list command
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_LIST_RULES_ARGS,
opts->fw_config->fw_command,
ch[i].table,
ch[i].to_chain
);
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
res = system(cmd_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);
got_err++;
}
}
return(got_err);
}
/* Quietly flush and delete all fwknop custom chains.
*/
static void
delete_all_chains(void)
{
int i, res;
int jump_rule_num;
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++)
{
if(fwc.chain[i].target[0] == '\0')
continue;
/* First look for a jump rule to this chain and remove it if it
* is there.
*/
if((jump_rule_num = jump_rule_exists(i)) > 0)
{
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_DEL_RULE_ARGS,
fwc.fw_command,
fwc.chain[i].table,
fwc.chain[i].from_chain,
jump_rule_num
);
//printf("CMD: '%s'\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
memset(cmd_buf, 0x0, CMD_BUFSIZE);
/* Now flush and remove the chain.
*/
snprintf(cmd_buf, CMD_BUFSIZE-1,
"(%s " IPT_FLUSH_CHAIN_ARGS "; %s " IPT_DEL_CHAIN_ARGS ")", // > /dev/null 2>&1",
fwc.fw_command,
fwc.chain[i].table,
fwc.chain[i].to_chain,
fwc.fw_command,
fwc.chain[i].table,
fwc.chain[i].to_chain
);
//printf("CMD: '%s'\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
}
/* Create the fwknop custom chains (at least those that are configured).
*/
static int
create_fw_chains(void)
{
int i;
int res, got_err = 0;
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++)
{
if(fwc.chain[i].target[0] == '\0')
continue;
/* 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
);
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
got_err++;
}
memset(cmd_buf, 0x0, CMD_BUFSIZE);
/* Then create the jump rule to that chain.
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_JUMP_RULE_ARGS,
fwc.fw_command,
fwc.chain[i].table,
fwc.chain[i].from_chain,
fwc.chain[i].jump_rule_pos,
fwc.chain[i].to_chain
);
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
got_err++;
}
}
return(got_err);
}
static void
set_fw_chain_conf(int type, char *conf_str)
{
int i, j;
char tbuf[1024] = {0};
char *ndx = conf_str;
char *chain_fields[FW_NUM_CHAIN_FIELDS];
struct fw_chain *chain = &(fwc.chain[type]);
chain->type = type;
if(ndx != NULL)
chain_fields[0] = tbuf;
i = 0;
j = 1;
while(*ndx != '\0')
{
if(*ndx != ' ')
{
if(*ndx == ',')
{
tbuf[i] = '\0';
chain_fields[j++] = &(tbuf[++i]);
}
else
tbuf[i++] = *ndx;
}
ndx++;
}
/* Sanity check - j should be the number of chain fields
* (excluding the type).
*/
if(j != FW_NUM_CHAIN_FIELDS)
{
fprintf(stderr, "[*] Custom Chain config parse error.\n"
"Wrong number of fields for chain type %i\n"
"Line: %s\n", type, conf_str);
exit(EXIT_FAILURE);
}
/* Pull and set Target */
strlcpy(chain->target, chain_fields[0], MAX_TARGET_NAME_LEN);
/* Pull and set Direction
if(strcmp(chain_fields[1], FW_CHAIN_DIR_SRC_STR) == 0)
chain->direction = FW_CHAIN_DIR_SRC;
else if(strcmp(chain_fields[1], FW_CHAIN_DIR_DST_STR) == 0)
chain->direction = FW_CHAIN_DIR_DST;
else if(strcmp(chain_fields[1], FW_CHAIN_DIR_BOTH_STR) == 0)
chain->direction = FW_CHAIN_DIR_BOTH;
else
chain->direction = FW_CHAIN_DIR_UNKNOWN;
*/
/* Pull and set Table */
strlcpy(chain->table, chain_fields[1], MAX_TABLE_NAME_LEN);
/* Pull and set From_chain */
strlcpy(chain->from_chain, chain_fields[2], MAX_CHAIN_NAME_LEN);
/* Pull and set Jump_rule_position */
chain->jump_rule_pos = atoi(chain_fields[3]);
/* Pull and set To_chain */
strlcpy(chain->to_chain, chain_fields[4], MAX_CHAIN_NAME_LEN);
/* Pull and set Jump_rule_position */
chain->rule_pos = atoi(chain_fields[5]);
}
void
fw_config_init(fko_srv_options_t *opts)
{
memset(&fwc, 0x0, sizeof(struct fw_config));
/* Set our firewall exe command path (iptables in most cases).
*/
strlcpy(fwc.fw_command, opts->config[CONF_EXE_IPTABLES], MAX_PATH_LEN);
/* Pull the fwknop chain config info and setup our internal
* config struct. The IPT_INPUT is the only one that is
* required. The rest are optional.
*/
set_fw_chain_conf(IPT_INPUT_ACCESS, opts->config[CONF_IPT_INPUT_ACCESS]);
/* The FWKNOP_OUTPUT_ACCESS requires ENABLE_IPT_OUTPUT_ACCESS be Y
*/
if(strncasecmp(opts->config[CONF_ENABLE_IPT_OUTPUT], "Y", 1)==0)
set_fw_chain_conf(IPT_OUTPUT_ACCESS, opts->config[CONF_IPT_OUTPUT_ACCESS]);
/* The remaining access chains require ENABLE_IPT_FORWARDING = Y
*/
if(strncasecmp(opts->config[CONF_ENABLE_IPT_FORWARDING], "Y", 1)==0)
{
set_fw_chain_conf(IPT_FORWARD_ACCESS, opts->config[CONF_IPT_FORWARD_ACCESS]);
set_fw_chain_conf(IPT_DNAT_ACCESS, opts->config[CONF_IPT_DNAT_ACCESS]);
/* SNAT (whichever mode) requires ENABLE_IPT_SNAT = Y
*/
if(strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "Y", 1)==0)
{
/* If an SNAT_TRANSLATE_IP is specified use the SNAT_ACCESS mode.
* Otherwise, use MASQUERADE_ACCESS.
*
* XXX: --DSS: Not sure if using the TRANSLATE_IP parameter as
* the determining factor is the best why to handle
* this.
*
*/
if(opts->config[CONF_SNAT_TRANSLATE_IP] != NULL
&& strncasecmp(opts->config[CONF_SNAT_TRANSLATE_IP], "__CHANGEME__", 10)!=0)
set_fw_chain_conf(IPT_SNAT_ACCESS, opts->config[CONF_IPT_SNAT_ACCESS]);
else
set_fw_chain_conf(IPT_MASQUERADE_ACCESS, opts->config[CONF_IPT_MASQUERADE_ACCESS]);
}
}
/* Let us find it via our opts struct as well.
*/
opts->fw_config = &fwc;
return;
}
void
fw_initialize(void)
{
int res;
/* Flush the chains (just in case) so we can start fresh.
*/
delete_all_chains();
/* Now create any configured chains.
*/
res = create_fw_chains();
if(res != 0)
{
fprintf(stderr, "Warning: Errors detected during fwknop custom chain creation.\n");
exit(EXIT_FAILURE);
}
}
void
fw_cleanup(void)
{
delete_all_chains();
}
/****************************************************************************/
/* Rule Processing - Create an access request...
*/
int
process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
{
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
char nat_ip[16] = {0};
char snat_target[SNAT_TARGET_BUFSIZE] = {0};
char *ndx;
unsigned int nat_port = 0;;
acc_port_list_t *port_list = NULL;
acc_port_list_t *ple;
unsigned int fst_proto;
unsigned int fst_port;
struct fw_chain *in_chain = &(opts->fw_config->chain[IPT_INPUT_ACCESS]);
struct fw_chain *out_chain = &(opts->fw_config->chain[IPT_OUTPUT_ACCESS]);
struct fw_chain *fwd_chain = &(opts->fw_config->chain[IPT_FORWARD_ACCESS]);
struct fw_chain *dnat_chain = &(opts->fw_config->chain[IPT_DNAT_ACCESS]);
struct fw_chain *snat_chain; /* We assign this later (if we need to). */
int res = 0;
time_t now;
unsigned int exp_ts;
/* Parse and expand our access message.
*/
expand_acc_port_list(&port_list, spadat->spa_message_remain);
/* Start at the top of the proto-port list...
*/
ple = port_list;
/* Remember the first proto/port combo in case we need them
* for NAT access requests.
*/
fst_proto = ple->proto;
fst_port = ple->port;
/* Set our expire time value.
*/
time(&now);
exp_ts = now + spadat->fw_access_timeout;
/* For straight access requests, we currently support multiple proto/port
* request.
*/
if(spadat->message_type == FKO_ACCESS_MSG
|| spadat->message_type == FKO_CLIENT_TIMEOUT_ACCESS_MSG)
{
/* Create an access command for each proto/port for the source ip.
*/
while(ple != NULL)
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_RULE_ARGS,
opts->fw_config->fw_command,
in_chain->table,
in_chain->to_chain,
ple->proto,
spadat->use_src_ip,
ple->port,
exp_ts,
in_chain->target
);
//--DSS tmp
//fprintf(stderr, "ADD CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added Rule to %s for %s, %s expires at %u",
in_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
in_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(in_chain->next_expire < now || exp_ts < in_chain->next_expire)
in_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
/* If we have to make an corresponding OUTPUT rule if out_chain target
* is not NULL.
*/
if(out_chain->to_chain != NULL && strlen(out_chain->to_chain))
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_OUT_RULE_ARGS,
opts->fw_config->fw_command,
out_chain->table,
out_chain->to_chain,
ple->proto,
spadat->use_src_ip,
ple->port,
exp_ts,
out_chain->target
);
//--DSS tmp
//fprintf(stderr, "ADD OUTPUT CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added OUTPUT Rule to %s for %s, %s expires at %u",
out_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
out_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(out_chain->next_expire < now || exp_ts < out_chain->next_expire)
out_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
ple = ple->next;
}
/* Done with the port list for access rules.
*/
free_acc_port_list(port_list);
}
/* NAT requests... */
else if( spadat->message_type == FKO_LOCAL_NAT_ACCESS_MSG
|| spadat->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG
|| spadat->message_type == FKO_NAT_ACCESS_MSG
|| spadat->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG )
{
/* Parse out the NAT IP and Port components.
*/
ndx = strchr(spadat->nat_access, ',');
if(ndx != NULL)
{
strlcpy(nat_ip, spadat->nat_access, (ndx-spadat->nat_access)+1);
nat_port = atoi(ndx+1);
}
// --DSS temp
//fprintf(stderr, "NAT IP: '%s', NAT PORT: '%i'\n", nat_ip, nat_port);
/* Make our FORWARD and NAT rules
*/
if(fwd_chain->to_chain != NULL && strlen(fwd_chain->to_chain))
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_FWD_RULE_ARGS,
opts->fw_config->fw_command,
fwd_chain->table,
fwd_chain->to_chain,
fst_proto,
spadat->use_src_ip,
nat_ip,
nat_port,
exp_ts,
fwd_chain->target
);
//--DSS tmp
//fprintf(stderr, "ADD OUTPUT CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added FORWARD Rule to %s for %s, %s expires at %u",
fwd_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
fwd_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(fwd_chain->next_expire < now || exp_ts < fwd_chain->next_expire)
fwd_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
if(dnat_chain->to_chain != NULL && strlen(dnat_chain->to_chain))
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_DNAT_RULE_ARGS,
opts->fw_config->fw_command,
dnat_chain->table,
dnat_chain->to_chain,
fst_proto,
spadat->use_src_ip,
fst_port,
exp_ts,
dnat_chain->target,
nat_ip,
nat_port
);
//--DSS tmp
//fprintf(stderr, "ADD DNAT CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added DNAT Rule to %s for %s, %s expires at %u",
dnat_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
dnat_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(dnat_chain->next_expire < now || exp_ts < dnat_chain->next_expire)
dnat_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
/* If SNAT (or MASQUERADE) is wanted, then we add those rules here as well.
*/
if(strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "Y", 1) == 0)
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
/* Setup some parameter depending on whether we are using SNAT
* or MASQUERADE.
*/
if(strncasecmp(opts->config[CONF_SNAT_TRANSLATE_IP], "__CHANGEME__", 10)!=0)
{
/* Using static SNAT */
snat_chain = &(opts->fw_config->chain[IPT_SNAT_ACCESS]);
snprintf(snat_target, SNAT_TARGET_BUFSIZE-1,
"--to-source %s:%i", opts->config[CONF_SNAT_TRANSLATE_IP],
fst_port);
}
else
{
/* Using MASQUERADE */
snat_chain = &(opts->fw_config->chain[IPT_MASQUERADE_ACCESS]);
snprintf(snat_target, SNAT_TARGET_BUFSIZE-1,
"--to-ports %i", fst_port);
}
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_SNAT_RULE_ARGS,
opts->fw_config->fw_command,
snat_chain->table,
snat_chain->to_chain,
fst_proto,
nat_ip,
nat_port,
exp_ts,
snat_chain->target,
snat_target
);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added Source NAT Rule to %s for %s, %s expires at %u",
snat_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
snat_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(snat_chain->next_expire < now || exp_ts < snat_chain->next_expire)
snat_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
}
return(res);
}
/* Iterate over the configure firewall access chains and purge expired
* firewall rules.
*/
void
check_firewall_rules(fko_srv_options_t *opts)
{
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
char cmd_out[STANDARD_CMD_OUT_BUFSIZE];
char exp_str[12];
char rule_num_str[6];
char *ndx, *rn_start, *rn_end, *tmp_mark;
int i, res, rn_offset;
time_t now, rule_exp, min_exp = 0;
struct fw_chain *ch = opts->fw_config->chain;
time(&now);
/* Iterate over each chain and look for active rules to delete.
*/
for(i = 0; i < NUM_FWKNOP_ACCESS_TYPES; i++)
{
/* Just in case we somehow lose track and fall out-of-whack,
* we be the hero and reset it to zero.
* (poet but don't know it :-o )
*/
if(ch[i].active_rules < 0)
ch[i].active_rules = 0;
/* If there are no active rules or we have not yet
* reached our expected next expire time, continue.
*/
if(ch[i].active_rules == 0 || ch[i].next_expire > now)
continue;
rn_offset = 0;
/* There should be a rule to delete. Get the current list of
* rules for this chain and delete the ones that are expired.
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_LIST_RULES_ARGS,
opts->fw_config->fw_command,
ch[i].table,
ch[i].to_chain
);
memset(cmd_out, 0x0, STANDARD_CMD_OUT_BUFSIZE);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
if(!EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, cmd_out);
continue;
}
if(opts->verbose > 2)
log_msg(LOG_INFO, "RES=%i, CMD_BUF: %s\nRULES LIST: %s", res, cmd_buf, cmd_out);
ndx = strstr(cmd_out, "_exp_");
if(ndx == NULL)
{
/* we did not find an expected rule.
*/
log_msg(LOG_ERR,
"Did not find expire comment in rules list %i.\n", i);
ch[i].active_rules--;
continue;
}
/* walk the list and process rules as needed.
*/
while (ndx != NULL) {
/* Jump forward and extract the timestamp
*/
ndx +=5;
/* remember this spot for when we look for the next
* rule.
*/
tmp_mark = ndx;
strlcpy(exp_str, ndx, 11);
rule_exp = (time_t)atoll(exp_str);
//fprintf(stderr, "RULE_EXP=%u, NOW=%u\n", rule_exp, now);
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);
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);
ch[i].active_rules--;
break;
}
strlcpy(rule_num_str, rn_start, (rn_end - rn_start)+1);
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_DEL_RULE_ARGS,
opts->fw_config->fw_command,
ch[i].table,
ch[i].to_chain,
atoi(rule_num_str) - rn_offset
);
//fprintf(stderr, "DELETE RULE CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
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++;
ch[i].active_rules--;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
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, "_exp_");
}
/* Set the next pending expire time accordingly. 0 if there are no
* more rules, or whatever the next expected (min_exp) time will be.
*/
if(ch[i].active_rules < 1)
ch[i].next_expire = 0;
else if(min_exp)
ch[i].next_expire = min_exp;
}
}
/***EOF***/

View File

@@ -31,30 +31,26 @@
#define STANDARD_CMD_OUT_BUFSIZE 4096
#define SNAT_TARGET_BUFSIZE 64
#if FIREWALL_IPTABLES
#include "fw_util_iptables.h"
#elif FIREWALL_IPFW
#include "fw_util_ipfw.h"
#elif FIREWALL_IPF
#include "fw_util_ipf.h"
#endif
/* iptables command args
*/
#define IPT_ADD_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s 2>&1"
#define IPT_ADD_OUT_RULE_ARGS "-t %s -A %s -p %i -d %s --sport %i -m comment --comment _exp_%u -j %s 2>&1"
#define IPT_ADD_FWD_RULE_ARGS "-t %s -A %s -p %i -s %s -d %s --dport %i -m comment --comment _exp_%u -j %s 2>&1"
#define IPT_ADD_DNAT_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s --to-destination %s:%i 2>&1"
#define IPT_ADD_SNAT_RULE_ARGS "-t %s -A %s -p %i -d %s --dport %i -m comment --comment _exp_%u -j %s %s 2>&1"
#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_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"
#if HAVE_TIME_H
#include <time.h>
#endif
/* Function prototypes
*/
void fw_config_init(fko_srv_options_t *opts);
void fw_initialize(void);
void fw_cleanup(void);
int process_spa_request(fko_srv_options_t *opts, spa_data_t *spdat);
void check_firewall_rules(fko_srv_options_t *opts);
int fw_dump_rules(fko_srv_options_t *opts);
int process_spa_request(fko_srv_options_t *opts, spa_data_t *spdat);
#endif /* FW_UTIL_H */

172
server/fw_util_ipf.c Normal file
View File

@@ -0,0 +1,172 @@
/* $Id$
*****************************************************************************
*
* File: fw_util_ipf.c
*
* Author: Damien S. Stuart
*
* Purpose: Fwknop routines for managing ipf firewall rules.
*
* Copyright (C) 2010 Damien Stuart (dstuart@dstuart.org)
*
* License (GNU Public License):
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#include "fwknopd_common.h"
#if FIREWALL_IPF
#include "fw_util.h"
#include "utils.h"
#include "log_msg.h"
#include "config_init.h" /* for the IS_EMPTY_LINE macro */
#include "extcmd.h"
#include "access.h"
static struct fw_config fwc;
/* Print all firewall rules currently instantiated by the running fwknopd
* daemon to stdout.
*/
int
fw_dump_rules(fko_srv_options_t *opts)
{
int i;
int res, got_err = 0;
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
/* TODO: Implement or get rid of me */
return(got_err);
}
void
fw_config_init(fko_srv_options_t *opts)
{
/* TODO: Implement me */
memset(&fwc, 0x0, sizeof(struct fw_config));
/* Set our firewall exe command path (iptables in most cases).
*/
strlcpy(fwc.fw_command, opts->config[CONF_FIREWALL_EXE], MAX_PATH_LEN);
/* Let us find it via our opts struct as well.
*/
opts->fw_config = &fwc;
return;
}
void
fw_initialize(void)
{
int res = 0;
/* TODO: Implement me */
if(res != 0)
{
fprintf(stderr, "Warning: Errors detected during fwknop custom chain creation.\n");
exit(EXIT_FAILURE);
}
}
void
fw_cleanup(void)
{
/* TODO: Implement or get rid of me */
}
/****************************************************************************/
/* Rule Processing - Create an access request...
*/
int
process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
{
/* TODO: Implement me */
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
char nat_ip[16] = {0};
char snat_target[SNAT_TARGET_BUFSIZE] = {0};
char *ndx;
unsigned int nat_port = 0;;
acc_port_list_t *port_list = NULL;
acc_port_list_t *ple;
unsigned int fst_proto;
unsigned int fst_port;
int res = 0;
time_t now;
unsigned int exp_ts;
/* Parse and expand our access message.
*/
expand_acc_port_list(&port_list, spadat->spa_message_remain);
/* Start at the top of the proto-port list...
*/
ple = port_list;
/* Remember the first proto/port combo in case we need them
* for NAT access requests.
*/
fst_proto = ple->proto;
fst_port = ple->port;
/* Set our expire time value.
*/
time(&now);
exp_ts = now + spadat->fw_access_timeout;
/* TODO: Implement me */
return(res);
}
/* Iterate over the configure firewall access chains and purge expired
* firewall rules.
*/
void
check_firewall_rules(fko_srv_options_t *opts)
{
/* TODO: Implement me */
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
char cmd_out[STANDARD_CMD_OUT_BUFSIZE];
char exp_str[12];
char rule_num_str[6];
char *ndx, *rn_start, *rn_end, *tmp_mark;
int i, res, rn_offset;
time_t now, rule_exp, min_exp = 0;
time(&now);
}
#endif /* FIREWALL_IPF */
/***EOF***/

43
server/fw_util_ipf.h Normal file
View File

@@ -0,0 +1,43 @@
/* $Id$
*****************************************************************************
*
* File: fw_util_ipf.h
*
* Author: Damien Stuart (dstuart@dstuart.org)
*
* Purpose: Header file for fw_util_ipf.c.
*
* Copyright (C) 2010 Damien Stuart (dstuart@dstuart.org)
*
* License (GNU Public License):
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#ifndef FW_UTIL_IPF_H
#define FW_UTIL_IPF_H
#define SNAT_TARGET_BUFSIZE 64
/* ipfw command args (gotta flesh these out)
*/
#define IPF_ADD_RULE_ARGS ""
#define IPF_ADD_OUT_RULE_ARGS ""
#define IPF_ADD_FWD_RULE_ARGS ""
#define IPF_ADD_DNAT_RULE_ARGS ""
#define IPF_ADD_SNAT_RULE_ARGS ""
#define IPF_DEL_RULE_ARGS ""
#define IPF_LIST_RULES_ARGS ""
#endif /* FW_UTIL_IPF_H */
/***EOF***/

173
server/fw_util_ipfw.c Normal file
View File

@@ -0,0 +1,173 @@
/* $Id$
*****************************************************************************
*
* File: fw_util_ipfw.c
*
* Author: Damien S. Stuart
*
* Purpose: Fwknop routines for managing ipfw firewall rules.
*
* Copyright (C) 2010 Damien Stuart (dstuart@dstuart.org)
*
* License (GNU Public License):
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#include "fwknopd_common.h"
#if FIREWALL_IPFW
#include "fw_util.h"
#include "utils.h"
#include "log_msg.h"
#include "config_init.h" /* for the IS_EMPTY_LINE macro */
#include "extcmd.h"
#include "access.h"
static struct fw_config fwc;
/* Print all firewall rules currently instantiated by the running fwknopd
* daemon to stdout.
*/
int
fw_dump_rules(fko_srv_options_t *opts)
{
int i;
int res, got_err = 0;
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
/* TODO: Implement me */
return(got_err);
}
void
fw_config_init(fko_srv_options_t *opts)
{
/* TODO: Implement me */
memset(&fwc, 0x0, sizeof(struct fw_config));
/* Set our firewall exe command path (iptables in most cases).
*/
strlcpy(fwc.fw_command, opts->config[CONF_FIREWALL_EXE], MAX_PATH_LEN);
/* Let us find it via our opts struct as well.
*/
opts->fw_config = &fwc;
return;
}
void
fw_initialize(void)
{
int res = 0;
/* TODO: Implement me */
if(res != 0)
{
fprintf(stderr, "Warning: Errors detected during fwknop custom chain creation.\n");
exit(EXIT_FAILURE);
}
}
void
fw_cleanup(void)
{
/* TODO: Implement me */
}
/****************************************************************************/
/* Rule Processing - Create an access request...
*/
int
process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
{
/* TODO: Implement me */
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
char nat_ip[16] = {0};
char snat_target[SNAT_TARGET_BUFSIZE] = {0};
char *ndx;
unsigned int nat_port = 0;;
acc_port_list_t *port_list = NULL;
acc_port_list_t *ple;
unsigned int fst_proto;
unsigned int fst_port;
int res = 0;
time_t now;
unsigned int exp_ts;
/* Parse and expand our access message.
*/
expand_acc_port_list(&port_list, spadat->spa_message_remain);
/* Start at the top of the proto-port list...
*/
ple = port_list;
/* Remember the first proto/port combo in case we need them
* for NAT access requests.
*/
fst_proto = ple->proto;
fst_port = ple->port;
/* Set our expire time value.
*/
time(&now);
exp_ts = now + spadat->fw_access_timeout;
/* TODO: Implement me */
return(res);
}
/* Iterate over the configure firewall access chains and purge expired
* firewall rules.
*/
void
check_firewall_rules(fko_srv_options_t *opts)
{
/* TODO: Implement me */
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
char cmd_out[STANDARD_CMD_OUT_BUFSIZE];
char exp_str[12];
char rule_num_str[6];
char *ndx, *rn_start, *rn_end, *tmp_mark;
int i, res, rn_offset;
time_t now, rule_exp, min_exp = 0;
time(&now);
}
#endif /* FIREWALL_IPFW */
/***EOF***/

43
server/fw_util_ipfw.h Normal file
View File

@@ -0,0 +1,43 @@
/* $Id$
*****************************************************************************
*
* File: fw_util_ipfw.h
*
* Author: Damien Stuart (dstuart@dstuart.org)
*
* Purpose: Header file for fw_util_ipfw.c.
*
* Copyright (C) 2010 Damien Stuart (dstuart@dstuart.org)
*
* License (GNU Public License):
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#ifndef FW_UTIL_IPFW_H
#define FW_UTIL_IPFW_H
#define SNAT_TARGET_BUFSIZE 64
/* ipfw command args (gotta flesh these out)
*/
#define IPFW_ADD_RULE_ARGS ""
#define IPFW_ADD_OUT_RULE_ARGS ""
#define IPFW_ADD_FWD_RULE_ARGS ""
#define IPFW_ADD_DNAT_RULE_ARGS ""
#define IPFW_ADD_SNAT_RULE_ARGS ""
#define IPFW_DEL_RULE_ARGS ""
#define IPFW_LIST_RULES_ARGS ""
#endif /* FW_UTIL_IPFW_H */
/***EOF***/

881
server/fw_util_iptables.c Normal file
View File

@@ -0,0 +1,881 @@
/* $Id$
*****************************************************************************
*
* File: fw_util_iptables.c
*
* Author: Damien S. Stuart
*
* Purpose: Fwknop routines for managing iptables firewall rules.
*
* Copyright (C) 2010 Damien Stuart (dstuart@dstuart.org)
*
* License (GNU Public License):
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#include "fwknopd_common.h"
#ifdef FIREWALL_IPTABLES
#include "fw_util.h"
#include "utils.h"
#include "log_msg.h"
#include "config_init.h" /* for the IS_EMPTY_LINE macro */
#include "extcmd.h"
#include "access.h"
static struct fw_config fwc;
static int
jump_rule_exists(int chain_num)
{
int num, pos = 0;
char cmd_buf[CMD_BUFSIZE] = {0};
char target[CMD_BUFSIZE] = {0};
char line_buf[CMD_BUFSIZE] = {0};
FILE *ipt;
sprintf(cmd_buf, "%s " IPT_LIST_RULES_ARGS,
fwc.fw_command,
fwc.chain[chain_num].table,
fwc.chain[chain_num].from_chain
);
ipt = popen(cmd_buf, "r");
if(ipt == NULL)
{
log_msg(LOG_ERR,
"Got error %i trying to get rules list.\n", errno);
return(-1);
}
while((fgets(line_buf, CMD_BUFSIZE-1, ipt)) != NULL)
{
/* Get past comments and empty lines (note: we only look at the
* first character).
*/
if(IS_EMPTY_LINE(line_buf[0]))
continue;
if(sscanf(line_buf, "%i %s ", &num, target) == 2)
{
if(strcmp(target, fwc.chain[chain_num].to_chain) == 0)
{
pos = num;
break;
}
}
}
pclose(ipt);
return(pos);
}
/* Print all firewall rules currently instantiated by the running fwknopd
* daemon to stdout.
*/
int
fw_dump_rules(fko_srv_options_t *opts)
{
int i;
int res, got_err = 0;
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
struct fw_chain *ch = opts->fw_config->chain;
printf("Listing rules in fwknop chains...\n");
for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++)
{
if(fwc.chain[i].target[0] == '\0')
continue;
/* Create the list command
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_LIST_RULES_ARGS,
opts->fw_config->fw_command,
ch[i].table,
ch[i].to_chain
);
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
res = system(cmd_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);
got_err++;
}
}
return(got_err);
}
/* Quietly flush and delete all fwknop custom chains.
*/
static void
delete_all_chains(void)
{
int i, res;
int jump_rule_num;
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++)
{
if(fwc.chain[i].target[0] == '\0')
continue;
/* First look for a jump rule to this chain and remove it if it
* is there.
*/
if((jump_rule_num = jump_rule_exists(i)) > 0)
{
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_DEL_RULE_ARGS,
fwc.fw_command,
fwc.chain[i].table,
fwc.chain[i].from_chain,
jump_rule_num
);
//printf("CMD: '%s'\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
memset(cmd_buf, 0x0, CMD_BUFSIZE);
/* Now flush and remove the chain.
*/
snprintf(cmd_buf, CMD_BUFSIZE-1,
"(%s " IPT_FLUSH_CHAIN_ARGS "; %s " IPT_DEL_CHAIN_ARGS ")", // > /dev/null 2>&1",
fwc.fw_command,
fwc.chain[i].table,
fwc.chain[i].to_chain,
fwc.fw_command,
fwc.chain[i].table,
fwc.chain[i].to_chain
);
//printf("CMD: '%s'\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
}
/* Create the fwknop custom chains (at least those that are configured).
*/
static int
create_fw_chains(void)
{
int i;
int res, got_err = 0;
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
for(i=0; i<(NUM_FWKNOP_ACCESS_TYPES); i++)
{
if(fwc.chain[i].target[0] == '\0')
continue;
/* 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
);
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
got_err++;
}
memset(cmd_buf, 0x0, CMD_BUFSIZE);
/* Then create the jump rule to that chain.
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_JUMP_RULE_ARGS,
fwc.fw_command,
fwc.chain[i].table,
fwc.chain[i].from_chain,
fwc.chain[i].jump_rule_pos,
fwc.chain[i].to_chain
);
//printf("(%i) CMD: '%s'\n", i, cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
/* Expect full success on this */
if(! EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
got_err++;
}
}
return(got_err);
}
static void
set_fw_chain_conf(int type, char *conf_str)
{
int i, j;
char tbuf[1024] = {0};
char *ndx = conf_str;
char *chain_fields[FW_NUM_CHAIN_FIELDS];
struct fw_chain *chain = &(fwc.chain[type]);
chain->type = type;
if(ndx != NULL)
chain_fields[0] = tbuf;
i = 0;
j = 1;
while(*ndx != '\0')
{
if(*ndx != ' ')
{
if(*ndx == ',')
{
tbuf[i] = '\0';
chain_fields[j++] = &(tbuf[++i]);
}
else
tbuf[i++] = *ndx;
}
ndx++;
}
/* Sanity check - j should be the number of chain fields
* (excluding the type).
*/
if(j != FW_NUM_CHAIN_FIELDS)
{
fprintf(stderr, "[*] Custom Chain config parse error.\n"
"Wrong number of fields for chain type %i\n"
"Line: %s\n", type, conf_str);
exit(EXIT_FAILURE);
}
/* Pull and set Target */
strlcpy(chain->target, chain_fields[0], MAX_TARGET_NAME_LEN);
/* Pull and set Direction
if(strcmp(chain_fields[1], FW_CHAIN_DIR_SRC_STR) == 0)
chain->direction = FW_CHAIN_DIR_SRC;
else if(strcmp(chain_fields[1], FW_CHAIN_DIR_DST_STR) == 0)
chain->direction = FW_CHAIN_DIR_DST;
else if(strcmp(chain_fields[1], FW_CHAIN_DIR_BOTH_STR) == 0)
chain->direction = FW_CHAIN_DIR_BOTH;
else
chain->direction = FW_CHAIN_DIR_UNKNOWN;
*/
/* Pull and set Table */
strlcpy(chain->table, chain_fields[1], MAX_TABLE_NAME_LEN);
/* Pull and set From_chain */
strlcpy(chain->from_chain, chain_fields[2], MAX_CHAIN_NAME_LEN);
/* Pull and set Jump_rule_position */
chain->jump_rule_pos = atoi(chain_fields[3]);
/* Pull and set To_chain */
strlcpy(chain->to_chain, chain_fields[4], MAX_CHAIN_NAME_LEN);
/* Pull and set Jump_rule_position */
chain->rule_pos = atoi(chain_fields[5]);
}
void
fw_config_init(fko_srv_options_t *opts)
{
memset(&fwc, 0x0, sizeof(struct fw_config));
/* Set our firewall exe command path (iptables in most cases).
*/
strlcpy(fwc.fw_command, opts->config[CONF_FIREWALL_EXE], MAX_PATH_LEN);
/* Pull the fwknop chain config info and setup our internal
* config struct. The IPT_INPUT is the only one that is
* required. The rest are optional.
*/
set_fw_chain_conf(IPT_INPUT_ACCESS, opts->config[CONF_IPT_INPUT_ACCESS]);
/* The FWKNOP_OUTPUT_ACCESS requires ENABLE_IPT_OUTPUT_ACCESS be Y
*/
if(strncasecmp(opts->config[CONF_ENABLE_IPT_OUTPUT], "Y", 1)==0)
set_fw_chain_conf(IPT_OUTPUT_ACCESS, opts->config[CONF_IPT_OUTPUT_ACCESS]);
/* The remaining access chains require ENABLE_IPT_FORWARDING = Y
*/
if(strncasecmp(opts->config[CONF_ENABLE_IPT_FORWARDING], "Y", 1)==0)
{
set_fw_chain_conf(IPT_FORWARD_ACCESS, opts->config[CONF_IPT_FORWARD_ACCESS]);
set_fw_chain_conf(IPT_DNAT_ACCESS, opts->config[CONF_IPT_DNAT_ACCESS]);
/* SNAT (whichever mode) requires ENABLE_IPT_SNAT = Y
*/
if(strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "Y", 1)==0)
{
/* If an SNAT_TRANSLATE_IP is specified use the SNAT_ACCESS mode.
* Otherwise, use MASQUERADE_ACCESS.
*
* XXX: --DSS: Not sure if using the TRANSLATE_IP parameter as
* the determining factor is the best why to handle
* this.
*
*/
if(opts->config[CONF_SNAT_TRANSLATE_IP] != NULL
&& strncasecmp(opts->config[CONF_SNAT_TRANSLATE_IP], "__CHANGEME__", 10)!=0)
set_fw_chain_conf(IPT_SNAT_ACCESS, opts->config[CONF_IPT_SNAT_ACCESS]);
else
set_fw_chain_conf(IPT_MASQUERADE_ACCESS, opts->config[CONF_IPT_MASQUERADE_ACCESS]);
}
}
/* Let us find it via our opts struct as well.
*/
opts->fw_config = &fwc;
return;
}
void
fw_initialize(void)
{
int res;
/* Flush the chains (just in case) so we can start fresh.
*/
delete_all_chains();
/* Now create any configured chains.
*/
res = create_fw_chains();
if(res != 0)
{
fprintf(stderr, "Warning: Errors detected during fwknop custom chain creation.\n");
exit(EXIT_FAILURE);
}
}
void
fw_cleanup(void)
{
delete_all_chains();
}
/****************************************************************************/
/* Rule Processing - Create an access request...
*/
int
process_spa_request(fko_srv_options_t *opts, spa_data_t *spadat)
{
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
char nat_ip[16] = {0};
char snat_target[SNAT_TARGET_BUFSIZE] = {0};
char *ndx;
unsigned int nat_port = 0;;
acc_port_list_t *port_list = NULL;
acc_port_list_t *ple;
unsigned int fst_proto;
unsigned int fst_port;
struct fw_chain *in_chain = &(opts->fw_config->chain[IPT_INPUT_ACCESS]);
struct fw_chain *out_chain = &(opts->fw_config->chain[IPT_OUTPUT_ACCESS]);
struct fw_chain *fwd_chain = &(opts->fw_config->chain[IPT_FORWARD_ACCESS]);
struct fw_chain *dnat_chain = &(opts->fw_config->chain[IPT_DNAT_ACCESS]);
struct fw_chain *snat_chain; /* We assign this later (if we need to). */
int res = 0;
time_t now;
unsigned int exp_ts;
/* Parse and expand our access message.
*/
expand_acc_port_list(&port_list, spadat->spa_message_remain);
/* Start at the top of the proto-port list...
*/
ple = port_list;
/* Remember the first proto/port combo in case we need them
* for NAT access requests.
*/
fst_proto = ple->proto;
fst_port = ple->port;
/* Set our expire time value.
*/
time(&now);
exp_ts = now + spadat->fw_access_timeout;
/* For straight access requests, we currently support multiple proto/port
* request.
*/
if(spadat->message_type == FKO_ACCESS_MSG
|| spadat->message_type == FKO_CLIENT_TIMEOUT_ACCESS_MSG)
{
/* Create an access command for each proto/port for the source ip.
*/
while(ple != NULL)
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_RULE_ARGS,
opts->fw_config->fw_command,
in_chain->table,
in_chain->to_chain,
ple->proto,
spadat->use_src_ip,
ple->port,
exp_ts,
in_chain->target
);
//--DSS tmp
//fprintf(stderr, "ADD CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added Rule to %s for %s, %s expires at %u",
in_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
in_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(in_chain->next_expire < now || exp_ts < in_chain->next_expire)
in_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
/* If we have to make an corresponding OUTPUT rule if out_chain target
* is not NULL.
*/
if(out_chain->to_chain != NULL && strlen(out_chain->to_chain))
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_OUT_RULE_ARGS,
opts->fw_config->fw_command,
out_chain->table,
out_chain->to_chain,
ple->proto,
spadat->use_src_ip,
ple->port,
exp_ts,
out_chain->target
);
//--DSS tmp
//fprintf(stderr, "ADD OUTPUT CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added OUTPUT Rule to %s for %s, %s expires at %u",
out_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
out_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(out_chain->next_expire < now || exp_ts < out_chain->next_expire)
out_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
ple = ple->next;
}
/* Done with the port list for access rules.
*/
free_acc_port_list(port_list);
}
/* NAT requests... */
else if( spadat->message_type == FKO_LOCAL_NAT_ACCESS_MSG
|| spadat->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG
|| spadat->message_type == FKO_NAT_ACCESS_MSG
|| spadat->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG )
{
/* Parse out the NAT IP and Port components.
*/
ndx = strchr(spadat->nat_access, ',');
if(ndx != NULL)
{
strlcpy(nat_ip, spadat->nat_access, (ndx-spadat->nat_access)+1);
nat_port = atoi(ndx+1);
}
// --DSS temp
//fprintf(stderr, "NAT IP: '%s', NAT PORT: '%i'\n", nat_ip, nat_port);
/* Make our FORWARD and NAT rules
*/
if(fwd_chain->to_chain != NULL && strlen(fwd_chain->to_chain))
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_FWD_RULE_ARGS,
opts->fw_config->fw_command,
fwd_chain->table,
fwd_chain->to_chain,
fst_proto,
spadat->use_src_ip,
nat_ip,
nat_port,
exp_ts,
fwd_chain->target
);
//--DSS tmp
//fprintf(stderr, "ADD OUTPUT CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added FORWARD Rule to %s for %s, %s expires at %u",
fwd_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
fwd_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(fwd_chain->next_expire < now || exp_ts < fwd_chain->next_expire)
fwd_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
if(dnat_chain->to_chain != NULL && strlen(dnat_chain->to_chain))
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_DNAT_RULE_ARGS,
opts->fw_config->fw_command,
dnat_chain->table,
dnat_chain->to_chain,
fst_proto,
spadat->use_src_ip,
fst_port,
exp_ts,
dnat_chain->target,
nat_ip,
nat_port
);
//--DSS tmp
//fprintf(stderr, "ADD DNAT CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added DNAT Rule to %s for %s, %s expires at %u",
dnat_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
dnat_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(dnat_chain->next_expire < now || exp_ts < dnat_chain->next_expire)
dnat_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
/* If SNAT (or MASQUERADE) is wanted, then we add those rules here as well.
*/
if(strncasecmp(opts->config[CONF_ENABLE_IPT_SNAT], "Y", 1) == 0)
{
memset(cmd_buf, 0x0, CMD_BUFSIZE);
/* Setup some parameter depending on whether we are using SNAT
* or MASQUERADE.
*/
if(strncasecmp(opts->config[CONF_SNAT_TRANSLATE_IP], "__CHANGEME__", 10)!=0)
{
/* Using static SNAT */
snat_chain = &(opts->fw_config->chain[IPT_SNAT_ACCESS]);
snprintf(snat_target, SNAT_TARGET_BUFSIZE-1,
"--to-source %s:%i", opts->config[CONF_SNAT_TRANSLATE_IP],
fst_port);
}
else
{
/* Using MASQUERADE */
snat_chain = &(opts->fw_config->chain[IPT_MASQUERADE_ACCESS]);
snprintf(snat_target, SNAT_TARGET_BUFSIZE-1,
"--to-ports %i", fst_port);
}
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_SNAT_RULE_ARGS,
opts->fw_config->fw_command,
snat_chain->table,
snat_chain->to_chain,
fst_proto,
nat_ip,
nat_port,
exp_ts,
snat_chain->target,
snat_target
);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
if(EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_INFO, "Added Source NAT Rule to %s for %s, %s expires at %u",
snat_chain->to_chain, spadat->use_src_ip,
spadat->spa_message_remain, exp_ts
);
snat_chain->active_rules++;
/* Reset the next expected expire time for this chain if it
* is warranted.
*/
if(snat_chain->next_expire < now || exp_ts < snat_chain->next_expire)
snat_chain->next_expire = exp_ts;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
}
return(res);
}
/* Iterate over the configure firewall access chains and purge expired
* firewall rules.
*/
void
check_firewall_rules(fko_srv_options_t *opts)
{
char cmd_buf[CMD_BUFSIZE] = {0};
char err[CMD_BUFSIZE] = {0};
char cmd_out[STANDARD_CMD_OUT_BUFSIZE];
char exp_str[12];
char rule_num_str[6];
char *ndx, *rn_start, *rn_end, *tmp_mark;
int i, res, rn_offset;
time_t now, rule_exp, min_exp = 0;
struct fw_chain *ch = opts->fw_config->chain;
time(&now);
/* Iterate over each chain and look for active rules to delete.
*/
for(i = 0; i < NUM_FWKNOP_ACCESS_TYPES; i++)
{
/* Just in case we somehow lose track and fall out-of-whack,
* we be the hero and reset it to zero.
* (poet but don't know it :-o )
*/
if(ch[i].active_rules < 0)
ch[i].active_rules = 0;
/* If there are no active rules or we have not yet
* reached our expected next expire time, continue.
*/
if(ch[i].active_rules == 0 || ch[i].next_expire > now)
continue;
rn_offset = 0;
/* There should be a rule to delete. Get the current list of
* rules for this chain and delete the ones that are expired.
*/
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_LIST_RULES_ARGS,
opts->fw_config->fw_command,
ch[i].table,
ch[i].to_chain
);
memset(cmd_out, 0x0, STANDARD_CMD_OUT_BUFSIZE);
res = run_extcmd(cmd_buf, cmd_out, STANDARD_CMD_OUT_BUFSIZE, 0);
if(!EXTCMD_IS_SUCCESS(res))
{
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, cmd_out);
continue;
}
if(opts->verbose > 2)
log_msg(LOG_INFO, "RES=%i, CMD_BUF: %s\nRULES LIST: %s", res, cmd_buf, cmd_out);
ndx = strstr(cmd_out, "_exp_");
if(ndx == NULL)
{
/* we did not find an expected rule.
*/
log_msg(LOG_ERR,
"Did not find expire comment in rules list %i.\n", i);
ch[i].active_rules--;
continue;
}
/* walk the list and process rules as needed.
*/
while (ndx != NULL) {
/* Jump forward and extract the timestamp
*/
ndx +=5;
/* remember this spot for when we look for the next
* rule.
*/
tmp_mark = ndx;
strlcpy(exp_str, ndx, 11);
rule_exp = (time_t)atoll(exp_str);
//fprintf(stderr, "RULE_EXP=%u, NOW=%u\n", rule_exp, now);
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);
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);
ch[i].active_rules--;
break;
}
strlcpy(rule_num_str, rn_start, (rn_end - rn_start)+1);
memset(cmd_buf, 0x0, CMD_BUFSIZE);
snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_DEL_RULE_ARGS,
opts->fw_config->fw_command,
ch[i].table,
ch[i].to_chain,
atoi(rule_num_str) - rn_offset
);
//fprintf(stderr, "DELETE RULE CMD: %s\n", cmd_buf);
res = run_extcmd(cmd_buf, err, CMD_BUFSIZE, 0);
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++;
ch[i].active_rules--;
}
else
log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err);
}
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, "_exp_");
}
/* Set the next pending expire time accordingly. 0 if there are no
* more rules, or whatever the next expected (min_exp) time will be.
*/
if(ch[i].active_rules < 1)
ch[i].next_expire = 0;
else if(min_exp)
ch[i].next_expire = min_exp;
}
}
#endif /* FIREWALL_IPTABLES */
/***EOF***/

47
server/fw_util_iptables.h Normal file
View File

@@ -0,0 +1,47 @@
/* $Id$
*****************************************************************************
*
* File: fw_util_iptables.h
*
* Author: Damien Stuart (dstuart@dstuart.org)
*
* Purpose: Header file for fw_util_iptables.c.
*
* Copyright (C) 2010 Damien Stuart (dstuart@dstuart.org)
*
* License (GNU Public License):
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#ifndef FW_UTIL_IPTABLES_H
#define FW_UTIL_IPTABLES_H
#define SNAT_TARGET_BUFSIZE 64
/* iptables command args
*/
#define IPT_ADD_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s 2>&1"
#define IPT_ADD_OUT_RULE_ARGS "-t %s -A %s -p %i -d %s --sport %i -m comment --comment _exp_%u -j %s 2>&1"
#define IPT_ADD_FWD_RULE_ARGS "-t %s -A %s -p %i -s %s -d %s --dport %i -m comment --comment _exp_%u -j %s 2>&1"
#define IPT_ADD_DNAT_RULE_ARGS "-t %s -A %s -p %i -s %s --dport %i -m comment --comment _exp_%u -j %s --to-destination %s:%i 2>&1"
#define IPT_ADD_SNAT_RULE_ARGS "-t %s -A %s -p %i -d %s --dport %i -m comment --comment _exp_%u -j %s %s 2>&1"
#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_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"
#endif /* FW_UTIL_IPTABLES_H */
/***EOF***/

View File

@@ -585,12 +585,12 @@ write_pid_file(fko_srv_options_t *opts)
* error, another instance already has the lock. So we grab
* the pid from the existing lock file, complain and bail.
*/
lck_res = flock(op_fd, LOCK_EX|LOCK_NB);
lck_res = lockf(op_fd, F_TLOCK, 0);
if(lck_res == -1)
{
if(errno != EWOULDBLOCK)
if(errno != EAGAIN)
{
perror("Unexpected error from flock: ");
perror("Unexpected error from lockf: ");
return -1;
}

View File

@@ -259,6 +259,6 @@
# System binaries
#
#EXE_IPTABLES /sbin/iptables;
#FIREWALL_EXE /sbin/iptables;
###EOF###

View File

@@ -160,8 +160,7 @@ enum {
CONF_ACCESS_FILE,
CONF_FWKNOP_PID_FILE,
CONF_DIGEST_FILE,
CONF_EXE_IPTABLES,
CONF_EXE_IPFW,
CONF_FIREWALL_EXE,
CONF_GPG_HOME_DIR,
@@ -220,8 +219,7 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = {
"ACCESS_FILE",
"FWKNOP_PID_FILE",
"DIGEST_FILE",
"EXE_IPTABLES",
"EXE_IPFW",
"FIREWALL_EXE",
"GPG_HOME_DIR",
};

View File

@@ -76,7 +76,9 @@ pcap_capture(fko_srv_options_t *opts)
/* We are only interested on seeing packets coming into the interface.
*/
if (pcap_setdirection(pcap, PCAP_D_IN) < 0)
log_msg(LOG_WARNING, "* Warning: pcap error on setdirection");
if(opts->verbose)
log_msg(LOG_WARNING, "* Warning: pcap error on setdirection: %s.",
pcap_geterr(pcap));
if (pcap == NULL)
{