[server] iptables 'comment' match check
authorMichael Rash <mbr@cipherdyne.org>
Sun, 12 Aug 2012 19:44:13 +0000 (15:44 -0400)
committerMichael Rash <mbr@cipherdyne.org>
Sun, 12 Aug 2012 19:44:13 +0000 (15:44 -0400)
Implemented a new check to ensure that the iptables 'comment' match exists to
ensure the proper environment for fwknopd operations.  This check is controlled
by the new ENABLE_IPT_COMMENT_CHECK variable, and was suggested by Hank
Leininger.

CREDITS
ChangeLog
server/cmd_opts.h
server/config_init.c
server/fw_util.h
server/fw_util_iptables.c
server/fw_util_iptables.h
server/fwknopd.conf
server/fwknopd_common.h
todo.org

diff --git a/CREDITS b/CREDITS
index 0e1ba85..ab6edd0 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -48,3 +48,8 @@ Geoff Carstairs
       This allows for better access control for multple users requiring access
       to multiple internal systems, in a manner that is transparent to the
       user.  The result was the FORCE_NAT mode.
+
+Hank Leininger
+    - For iptables firewalls, suggested a check for the 'comment' match to
+      ensure the local environment will properly support fwknopd operations.
+      The result is the new ENABLE_IPT_COMMENT_CHECK functionality.
index dc0027e..326a23e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -58,6 +58,10 @@ fwknop-2.0.2 (08//2012):
 
     - [test suite] Added GPG tests for keyrings that have no associated
       passphrases.
+    - [server] Implemented a new check to ensure that the iptables 'comment'
+      match exists to ensure the proper environment for fwknopd operations.
+      This check is controlled by the new ENABLE_IPT_COMMENT_CHECK variable,
+      and was suggested by Hank Leininger.
 
 fwknop-2.0.1 (07/23/2012):
     - [server] Bug fix where the same encryption key used for two stanzas in
index 05dc9ca..0abe85d 100644 (file)
@@ -78,6 +78,7 @@ static char *config_map[NUMBER_OF_CONFIG_ENTRIES] = {
     "IPT_DNAT_ACCESS",
     "IPT_SNAT_ACCESS",
     "IPT_MASQUERADE_ACCESS",
+    "ENABLE_IPT_COMMENT_CHECK",
 #elif FIREWALL_IPFW
     "FLUSH_IPFW_AT_INIT",
     "FLUSH_IPFW_AT_EXIT",
index f83ce20..2ac667a 100644 (file)
@@ -458,6 +458,12 @@ validate_options(fko_srv_options_t *opts)
         set_config_entry(opts, CONF_IPT_MASQUERADE_ACCESS,
             DEF_IPT_MASQUERADE_ACCESS);
 
+    /* Check for the iptables 'comment' match at init time
+    */
+    if(opts->config[CONF_ENABLE_IPT_COMMENT_CHECK] == NULL)
+        set_config_entry(opts, CONF_ENABLE_IPT_COMMENT_CHECK,
+            DEF_ENABLE_IPT_COMMENT_CHECK);
+
 #elif FIREWALL_IPFW
 
     /* Flush ipfw rules at init.
index 1f520fe..f958388 100644 (file)
@@ -37,6 +37,7 @@
 #define STANDARD_CMD_OUT_BUFSIZE    4096
 
 #define EXPIRE_COMMENT_PREFIX "_exp_"
+#define TMP_COMMENT "__TMPCOMMENT__"
 
 #if FIREWALL_IPTABLES
   #include "fw_util_iptables.h"
index 8e11470..ad1648a 100644 (file)
@@ -53,6 +53,70 @@ zero_cmd_buffers(void)
 }
 
 static int
+comment_match_exists(const fko_srv_options_t *opts)
+{
+    int               res = 1;
+    char             *ndx = NULL;
+    struct fw_chain  *in_chain  = &(opts->fw_config->chain[IPT_INPUT_ACCESS]);
+
+    zero_cmd_buffers();
+
+    /* Add a harmless rule to the iptables OUTPUT chain that uses the comment
+     * match and make sure it exists.  If not, return zero.  Otherwise, delete
+     * the rule and return true.
+    */
+    snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_TMP_COMMENT_ARGS,
+        opts->fw_config->fw_command,
+        in_chain->table,
+        in_chain->to_chain,
+        1,   /* first rule */
+        in_chain->target
+    );
+
+    res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
+
+    if (opts->verbose)
+        log_msg(LOG_INFO, "comment_match_exists() CMD: '%s' (res: %d, err: %s)",
+                cmd_buf, res, err_buf);
+
+    zero_cmd_buffers();
+
+    snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_LIST_RULES_ARGS,
+        opts->fw_config->fw_command,
+        in_chain->table,
+        in_chain->to_chain
+    );
+
+    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);
+
+    ndx = strstr(cmd_out, TMP_COMMENT);
+    if(ndx == NULL)
+        res = 0;  /* did not find the tmp comment */
+    else
+        res = 1;
+
+    if(res == 1)
+    {
+        /* Delete the tmp comment rule
+        */
+        zero_cmd_buffers();
+
+        snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_DEL_RULE_ARGS,
+            opts->fw_config->fw_command,
+            in_chain->table,
+            in_chain->to_chain,
+            1
+        );
+        run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
+    }
+
+    return res;
+}
+
+static int
 add_jump_rule(const fko_srv_options_t *opts, const int chain_num)
 {
     int res = 0;
@@ -205,7 +269,7 @@ fw_dump_rules(const fko_srv_options_t *opts)
             /* Expect full success on this */
             if(! EXTCMD_IS_SUCCESS(res))
             {
-                log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf); 
+                log_msg(LOG_ERR, "Error %i from cmd:'%s': %s", res, cmd_buf, err_buf);
                 got_err++;
             }
         }
