[client] --nat-rand-port bug fix
authorMichael Rash <mbr@cipherdyne.org>
Sat, 16 Mar 2013 18:38:20 +0000 (14:38 -0400)
committerMichael Rash <mbr@cipherdyne.org>
Sat, 16 Mar 2013 18:38:20 +0000 (14:38 -0400)
Bug fix for --nat-rand-port mode to ensure that the port to be
NAT'd is properly defined so that the fwknopd server will NAT
connnections to this port instead of applying the NAT operation to the
port that is to be accessed via -A.  This change also prints the
randomly assigned port to stdout regardless of whether --verbose mode is
used (since it not then the user will have no idea which port is
actually going to be NAT'd on the fwknopd side).

ChangeLog
Makefile.am
client/fwknop.c
test/conf/fwknoprc_hmac_sha512_long_key [new file with mode: 0644]
test/conf/hmac_force_nat_access.conf [new file with mode: 0644]
test/conf/hmac_sha256_open_ports_access.conf [new file with mode: 0644]
test/conf/hmac_sha512_long_key_access.conf [new file with mode: 0644]
test/test-fwknop.pl
test/tests/rijndael.pl
test/tests/rijndael_hmac.pl

index cc29b3e..63ab84e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,9 @@
 fwknop-2.5 (//2013):
-    - Major release of new functionality - HMAC SHA-256 support in the
-      encrypt-then-authenticate model.
+    - Major release of new functionality - HMAC support in the encrypt-then-
+      authenticate model.  Supported HMAC digests include MD5, SHA1, SHA256,
+      SHA384, and SHA512.  The default is HMAC-SHA256 when HMAC is used.
     - [libfko] Significant bug fix to honor the full encryption key length for
-      user-supplied Rijndael keys > 16 bytes long.  Previous to this bug fix,
+      user-supplied Rijndael keys > 16 bytes long.  Previous to this fix,
       only the first 16 bytes of a key were actually used in the encryption/
       decryption process even if the supplied key was longer.  The result was
       a weakening of expected security for users that had keys > 16 bytes,
@@ -13,8 +14,8 @@ fwknop-2.5 (//2013):
       the passphrase and a random salt.  This issue was reported by Michael T.
       Dean.  Closes issue #18 on github.
     - [libfko] Added the ability to maintain backwards compatibility with the
-      now deprecated "zero padding" strategy in AES mode that was a hold over
-      from the old perl fwknop implementation.
+      now deprecated "zero padding" key derivation strategy in AES mode that
+      was a hold over from the old perl fwknop implementation.
     - [test suite] Added --enable-openssl-checks to send all SPA packets
       encrypted via libfko through the OpenSSL library to ensure that the
       libfko usage of AES is always compatible with OpenSSL.  This ensures
@@ -23,6 +24,13 @@ fwknop-2.5 (//2013):
       engine.  If a vulnerability is discovered in OpenSSL and a change is
       made, then the --enable-openssl-checks mode will allow the test suite to
       discover this in a automated fashion for fwknop.
+    - [client] Bug fix for --nat-rand-port mode to ensure that the port to be
+      NAT'd is properly defined so that the fwknopd server will NAT
+      connnections to this port instead of applying the NAT operation to the
+      port that is to be accessed via -A.  This change also prints the
+      randomly assigned port to stdout regardless of whether --verbose mode is
+      used (since it not then the user will have no idea which port is
+      actually going to be NAT'd on the fwknopd side).
     - (Vlad Glagolev) Submitted an OpenBSD port for fwknop-2.0.4, and this has
       been checked in under the extras/openbsd/fwknop-2.0.4 directory.
 
index 94f3a19..a1a76e1 100644 (file)
@@ -162,6 +162,7 @@ EXTRA_DIST = \
     test/conf/hmac_sha512_access.conf \
     test/conf/hmac_sha512_short_key_access.conf \
     test/conf/hmac_simple_keys_access.conf \
+    test/conf/hmac_sha256_open_ports_access.conf \
     test/conf/fwknoprc_default_hmac_base64_key \
     test/conf/fwknoprc_hmac_invalid_type \
     test/conf/fwknoprc_hmac_md5_key \
index 67eaf34..2f0adba 100644 (file)
@@ -52,7 +52,10 @@ static void save_args(int argc, char **argv, const char * const args_save_file);
 static void run_last_args(fko_cli_options_t *options,
         const char * const args_save_file);
 static int set_message_type(fko_ctx_t ctx, fko_cli_options_t *options);
-static int set_nat_access(fko_ctx_t ctx, fko_cli_options_t *options);
+static int set_nat_access(fko_ctx_t ctx, fko_cli_options_t *options,
+        const char * const access_buf);
+static void set_access_buf(fko_ctx_t ctx, fko_cli_options_t *options,
+        char *access_buf);
 static int get_rand_port(fko_ctx_t ctx);
 int resolve_ip_http(fko_cli_options_t *options);
 static void clean_exit(fko_ctx_t ctx, fko_cli_options_t *opts,
@@ -213,16 +216,7 @@ main(int argc, char **argv)
          * to be specified as well, so in this case append the string
          * "none/0" to the allow IP.
         */
-        if(options.access_str[0] != 0x0)
-        {
-            snprintf(access_buf, MAX_LINE_LEN, "%s%s%s",
-                    options.allow_ip_str, ",", options.access_str);
-        }
-        else
-        {
-            snprintf(access_buf, MAX_LINE_LEN, "%s%s%s",
-                    options.allow_ip_str, ",", "none/0");
-        }
+        set_access_buf(ctx, &options, access_buf);
     }
     res = fko_set_spa_message(ctx, access_buf);
     if(res != FKO_SUCCESS)
@@ -236,7 +230,7 @@ main(int argc, char **argv)
     */
     if (options.nat_local || options.nat_access_str[0] != 0x0)
     {
-        res = set_nat_access(ctx, &options);
+        res = set_nat_access(ctx, &options, access_buf);
         if(res != FKO_SUCCESS)
         {
             errmsg("fko_set_nat_access_str", res);
@@ -529,7 +523,7 @@ static int
 get_rand_port(fko_ctx_t ctx)
 {
     char *rand_val = NULL;
-    char  port_str[6];
+    char  port_str[MAX_PORT_STR_LEN+1];
     int   tmpint, is_err;
     int   port     = 0;
     int   res      = 0;
@@ -601,25 +595,119 @@ ipv4_str_has_port(char *str)
     return 0;
 }
 
+/* Set access buf
+*/
+static void
+set_access_buf(fko_ctx_t ctx, fko_cli_options_t *options, char *access_buf)
+{
+    char   *ndx = NULL, tmp_nat_port[MAX_PORT_STR_LEN+1] = {0};
+    int     nat_port = 0;
+
+    memset(tmp_nat_port, 0x0, MAX_PORT_STR_LEN+1);
+
+    if(options->access_str[0] != 0x0)
+    {
+        if (options->nat_rand_port)
+        {
+            nat_port = get_rand_port(ctx);
+            options->nat_port = nat_port;
+        }
+        else if (options->nat_port)
+            nat_port = options->nat_port;
+
+        if(nat_port > 0 && nat_port <= MAX_PORT)
+        {
+            /* Replace the access string port with the NAT port since the
+             * NAT port is manually specified (--nat-port) or derived from
+             * random data (--nat-rand-port).  In the NAT modes, the fwknopd
+             * server uses the port in the access string as the one to NAT,
+             * and access is granted via this translated port to whatever is
+             * specified with --nat-access <IP:port> (so this service is the
+             * utlimate target of the incoming connection after the SPA
+             * packet is sent).
+            */
+            ndx = strchr(options->access_str, '/');
+            if(ndx == NULL)
+            {
+                fprintf(stderr, "[*] Expecting <proto>/<port> for -A arg.\n");
+                clean_exit(ctx, options, EXIT_FAILURE);
+            }
+            snprintf(access_buf, MAX_LINE_LEN, "%s%s",
+                    options->allow_ip_str, ",");
+
+            /* This adds in the protocol + '/' char
+            */
+            strlcat(access_buf, options->access_str,
+                    strlen(access_buf) + (ndx - options->access_str) + 2);
+
+            if (strchr(ndx+1, '/') != NULL)
+            {
+                fprintf(stderr,
+                        "[*] NAT for multiple ports/protocols not yet supported.\n");
+                clean_exit(ctx, options, EXIT_FAILURE);
+            }
+
+            /* Now add the NAT port
+            */
+            snprintf(tmp_nat_port, MAX_PORT_STR_LEN+1, "%d", nat_port);
+            strlcat(access_buf, tmp_nat_port,
+                    strlen(access_buf)+MAX_PORT_STR_LEN+1);
+        }
+        else
+        {
+            snprintf(access_buf, MAX_LINE_LEN, "%s%s%s",
+                    options->allow_ip_str, ",", options->access_str);
+        }
+    }
+    else
+    {
+        snprintf(access_buf, MAX_LINE_LEN, "%s%s%s",
+                options->allow_ip_str, ",", "none/0");
+    }
+    return;
+}
+
 /* Set NAT access string
 */
 static int
-set_nat_access(fko_ctx_t ctx, fko_cli_options_t *options)
+set_nat_access(fko_ctx_t ctx, fko_cli_options_t *options, const char * const access_buf)
 {
-    char nat_access_buf[MAX_LINE_LEN] = "";
-    int nat_port = 0;
+    char nat_access_buf[MAX_LINE_LEN] = {0};
+    char tmp_access_port[MAX_PORT_STR_LEN+1], *ndx = NULL;
+    int  access_port = 0, i = 0, is_err = 0;
 
-    if (options->nat_rand_port)
-        nat_port = get_rand_port(ctx);
-    else if (options->nat_port)
-        nat_port = options->nat_port;
-    else
-        nat_port = DEFAULT_NAT_PORT;
+    memset(nat_access_buf, 0x0, MAX_LINE_LEN);
+    memset(tmp_access_port, 0x0, MAX_PORT_STR_LEN+1);
+
+    ndx = strchr(options->access_str, '/');
+    if(ndx == NULL)
+    {
+        fprintf(stderr, "[*] Expecting <proto>/<port> for -A arg.\n");
+        clean_exit(ctx, options, EXIT_FAILURE);
+    }
+    ndx++;
+
+    while(*ndx != '\0' && isdigit(*ndx) && i < MAX_PORT_STR_LEN)
+    {
+        tmp_access_port[i] = *ndx;
+        ndx++;
+        i++;
+    }
+    tmp_access_port[i] = '\0';
+
+    access_port = strtol_wrapper(tmp_access_port, 1,
+            MAX_PORT, NO_EXIT_UPON_ERR, &is_err);
+    if(is_err != FKO_SUCCESS)
+    {
+        fprintf(stderr, "[*] Invalid port value '%d' for -A arg.\n",
+                access_port);
+        clean_exit(ctx, options, EXIT_FAILURE);
+    }
 
     if (options->nat_local && options->nat_access_str[0] == 0x0)
     {
         snprintf(nat_access_buf, MAX_LINE_LEN, "%s,%d",
-            options->spa_server_str, nat_port);
+            options->spa_server_str, access_port);
     }
 
     if (nat_access_buf[0] == 0x0 && options->nat_access_str[0] != 0x0)
@@ -632,10 +720,20 @@ set_nat_access(fko_ctx_t ctx, fko_cli_options_t *options)
         else
         {
             snprintf(nat_access_buf, MAX_LINE_LEN, "%s,%d",
-                options->nat_access_str, nat_port);
+                options->nat_access_str, access_port);
         }
     }
 
+    if(options->nat_rand_port)
+    {
+        /* Must print to stdout what the random port is since
+         * if not then the user will not which port will be
+         * opened/NAT'd on the fwknopd side
+        */
+        printf("[+] Randomly assigned port '%d' on: '%s' will grant access to: '%s'\n",
+                options->nat_port, access_buf, nat_access_buf);
+    }
+
     return fko_set_spa_nat_access(ctx, nat_access_buf);
 }
 
@@ -865,7 +963,8 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
     char *key, int *key_len, char *hmac_key,
     int *hmac_key_len, const int crypt_op)
 {
-    int use_hmac = 0, res = 0;
+    char   *key_tmp = NULL, *hmac_key_tmp = NULL;
+    int     use_hmac = 0, res = 0;
 
     memset(key, 0x0, MAX_KEY_LEN+1);
     memset(hmac_key, 0x0, MAX_KEY_LEN+1);
@@ -893,7 +992,8 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
         }
         else
         {
-            fprintf(stderr, "[*] Invalid base64 decoded key length.");
+            fprintf(stderr, "[*] Invalid key length: '%d', must be in [1,%d]",
+                    *key_len, MAX_KEY_LEN);
             clean_exit(ctx, options, EXIT_FAILURE);
         }
     }
@@ -910,46 +1010,59 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
         {
             if(crypt_op == CRYPT_OP_DECRYPT)
             {
-                strlcpy(key, getpasswd("Enter passphrase for secret key: "),
-                    MAX_KEY_LEN+1);
+                key_tmp = getpasswd("Enter passphrase for secret key: ");
+                if(key_tmp == NULL)
+                {
+                    fprintf(stderr, "[*] getpasswd() key error.\n");
+                    clean_exit(ctx, options, EXIT_FAILURE);
+                }
+                strlcpy(key, key_tmp, MAX_KEY_LEN+1);
                 *key_len = strlen(key);
             }
             else if(options->gpg_signer_key && strlen(options->gpg_signer_key))
             {
-                strlcpy(key, getpasswd("Enter passphrase for signing: "),
-                    MAX_KEY_LEN+1);
+                key_tmp = getpasswd("Enter passphrase for signing: ");
+                if(key_tmp == NULL)
+                {
+                    fprintf(stderr, "[*] getpasswd() key error.\n");
+                    clean_exit(ctx, options, EXIT_FAILURE);
+                }
+                strlcpy(key, key_tmp, MAX_KEY_LEN+1);
                 *key_len = strlen(key);
             }
         }
         else
         {
             if(crypt_op == CRYPT_OP_ENCRYPT)
-                strlcpy(key, getpasswd("Enter encryption key: "),
-                    MAX_KEY_LEN+1);
+                key_tmp = getpasswd("Enter encryption key: ");
             else if(crypt_op == CRYPT_OP_DECRYPT)
-                strlcpy(key, getpasswd("Enter decryption key: "),
-                    MAX_KEY_LEN+1);
+                key_tmp = getpasswd("Enter decryption key: ");
             else
-                strlcpy(key, getpasswd("Enter key: "),
-                    MAX_KEY_LEN+1);
+                key_tmp = getpasswd("Enter key: ");
+
+            if(key_tmp == NULL)
+            {
+                fprintf(stderr, "[*] getpasswd() key error.\n");
+                clean_exit(ctx, options, EXIT_FAILURE);
+            }
+            strlcpy(key, key_tmp, MAX_KEY_LEN+1);
             *key_len = strlen(key);
         }
     }
 
-
-    if (options->have_hmac_key)
+    if(options->have_hmac_key)
     {
         strlcpy(hmac_key, options->hmac_key, MAX_KEY_LEN+1);
         *hmac_key_len = strlen(hmac_key);
         use_hmac = 1;
     }
-    else if (options->have_hmac_base64_key)
+    else if(options->have_hmac_base64_key)
     {
         *hmac_key_len = fko_base64_decode(options->hmac_key_base64,
             (unsigned char *) options->hmac_key);
-        if(*hmac_key_len > MAX_KEY_LEN || *hmac_key_len <= 0)
+        if(*hmac_key_len > MAX_KEY_LEN || *hmac_key_len < 0)
         {
-            fprintf(stderr, "[*] Invalid decoded key length: '%d', must be in [1,%d]",
+            fprintf(stderr, "[*] Invalid decoded key length: '%d', must be in [0,%d]",
                     *hmac_key_len, MAX_KEY_LEN);
             clean_exit(ctx, options, EXIT_FAILURE);
         }
@@ -968,13 +1081,28 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
         else
         {
 #endif
-        strlcpy(hmac_key, getpasswd("Enter HMAC key: "), MAX_KEY_LEN+1);
+        hmac_key_tmp = getpasswd("Enter HMAC key: ");
+
+        if(hmac_key_tmp == NULL)
+        {
+            fprintf(stderr, "[*] getpasswd() key error.\n");
+            clean_exit(ctx, options, EXIT_FAILURE);
+        }
+
+        strlcpy(hmac_key, hmac_key_tmp, MAX_KEY_LEN+1);
         *hmac_key_len = strlen(hmac_key);
         use_hmac = 1;
     }
 
     if (use_hmac)
     {
+        if(*hmac_key_len < 0 || *hmac_key_len > MAX_KEY_LEN)
+        {
+            fprintf(stderr, "[*] Invalid HMAC key length: '%d', must be in [0,%d]",
+                    *hmac_key_len, MAX_KEY_LEN);
+            clean_exit(ctx, options, EXIT_FAILURE);
+        }
+
         res = fko_set_spa_hmac_type(ctx, options->hmac_type);
         if(res != FKO_SUCCESS)
         {
diff --git a/test/conf/fwknoprc_hmac_sha512_long_key b/test/conf/fwknoprc_hmac_sha512_long_key
new file mode 100644 (file)
index 0000000..0ebec97
--- /dev/null
@@ -0,0 +1,73 @@
+# .fwknoprc
+##############################################################################
+#
+# Firewall Knock Operator (fwknop) client rc file.
+#
+# This file contains user-specific fwknop client configuration default
+# and named parameter sets for specific invocations of the fwknop client.
+#
+# Each section (or stanza) is identified and started by a line in this
+# file that contains a single identifier surrounded by square brackets.
+#
+# The parameters within the stanza typicaly match corresponding client 
+# command-line parameters.
+#
+# The first one should always be `[default]' as it defines the global
+# default settings for the user. These override the program defaults
+# for these parameter.  If a named stanza is used, its entries will
+# override any of the default.  Command-line options will trump them
+# all.
+#
+# Subsequent stanzas will have only the overriding and destination
+# specific parameters.
+#
+# Lines starting with `#' and empty lines are ignored.
+#
+# See the fwknop.8 man page for a complete list of valid parameters
+# and their values.
+#
+##############################################################################
+#
+# We start with the 'default' stanza.  Uncomment and edit for your
+# preferences.  The client will use its build-in default for those items
+# that are commented out.
+#
+[default]
+
+#DIGEST_TYPE         sha256
+#FW_TIMEOUT          30
+#SPA_SERVER_PORT     62201
+#SPA_SERVER_PROTO    udp
+#ALLOW_IP            <ip addr>
+#SPOOF_USER          <username>
+#SPOOF_SOURCE_IP     <IPaddr>
+#TIME_OFFSET         0
+#USE_GPG             N
+#GPG_HOMEDIR         /path/to/.gnupg
+#GPG_SIGNER          <signer ID>
+#GPG_RECIPIENT       <recipient ID>
+HMAC_DIGEST_TYPE    sha512
+KEY_BASE64          wzNP62oPPgEc+kXDPQLHPOayQBuNbYUTPP+QrErNDmg=
+HMAC_KEY_BASE64:    QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
+
+# User-provided named stanzas:
+
+# Example for a destination server of 192.168.1.20 to open access to 
+# SSH for an IP that is resoved externally, and one with a NAT request
+# for a specific source IP that maps port 8088 on the server
+# to port 88 on 192.168.1.55 with timeout.
+#
+#[myssh]
+#SPA_SERVER          192.168.1.20
+#ACCESS              tcp/22
+#ALLOW_IP            resolve
+#
+#[mynatreq]
+#SPA_SERVER          192.168.1.20
+#ACCESS              tcp/8088
+#ALLOW_IP            10.21.2.6
+#NAT_ACCESS          192.168.1.55,88
+#CLIENT_TIMEOUT      60
+#
+
+###EOF###
diff --git a/test/conf/hmac_force_nat_access.conf b/test/conf/hmac_force_nat_access.conf
new file mode 100644 (file)
index 0000000..63a3421
--- /dev/null
@@ -0,0 +1,5 @@
+SOURCE: ANY;
+KEY_BASE64          wzNP62oPPgEc+kXDPQLHPOayQBuNbYUTPP+QrErNDmg=
+HMAC_KEY_BASE64     Yh+xizBnl6FotC5ec7FanVGClRMlsOAPh2u6eovnerfBVKwaVKzjGoblFMHMc593TNyi0dWn4opLoTIV9q/ttg==
+FW_ACCESS_TIMEOUT:  3;
+FORCE_NAT: 192.168.1.123 22;
diff --git a/test/conf/hmac_sha256_open_ports_access.conf b/test/conf/hmac_sha256_open_ports_access.conf
new file mode 100644 (file)
index 0000000..979c04c
--- /dev/null
@@ -0,0 +1,6 @@
+SOURCE: 4.3.2.0/24, 127.0.0.0/24, 123.123.123.123/24, 23.43.0.0/16, 10.10.10.10;
+OPEN_PORTS: udp/6001, tcp/22, tcp/80, tcp/12345;
+KEY_BASE64:         wzNP62oPPgEc+kXDPQLHPOayQBuNbYUTPP+QrErNDmg=
+HMAC_KEY_BASE64:    Yh+xizBnl6FotC5ec7FanVGClRMlsOAPh2u6eovnerfBVKwaVKzjGoblFMHMc593TNyi0dWn4opLoTIV9q/ttg==
+HMAC_DIGEST_TYPE:   sha256;
+FW_ACCESS_TIMEOUT:  3;
diff --git a/test/conf/hmac_sha512_long_key_access.conf b/test/conf/hmac_sha512_long_key_access.conf
new file mode 100644 (file)
index 0000000..5f9cd6b
--- /dev/null
@@ -0,0 +1,5 @@
+SOURCE: ANY;
+KEY_BASE64:         wzNP62oPPgEc+kXDPQLHPOayQBuNbYUTPP+QrErNDmg=
+HMAC_KEY_BASE64:    QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
+HMAC_DIGEST_TYPE:   sha512;
+FW_ACCESS_TIMEOUT:  3;
index 09c9e35..1afaaff 100755 (executable)
@@ -46,6 +46,7 @@ our %cf = (
     'hmac_sha384_long_key_access'  => "$conf_dir/hmac_sha384_long_key_access.conf",
     'hmac_sha512_access'           => "$conf_dir/hmac_sha512_access.conf",
     'hmac_sha512_short_key_access' => "$conf_dir/hmac_sha512_short_key_access.conf",
+    'hmac_sha512_long_key_access'  => "$conf_dir/hmac_sha512_long_key_access.conf",
     'hmac_simple_keys_access'      => "$conf_dir/hmac_simple_keys_access.conf",
     'hmac_invalid_type_access'     => "$conf_dir/hmac_invalid_type_access.conf",
     'exp_access'                   => "$conf_dir/expired_stanza_access.conf",
@@ -53,6 +54,7 @@ our %cf = (
     'exp_epoch_access'             => "$conf_dir/expired_epoch_stanza_access.conf",
     'invalid_exp_access'           => "$conf_dir/invalid_expire_access.conf",
     'force_nat_access'             => "$conf_dir/force_nat_access.conf",
+    'hmac_force_nat_access'        => "$conf_dir/hmac_force_nat_access.conf",
     'cmd_access'                   => "$conf_dir/cmd_access.conf",
     'local_nat'                    => "$conf_dir/local_nat_fwknopd.conf",
     'ipfw_active_expire'           => "$conf_dir/ipfw_active_expire_equal_fwknopd.conf",
@@ -67,6 +69,7 @@ our %cf = (
     'tcp_pcap_filter'              => "$conf_dir/tcp_pcap_filter_fwknopd.conf",
     'icmp_pcap_filter'             => "$conf_dir/icmp_pcap_filter_fwknopd.conf",
     'open_ports_access'            => "$conf_dir/open_ports_access.conf",
+    'hmac_open_ports_access'       => "$conf_dir/hmac_sha256_open_ports_access.conf",
     'multi_gpg_access'             => "$conf_dir/multi_gpg_access.conf",
     'multi_gpg_no_pw_access'       => "$conf_dir/multi_gpg_no_pw_access.conf",
     'multi_stanza_access'          => "$conf_dir/multi_stanzas_access.conf",
@@ -108,6 +111,7 @@ our %cf = (
     'rc_hmac_sha384_long_key'      => "$conf_dir/fwknoprc_hmac_sha384_long_key",
     'rc_hmac_sha512_key'           => "$conf_dir/fwknoprc_hmac_sha512_key",
     'rc_hmac_sha512_short_key'     => "$conf_dir/fwknoprc_hmac_sha512_short_key",
+    'rc_hmac_sha512_long_key'      => "$conf_dir/fwknoprc_hmac_sha512_long_key",
     'base64_key_access'            => "$conf_dir/base64_key_access.conf",
     'disable_aging'                => "$conf_dir/disable_aging_fwknopd.conf",
     'disable_aging_nat'            => "$conf_dir/disable_aging_nat_fwknopd.conf",
index 98d50d2..770cc02 100644 (file)
         'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
             "$fwknopdCmd $default_server_conf_args $intf_str",
         'server_positive_output_matches' => [qr/requested\sNAT\saccess.*not\senabled/i],
-        'server_conf' => $cf{'nat'},
+        'server_conf' => $cf{'def'},
         'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
         'fatal'    => $NO
     },
         'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
             "$fwknopdCmd -c $cf{'nat'} -a $cf{'open_ports_access'} " .
             "-d $default_digest_file -p $default_pid_file $intf_str",
-        'server_positive_output_matches' => [qr/to\:$internal_nat_host\:22/i],
+        'server_positive_output_matches' => [
+            qr/FWKNOP_FORWARD\s.*dport\s22\s/,
+            qr/to\:$internal_nat_host\:22/i],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'server_conf' => $cf{'nat'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael',
+        'subcategory' => 'client+server',
+        'detail'   => "NAT tcp/80 to $internal_nat_host tcp/22",
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
+            "$local_key_file --verbose --verbose -N $internal_nat_host:22",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'nat'} -a $cf{'def_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [
+            qr/FWKNOP_FORWARD\s.*dport\s22\s/,
+            qr/to\:$internal_nat_host\:22/i],
         'fw_rule_created' => $NEW_RULE_REQUIRED,
         'fw_rule_removed' => $NEW_RULE_REMOVED,
         'server_conf' => $cf{'nat'},
         'fatal'    => $NO
     },
+
     {
         'category' => 'Rijndael',
         'subcategory' => 'client',
         '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' => $cf{'local_nat'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael',
+        'subcategory' => 'client+server',
+        'detail'   => "local NAT rand port to tcp/22",
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args --nat-local --nat-rand-port",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'def_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [qr/to\:$loopback_ip\: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' => $cf{'local_nat'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael',
+        'subcategory' => 'client+server',
+        'detail'   => "NAT rand port to tcp/22",
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args --nat-rand-port -N $internal_nat_host",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'nat'} -a $cf{'def_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [
+            qr/FWKNOP_FORWARD.*dport\s22\s.*\sACCEPT/,
+            qr/FWKNOP_PREROUTING.*\sDNAT\s.*to\-destination\s$internal_nat_host\:22/,
+        ],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
         'server_conf' => $cf{'nat'},
         'fatal'    => $NO
     },
     {
         'category' => 'Rijndael',
         'subcategory' => 'client+server',
-        'detail'   => "local NAT non-FORCE_NAT (tcp/22 ssh)",
+        'detail'   => "NAT rand port to -N <host>:40001",
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args --nat-rand-port -N $internal_nat_host:40001",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'nat'} -a $cf{'def_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [
+            qr/FWKNOP_FORWARD.*dport\s40001\s.*\sACCEPT/,
+            qr/FWKNOP_PREROUTING.*\sDNAT\s.*to\-destination\s$internal_nat_host\:40001/,
+        ],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'server_conf' => $cf{'nat'},
+        'fatal'    => $NO
+    },
+
+
+    {
+        'category' => 'Rijndael',
+        'subcategory' => 'client+server',
+        'detail'   => "local NAT non-FORCE_NAT (tcp/22)",
         'function' => \&spa_cycle,
         'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
-            "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --get-key " .
-            "$local_key_file --verbose --verbose --nat-local --nat-port 22",
+            "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --get-key " .
+            "$local_key_file --verbose --verbose --nat-local --nat-port 80",
         'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
             "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'def_access'} " .
             "-d $default_digest_file -p $default_pid_file $intf_str",
         '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' => $cf{'nat'},
+        'server_conf' => $cf{'local_nat'},
         'fatal'    => $NO
     },
     {
index 11ab9b7..646d323 100644 (file)
     {
         'category' => 'Rijndael+HMAC',
         'subcategory' => 'client+server',
+        'detail'   => 'complete cycle (tcp/23)',
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/23 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => 'complete cycle (tcp/9418)',
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/9418 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => 'complete cycle (tcp/60001)',
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/60001 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => 'multi port (tcp/60001,udp/60001)',
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/60001,udp/60001 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => 'random SPA port (tcp/22)',
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_hmac_args -r",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str " .
+            qq|-P "udp"|,
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
         'detail'   => 'complete cycle simple keys',
         'function' => \&spa_cycle,
         'cmdline'  => "$default_client_args_no_get_key " .
     {
         'category' => 'Rijndael+HMAC',
         'subcategory' => 'client+server',
+        'detail'   => 'spoof username cycle (tcp/22)',
+        'function' => \&spa_cycle,
+        'cmdline'  => "SPOOF_USER=$spoof_user LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
         'detail'   => 'rotate digest file',
         'function' => \&rotate_digest_file,
         'cmdline'  => $default_client_hmac_args,
         'key_file' => $cf{'rc_hmac_sha384_long_key'},
         'fatal'    => $NO
     },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => 'complete cycle SHA512 (long key)',
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args_no_get_key --rc-file " .
+            "$cf{'rc_hmac_sha512_long_key'} --hmac-digest-type sha512",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_sha512_long_key_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'key_file' => $cf{'rc_hmac_sha512_long_key'},
+        'fatal'    => $NO
+    },
 
     {
         'category' => 'Rijndael+HMAC',
         'key_file' => $cf{'rc_hmac_b64_key'},
         'fatal'    => $NO
     },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => "non-enabled NAT (tcp/22 ssh)",
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args_no_get_key --rc-file " .
+            "$cf{'rc_hmac_b64_key'} -N $internal_nat_host:22",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+             "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [qr/requested\sNAT\saccess.*not\senabled/i],
+        'server_conf' => $cf{'def'},
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => "NAT to $internal_nat_host (tcp/22 ssh)",
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args_no_get_key --rc-file " .
+            "$cf{'rc_hmac_b64_key'} -N $internal_nat_host:22",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'nat'} -a $cf{'hmac_open_ports_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [
+            qr/FWKNOP_FORWARD\s.*dport\s22\s/,
+            qr/to\:$internal_nat_host\:22/i],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'server_conf' => $cf{'nat'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => "NAT tcp/80 to $internal_nat_host tcp/22",
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/80 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose -N $internal_nat_host:22",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'nat'} -a $cf{'hmac_open_ports_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [
+            qr/FWKNOP_FORWARD\s.*dport\s22\s/,
+            qr/to\:$internal_nat_host\:22/i],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'server_conf' => $cf{'nat'},
+        'fatal'    => $NO
+    },
+
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client',
+        'detail'   => "NAT bogus IP validation",
+        'function' => \&generic_exec,
+        'exec_err' => $YES,
+        'cmdline'  => "$default_client_args_no_get_key --rc-file " .
+            "$cf{'rc_hmac_b64_key'} -N 999.1.1.1:22",
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => "force NAT $force_nat_host (tcp/22)",
+        'function' => \&spa_cycle,
+        'cmdline'  => $default_client_args,
+        'cmdline'  => "$default_client_args_no_get_key --rc-file " .
+            $cf{'rc_hmac_b64_key'},
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'nat'} -a $cf{'hmac_force_nat_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [qr/\sto\:$force_nat_host\:22/i],
+        'server_negative_output_matches' => [qr/\sto\:$internal_nat_host\:22/i],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'server_conf' => $cf{'nat'},
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => "local NAT $force_nat_host (tcp/22)",
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args_no_get_key --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --nat-local",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'hmac_force_nat_access'} " .
+            "-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' => $cf{'local_nat'},
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => "local NAT non-FORCE_NAT",
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose --nat-local --nat-port 80",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [qr/to\:$loopback_ip\: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' => $cf{'local_nat'},
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => "local NAT rand port to tcp/22",
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose --nat-local --nat-rand-port",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [qr/to\:$loopback_ip\: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' => $cf{'local_nat'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => "NAT rand port to tcp/22",
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose --nat-rand-port -N $internal_nat_host",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'nat'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [
+            qr/FWKNOP_FORWARD.*dport\s22\s.*\sACCEPT/,
+            qr/FWKNOP_PREROUTING.*\sDNAT\s.*to\-destination\s$internal_nat_host\:22/,
+        ],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'server_conf' => $cf{'nat'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => "NAT rand port to -N <host>:40001",
+        'function' => \&spa_cycle,
+        'cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopCmd -A tcp/22 -a $fake_ip -D $loopback_ip --rc-file " .
+            "$cf{'rc_hmac_b64_key'} --verbose --verbose --nat-rand-port -N $internal_nat_host:40001",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'nat'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [
+            qr/FWKNOP_FORWARD.*dport\s40001\s.*\sACCEPT/,
+            qr/FWKNOP_PREROUTING.*\sDNAT\s.*to\-destination\s$internal_nat_host\:40001/,
+        ],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'server_conf' => $cf{'nat'},
+        'fatal'    => $NO
+    },
+
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'client+server',
+        'detail'   => 'fw rules not duplicated',
+        'function' => \&iptables_rules_not_duplicated,
+        'cmdline'  => "$default_client_hmac_args --test",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $cf{'local_nat'} -a $cf{'hmac_access'} " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_negative_output_matches' => [qr/^2\s+ACCEPT\s.*$fake_ip/],
+        'key_file' => $cf{'rc_hmac_b64_key'},
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael+HMAC',
+        'subcategory' => 'server',
+        'detail'   => 'digest cache structure',
+        'function' => \&digest_cache_structure,
+        'fatal'    => $NO
+    },
+
 );