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:
@@ -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
|
||||
|
||||
|
||||
76
configure.ac
76
configure.ac
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
895
server/fw_util.c
895
server/fw_util.c
@@ -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***/
|
||||
|
||||
@@ -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
172
server/fw_util_ipf.c
Normal 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
43
server/fw_util_ipf.h
Normal 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
173
server/fw_util_ipfw.c
Normal 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
43
server/fw_util_ipfw.h
Normal 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
881
server/fw_util_iptables.c
Normal 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
47
server/fw_util_iptables.h
Normal 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***/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -259,6 +259,6 @@
|
||||
|
||||
# System binaries
|
||||
#
|
||||
#EXE_IPTABLES /sbin/iptables;
|
||||
#FIREWALL_EXE /sbin/iptables;
|
||||
|
||||
###EOF###
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user