From bf00422585302a67bcd7fbb2d46b38b8b0b1ce41 Mon Sep 17 00:00:00 2001
From: Simon Humbert <shumbert@hostopia.com>
Date: Thu, 5 May 2016 11:59:42 -0400
Subject: [PATCH] update README.markdown and add tests in
 spec/fixtures/iptables/conversion_hash.rb

---
 README.markdown                           | 18 ++++-
 lib/puppet/provider/firewall/iptables.rb  |  3 +
 lib/puppet/type/firewall.rb               |  2 +-
 spec/fixtures/iptables/conversion_hash.rb | 80 +++++++++++++++++++++++
 4 files changed, 100 insertions(+), 3 deletions(-)

diff --git a/README.markdown b/README.markdown
index 338ecae..d455c70 100644
--- a/README.markdown
+++ b/README.markdown
@@ -410,12 +410,12 @@ This type enables you to manage firewall rules within Puppet.
 
  * `ip6tables`: Ip6tables type provider
     * Required binaries: `ip6tables-save`, `ip6tables`.
-    * Supported features: `address_type`, `connection_limiting`, `dnat`, `hop_limiting`, `icmp_match`, `interface_match`, `iprange`, `ipsec_dir`, `ipsec_policy`, `ipset`, `iptables`, `isfirstfrag`, `ishasmorefrags`, `islastfrag`, `log_level`, `log_prefix`, `log_uid`, `mark`, `mask`, `mss`, `owner`, `pkttype`, `rate_limiting`, `recent_limiting`, `reject_type`, `snat`, `socket`, `state_match`, `tcp_flags`.
+    * Supported features: `address_type`, `connection_limiting`, `dnat`, `hop_limiting`, `icmp_match`, `interface_match`, `iprange`, `ipsec_dir`, `ipsec_policy`, `ipset`, `iptables`, `isfirstfrag`, `ishasmorefrags`, `islastfrag`, `length`, `log_level`, `log_prefix`, `log_uid`, `mark`, `mask`, `mss`, `owner`, `pkttype`, `rate_limiting`, `recent_limiting`, `reject_type`, `snat`, `socket`, `state_match`, `string_matching`, `tcp_flags`.
 
 * `iptables`: Iptables type provider
     * Required binaries: `iptables-save`, `iptables`.
     * Default for `kernel` == `linux`.
-    * Supported features: `address_type`, `clusterip`, `connection_limiting`, `dnat`, `icmp_match`, `interface_match`, `iprange`, `ipsec_dir`, `ipsec_policy`, `ipset`, `iptables`, `isfragment`, `log_level`, `log_prefix`, `log_uid`, `mark`, `mask`, `mss`, `netmap`, `owner`, `pkttype`, `rate_limiting`, `recent_limiting`, `reject_type`, `snat`, `socket`, `state_match`, `tcp_flags`.
+    * Supported features: `address_type`, `clusterip`, `connection_limiting`, `dnat`, `icmp_match`, `interface_match`, `iprange`, `ipsec_dir`, `ipsec_policy`, `ipset`, `iptables`, `isfragment`, `length`, `log_level`, `log_prefix`, `log_uid`, `mark`, `mask`, `mss`, `netmap`, `owner`, `pkttype`, `rate_limiting`, `recent_limiting`, `reject_type`, `snat`, `socket`, `state_match`, `string_matching`, `tcp_flags`.
 
 **Autorequires:**
 
@@ -455,6 +455,8 @@ If Puppet is managing the iptables or iptables-persistent packages, and the prov
 
 * `islastfrag`: The ability to match the last fragment of an ipv6 packet.
 
+* `length`: The ability to match the length of the layer-3 payload.
+
 * `log_level`: The ability to control the log level.
 
 * `log_prefix`: The ability to add prefixes to log messages.
@@ -483,6 +485,8 @@ If Puppet is managing the iptables or iptables-persistent packages, and the prov
 
 * `state_match`: The ability to match stateful firewall states.
 
+* `string_matching`: The ability to match a given string by using some pattern matching strategy.
+
 * `tcp_flags`: The ability to match on particular TCP flag settings.
 
 * `netmap`: The ability to map entire subnets via source or destination nat rules.
@@ -590,6 +594,8 @@ If Puppet is managing the iptables or iptables-persistent packages, and the prov
 
 * `kernel_timezone`: Use the kernel timezone instead of UTC to determine whether a packet meets the time regulations.
 
+* `length`: Set the value for matching the length of the layer-3 payload. Can be a single number or a range using '-' as a separator. Requires the `length` feature.
+
 * `limit`: Rate limiting value for matched packets. The format is: 'rate/[/second/|/minute|/hour|/day]'. Example values are: '50/sec', '40/min', '30/hour', '10/day'. Requires the  `rate_limiting` feature.
 
 * `line`: Read-only property for caching the rule line.
