Add INPUT ACCEPT rule for --nat-local connections
authorMichael Rash <mbr@cipherdyne.org>
Mon, 16 Jul 2012 01:32:14 +0000 (21:32 -0400)
committerMichael Rash <mbr@cipherdyne.org>
Mon, 16 Jul 2012 01:32:14 +0000 (21:32 -0400)
When using the --nat-local argument on the fwknop client command line, the
fwknopd server needs to add an INPUT ACCEPT rule for the requested access
since the incoming connection is destined for a local socket.  Added test
suite support to test --nat-local access.

[test suite] Minor bug fix to ensure that all file_find_regex() calls return
true if all regex's are matched and false if any regex does not match data in
the specified file.

client/fwknop.c
server/fw_util_iptables.c
test/test-fwknop.pl

index 687f5a0..040c3ff 100644 (file)
@@ -664,22 +664,19 @@ set_message_type(fko_ctx_t ctx, fko_cli_options_t *options)
     {
         message_type = FKO_COMMAND_MSG;
     }
+    else if(options->nat_local)
+    {
+        if (options->fw_timeout >= 0)
+            message_type = FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG;
+        else
+            message_type = FKO_LOCAL_NAT_ACCESS_MSG;
+    }
     else if(options->nat_access_str[0] != 0x0)
     {
-        if (options->nat_local)
-        {
-            if (options->fw_timeout >= 0)
-                message_type = FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG;
-            else
-                message_type = FKO_LOCAL_NAT_ACCESS_MSG;
-        }
+        if (options->fw_timeout >= 0)
+            message_type = FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG;
         else
-        {
-            if (options->fw_timeout >= 0)
-                message_type = FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG;
-            else
-                message_type = FKO_NAT_ACCESS_MSG;
-        }
+            message_type = FKO_NAT_ACCESS_MSG;
     }
     else
     {
index a1a36ec..555eef2 100644 (file)
@@ -650,6 +650,49 @@ process_spa_request(const fko_srv_options_t *opts, const acc_stanza_t *acc, spa_
                 nat_port = atoi(ndx+1);
             }
         }
+    
+        if(spadat->message_type == FKO_LOCAL_NAT_ACCESS_MSG)
+        {
+            /* Need to add an ACCEPT rule into the INPUT chain
+            */
+            zero_cmd_buffers();
+
+            snprintf(cmd_buf, CMD_BUFSIZE-1, "%s " IPT_ADD_RULE_ARGS,
+                opts->fw_config->fw_command,
+                in_chain->table,
+                in_chain->to_chain,
+                fst_proto,
+                spadat->use_src_ip,
+                nat_port,
+                exp_ts,
+                in_chain->target
+            );
+
+            res = run_extcmd(cmd_buf, err_buf, CMD_BUFSIZE, 0);
+
+            if (opts->verbose)
+                log_msg(LOG_INFO, "process_spa_request() CMD: '%s' (res: %d, err: %s)",
+                    cmd_buf, res, err_buf);
+
+            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_buf);
+
+        }
 
         /* Make our FORWARD and NAT rules
         */
index ae9a642..447d2c0 100755 (executable)
@@ -27,6 +27,7 @@ my $future_expired_access_conf = "$conf_dir/future_expired_stanza_access.conf";
 my $expired_epoch_access_conf = "$conf_dir/expired_epoch_stanza_access.conf";
 my $invalid_expire_access_conf = "$conf_dir/invalid_expire_access.conf";
 my $force_nat_access_conf = "$conf_dir/force_nat_access.conf";
+my $local_nat_fwknopd_conf = "$conf_dir/local_nat_fwknopd.conf";
 my $dual_key_usage_access_conf = "$conf_dir/dual_key_usage_access.conf";
 my $gpg_access_conf     = "$conf_dir/gpg_access.conf";
 my $default_digest_file = "$run_dir/digest.cache";
@@ -931,7 +932,6 @@ my @tests = (
         'server_conf' => $nat_conf,
         'fatal'    => $NO
     },
-
     {
         'category' => 'Rijndael SPA',
         'subcategory' => 'client+server',
@@ -949,7 +949,24 @@ my @tests = (
         'server_conf' => $nat_conf,
         'fatal'    => $NO
     },
-
+    {
+        'category' => 'Rijndael SPA',
+        'subcategory' => 'client+server',
+        'detail'   => "local NAT $force_nat_host (tcp/22 ssh)",
+        'err_msg'  => "could not complete NAT SPA cycle",
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args --nat-local",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $local_nat_fwknopd_conf -a $force_nat_access_conf " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [qr/to\:$force_nat_host\:22/i,
+            qr/FWKNOP_INPUT.*dport\s22.*\sACCEPT/],
+        'server_negative_output_matches' => [qr/to\:$internal_nat_host\:22/i],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'server_conf' => $nat_conf,
+        'fatal'    => $NO
+    },
     {
         'category' => 'Rijndael SPA',
         'subcategory' => 'client+server',
@@ -1490,7 +1507,8 @@ sub compile_warnings() {
 
     ### look for compilation warnings - something like:
     ###     warning: ‘test’ is used uninitialized in this function
-    return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/], $current_test_file);
+    return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/],
+        $current_test_file);
 
     ### the new binaries should exist
     unless (-e $fwknopCmd and -x $fwknopCmd) {
@@ -2089,7 +2107,7 @@ sub client_server_interaction() {
 
     if (&is_fwknopd_running()) {
         &stop_fwknopd();
-        unless (&file_find_regex([qr/Got\sSIGTERM/, qr/^Terminated/],
+        unless (&file_find_regex([qr/Got\sSIGTERM/],
                 $server_test_file)) {
             $server_was_stopped = 0;
         }
@@ -2702,34 +2720,37 @@ sub stop_fwknopd() {
 sub file_find_regex() {
     my ($re_ar, $file) = @_;
 
-    my $found = 0;
+    my $found_all_regexs = 1;
     my @write_lines = ();
+    my @file_lines = ();
 
     open F, "< $file" or die "[*] Could not open $file: $!";
-    LINE: while (<F>) {
-        my $line = $_;
-        next LINE if $line =~ /file_file_regex\(\)/;
-        for my $re (@$re_ar) {
+    while (<F>) {
+        push @file_lines, $_;
+    }
+    close F;
+
+    for my $re (@$re_ar) {
+        my $matched = 0;
+        for my $line (@file_lines) {
             if ($line =~ $re) {
                 push @write_lines, "[.] file_find_regex() " .
                     "Matched '$re' with line: $line";
-                $found = 1;
-                last LINE;
+                $matched = 1;
             }
         }
+        unless ($matched) {
+            push @write_lines, "[.] file_find_regex() " .
+                "Did not match any regex in '@$re_ar' in file: $file\n";
+            $found_all_regexs = 0;
+        }
     }
-    close F;
 
-    if ($found) {
-        for my $line (@write_lines) {
-            &write_test_file($line, $file);
-        }
-    } else {
-        &write_test_file("[.] find_find_regex() Did not " .
-            "match any regex in: '@$re_ar'\n", $file);
+    for my $line (@write_lines) {
+        &write_test_file($line, $file);
     }
 
-    return $found;
+    return $found_all_regexs;
 }
 
 sub find_command() {