Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactored firewall rule code to separate files by firewall type. Stu…

…bbed 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
  • Loading branch information...
commit 838b80fd7d7b822cfeecce9f2dc34c6ca49f68cd 1 parent c1f67b9
Damien Stuart authored
View
7 common/netinet_common.h
@@ -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
74 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],
+
+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@:>@])],
[
- AC_DEFINE_UNQUOTED([IPFW_EXE], ["$IPFW_EXE"], [Path to ipfw executable])
- ipfw_exe=$IPFW_EXE
- ], [ ipfw_exe="(not found)"]
- )],
+ 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
4 server/Makefile.am
@@ -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
16 server/config_init.c
@@ -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
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);
-}
-*/
-
-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.
+/* --DSS This is a place holder for now. We may put the generalized external
+ * firewall script code here ( or not).
*/
-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
26 server/fw_util.h
@@ -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 */
View
172 server/fw_util_ipf.c
@@ -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***/
View
43 server/fw_util_ipf.h
@@ -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***/
View
173 server/fw_util_ipfw.c
@@ -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***/
View
43 server/fw_util_ipfw.h
@@ -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***/
View
881 server/fw_util_iptables.c
@@ -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***/
View
47 server/fw_util_iptables.h
@@ -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_IPTABLE