@@ -743,6 +749,14 @@ firewall { '101 blacklist strange traffic':
 
 * `state`: Matches a packet based on its state in the firewall stateful inspection table. Valid values are: 'INVALID', 'ESTABLISHED', 'NEW', 'RELATED'. Requires the `state_match` feature.
 
+* `string`: Set the pattern for string matching. Requires the `string_matching` feature.
+
+* `string_algo`: Used in conjunction with `string`, select the pattern matching strategy. Valid values are: 'bm', 'kmp' (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris). Requires the `string_matching` feature.
+
+* `string_from`: Used in conjunction with `string`, set the offset from which it starts looking for any matching. Requires the `string_matching` feature.
+
+* `string_to`: Used in conjunction with `string`, set the offset up to which should be scanned. Requires the `string_matching` feature.
+
 * `table`: Table to use. Valid values are: 'nat', 'mangle', 'filter', 'raw', 'rawpost'. By default the setting is 'filter'. Requires the `iptables` feature.
 
 * `tcp_flags`: Match when the TCP flags are as specified. Set as a string with a list of comma-separated flag names for the mask, then a space, then a comma-separated list of flags that should be set. The flags are: 'SYN', 'ACK', 'FIN', 'RST', 'URG', 'PSH', 'ALL', 'NONE'.
diff --git a/lib/puppet/provider/firewall/iptables.rb b/lib/puppet/provider/firewall/iptables.rb
index c040d54..39265e7 100644
--- a/lib/puppet/provider/firewall/iptables.rb
+++ b/lib/puppet/provider/firewall/iptables.rb
@@ -495,6 +495,9 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
         elem.gsub(/:/,'-')
       end
     end
+    if hash[:length]
+      hash[:length].gsub!(/:/,'-')
+    end
 
     # Invert any rules that are prefixed with a '!'
     [
diff --git a/lib/puppet/type/firewall.rb b/lib/puppet/type/firewall.rb
index 6063f06..75b6ce0 100644
--- a/lib/puppet/type/firewall.rb
+++ b/lib/puppet/type/firewall.rb
@@ -1444,7 +1444,7 @@ Puppet::Type.newtype(:firewall) do
 
   newproperty(:string_to, :required_features => :string_matching) do
     desc <<-EOS
-      String matching feature, offset  up  to which we should scan.
+      String matching feature, offset up to which we should scan.
     EOS
   end
 
diff --git a/spec/fixtures/iptables/conversion_hash.rb b/spec/fixtures/iptables/conversion_hash.rb
index 990da91..2acce5f 100644
--- a/spec/fixtures/iptables/conversion_hash.rb
+++ b/spec/fixtures/iptables/conversion_hash.rb
@@ -590,6 +590,43 @@ ARGS_TO_HASH = {
       :chain             => 'foo-filter',
     },
   },
+  'length_1' => {
+    :line   => '-A INPUT -m length --length 42000',
+    :table  => 'filter',
+    :params => {
+      :length => '42000',
+    },
+  },
+  'length_2' => {
+    :line   => '-A INPUT -m length --length 1492:65535',
+    :table  => 'filter',
+    :params => {
+      :length => '1492-65535',
+    },
+  },
+  'string_matching_1' => {
+    :line   => '-A INPUT -m string --string "GET /index.html"',
+    :table  => 'filter',
+    :params => {
+      :string => 'GET /index.html',
+    },
+  },
+  'string_matching_2' => {
+    :line   => '-A INPUT -m string --string "GET /index.html" --algo bm',
+    :table  => 'filter',
+    :params => {
+      :string      => 'GET /index.html',
+      :string_algo => 'bm',
+    },
+  },
+  'string_matching_3' => {
+    :line   => '-A INPUT -m string --string "GET /index.html" --from 1',
+    :table  => 'filter',
+    :params => {
+      :string      => 'GET /index.html',
+      :string_from => '1',
+    },
+  },
 }
 
 # This hash is for testing converting a hash to an argument line.
@@ -1126,4 +1163,47 @@ HASH_TO_ARGS = {
     },
     :args => ["-t", :mangle, "-p", :tcp, "-m", "multiport", '--ports', '997', "-m", "comment", "--comment", "068 set dscp class to EF", "-j", "DSCP", "--set-dscp-class", "ef"],
   },
+  'length_1' => {
+    :params => {
+      :name   => '000 length',
+      :table  => 'filter',
+      :length => '42000',
+    },
+    :args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment", "000 length", "-m", "length", "--length", "42000"],
+  },
+  'length_2' => {
+    :params => {
+      :name   => '000 length',
+      :table  => 'filter',
+      :length => '1492-65535',
+    },
+    :args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment", "000 length", "-m", "length", "--length", "1492:65535"],
+  },
+  'string_matching_1' => {
+    :params => {
+      :name   => '000 string_matching',
+      :table  => 'filter',
+      :string => 'GET /index.html',
+    },
+    :args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment", "000 string_matching", "-m", "string", "--string", "'GET /index.html'"],
+  },
+  'string_matching_2' => {
+    :params => {
+      :name        => '000 string_matching',
+      :table       => 'filter',
+      :string      => 'GET /index.html',
+      :string_algo => 'bm',
+    },
+    :args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment", "000 string_matching", "-m", "string", "--string", "'GET /index.html'", "--algo", :bm],
+  },
+  'string_matching_3' => {
+    :params => {
+      :name        => '000 string_matching',
+      :table       => 'filter',
+      :string      => 'GET /index.html',
+      :string_from => '1',
+      :string_to   => '65535',
+    },
+    :args => ["-t", :filter, "-p", :tcp, "-m", "comment", "--comment", "000 string_matching", "-m", "string", "--string", "'GET /index.html'", "--from", "1", "--to", "65535"],
+  },
 }
-- 
2.45.2