@@ -466,6 +530,15 @@ fw_initialize(const fko_srv_options_t *opts)
         fprintf(stderr, "Warning: Errors detected during fwknop custom chain creation.\n");
         exit(EXIT_FAILURE);
     }
+
+    /* Make sure that the 'comment' match is available
+    */
+    if((strncasecmp(opts->config[CONF_ENABLE_IPT_COMMENT_CHECK], "Y", 1) == 0)
+            && (comment_match_exists(opts) != 1))
+    {
+        fprintf(stderr, "Warning: Could not use the 'comment' match.\n");
+        exit(EXIT_FAILURE);
+    }
 }
 
 int
index d8ef36b..9c706e5 100644 (file)
@@ -40,6 +40,7 @@
 #define IPT_ADD_FWD_RULE_ARGS   "-t %s -A %s -p %i -s %s -d %s --dport %i -m comment --comment " EXPIRE_COMMENT_PREFIX "%u -j %s 2>&1"
 #define IPT_ADD_DNAT_RULE_ARGS  "-t %s -A %s -p %i -s %s --dport %i -m comment --comment " EXPIRE_COMMENT_PREFIX "%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 " EXPIRE_COMMENT_PREFIX "%u -j %s %s 2>&1"
+#define IPT_TMP_COMMENT_ARGS    "-t %s -I %s %i -s 127.0.0.2 -m comment --comment " TMP_COMMENT " -j %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"
index 6aed85e..c8afc08 100644 (file)
 #IPT_SNAT_ACCESS         SNAT, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1;
 #IPT_MASQUERADE_ACCESS   MASQUERADE, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1;
 
+# The ENABLE_COMMENT_MATCH_CHECK variable instructs fwknopd to check for the
+# iptables 'comment' match at start up.  If it's not found, then fwknopd will
+# exit and throw an error.  This variable is enabled by default, but can be
+# disabled if you want fwknopd to run without being sure that the comment match
+# if available (not recommended, since the comment match enables new SPA rules
+# to be timed out).
+#
+#ENABLE_IPT_COMMENT_CHECK        Y;
+
 ##############################################################################
 # Parameters specific to ipfw:
 #
index 3ba797d..a6f0655 100644 (file)
 */
 #if FIREWALL_IPTABLES
 
-  #define DEF_FLUSH_IPT_AT_INIT     "Y"
-  #define DEF_FLUSH_IPT_AT_EXIT     "Y"
-  #define DEF_ENABLE_IPT_FORWARDING "N"
-  #define DEF_ENABLE_IPT_LOCAL_NAT  "Y"
-  #define DEF_ENABLE_IPT_SNAT       "N"
-  #define DEF_ENABLE_IPT_OUTPUT     "N"
-  #define DEF_IPT_INPUT_ACCESS      "ACCEPT, filter, INPUT, 1, FWKNOP_INPUT, 1"
-  #define DEF_IPT_OUTPUT_ACCESS     "ACCEPT, filter, OUTPUT, 1, FWKNOP_OUTPUT, 1"
-  #define DEF_IPT_FORWARD_ACCESS    "ACCEPT, filter, FORWARD, 1, FWKNOP_FORWARD, 1"
-  #define DEF_IPT_DNAT_ACCESS       "DNAT, nat, PREROUTING, 1, FWKNOP_PREROUTING, 1"
-  #define DEF_IPT_SNAT_ACCESS       "SNAT, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1"
-  #define DEF_IPT_MASQUERADE_ACCESS "MASQUERADE, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1"
+  #define DEF_FLUSH_IPT_AT_INIT         "Y"
+  #define DEF_FLUSH_IPT_AT_EXIT         "Y"
+  #define DEF_ENABLE_IPT_FORWARDING     "N"
+  #define DEF_ENABLE_IPT_LOCAL_NAT      "Y"
+  #define DEF_ENABLE_IPT_SNAT           "N"
+  #define DEF_ENABLE_IPT_OUTPUT         "N"
+  #define DEF_ENABLE_IPT_COMMENT_CHECK  "Y"
+  #define DEF_IPT_INPUT_ACCESS          "ACCEPT, filter, INPUT, 1, FWKNOP_INPUT, 1"
+  #define DEF_IPT_OUTPUT_ACCESS         "ACCEPT, filter, OUTPUT, 1, FWKNOP_OUTPUT, 1"
+  #define DEF_IPT_FORWARD_ACCESS        "ACCEPT, filter, FORWARD, 1, FWKNOP_FORWARD, 1"
+  #define DEF_IPT_DNAT_ACCESS           "DNAT, nat, PREROUTING, 1, FWKNOP_PREROUTING, 1"
+  #define DEF_IPT_SNAT_ACCESS           "SNAT, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1"
+  #define DEF_IPT_MASQUERADE_ACCESS     "MASQUERADE, nat, POSTROUTING, 1, FWKNOP_POSTROUTING, 1"
 
 /* Ipfw-specific defines
 */
@@ -201,6 +202,7 @@ enum {
     CONF_IPT_DNAT_ACCESS,
     CONF_IPT_SNAT_ACCESS,
     CONF_IPT_MASQUERADE_ACCESS,
+    CONF_ENABLE_IPT_COMMENT_CHECK,
 #elif FIREWALL_IPFW
     CONF_FLUSH_IPFW_AT_INIT,
     CONF_FLUSH_IPFW_AT_EXIT,
index 78ca683..322b01d 100644 (file)
--- a/todo.org
+++ b/todo.org
@@ -1,6 +1,9 @@
 * fwknop tasks
   This is the main todo org mode file for the fwknop project
-** fwknopd iptables comment match detection
+** COMPLETED
+   This bucket is for completed tasks.
+*** fwknopd iptables comment match detection
+    :CLOSED: <2012-08-12 Sun>
    Hank Leininger suggested that fwknopd do better detection for the iptables
    comment match since it is required for the expiration of SPA rules.
 ** Include files for access.conf