]> git.proxmox.com Git - pve-firewall.git/blobdiff - src/PVE/Firewall.pm
fix iptables-restore failing if icmp-type value > 255
[pve-firewall.git] / src / PVE / Firewall.pm
index c34216758acfffdcd020c707521ac6bd0b26a468..da1784cf66cbbf7c4f72771724f8193691b9cd41 100644 (file)
@@ -1623,6 +1623,8 @@ sub verify_rule {
                if !$allow_groups;
            &$add_error('action', "invalid characters in security group name")
                if $action && ($action !~ m/^${security_group_name_pattern}$/);
+           &$add_error('action', "security group '$action' does not exist")
+               if $action && !defined($cluster_conf->{groups}->{$action});
        } else {
            &$add_error('type', "unknown rule type '$type'");
        }
@@ -2041,11 +2043,17 @@ sub ipt_rule_to_cmds {
                    # Note: we use dport to store --icmp-type
                    die "unknown icmp-type '$rule->{dport}'\n"
                        if $rule->{dport} !~ /^\d+$/ && !defined($icmp_type_names->{$rule->{dport}});
+                   # values for icmp-type range between 0 and 255
+                   # higher values and iptables-restore fails
+                   die "invalid icmp-type '$rule->{dport}'\n" if ($rule->{dport} =~ m/^(\d+)$/) && ($1 > 255);
                    push @match, "-m icmp --icmp-type $rule->{dport}";
                } elsif ($proto eq 'icmpv6') {
                    # Note: we use dport to store --icmpv6-type
                    die "unknown icmpv6-type '$rule->{dport}'\n"
                        if $rule->{dport} !~ /^\d+$/ && !defined($icmpv6_type_names->{$rule->{dport}});
+                   # values for icmpv6-type range between 0 and 255
+                   # higher values and iptables-restore fails
+                   die "invalid icmpv6-type '$rule->{dport}'\n" if ($rule->{dport} =~ m/^(\d+)$/) && ($1 > 255);
                    push @match, "-m icmpv6 --icmpv6-type $rule->{dport}";
                } elsif (!$PROTOCOLS_WITH_PORTS->{$proto}) {
                    die "protocol $proto does not have ports\n";
@@ -2897,6 +2905,8 @@ sub generic_fw_config_parser {
     }
     return {} if !$raw;
 
+    my $curr_group_keys = {};
+
     my $linenr = 0;
     while ($raw =~ /^\h*(.*?)\h*$/gm) {
        my $line = $1;
@@ -2957,6 +2967,8 @@ sub generic_fw_config_parser {
            }
 
            $res->{$section}->{$group} = [];
+           $curr_group_keys = {};
+
            $res->{ipset_comments}->{$group} = decode('utf8', $comment)
                if $comment;
            next;
@@ -3021,6 +3033,8 @@ sub generic_fw_config_parser {
                } else {
                    $cidr = parse_ip_or_cidr($cidr);
                }
+               die "duplicate ipset entry for '$cidr'\n"
+                   if defined($curr_group_keys->{$cidr});
            };
            if (my $err = $@) {
                chomp $err;
@@ -3044,6 +3058,7 @@ sub generic_fw_config_parser {
            }
 
            push @{$res->{$section}->{$group}}, $entry;
+           $curr_group_keys->{$cidr} = 1;
        } else {
            warn "$prefix: skip line - unknown section\n";
            next;
@@ -3221,7 +3236,13 @@ my $format_ipsets = sub {
 
        my $nethash = {};
        foreach my $entry (@$options) {
-           $nethash->{$entry->{cidr}} = $entry;
+           my $cidr = $entry->{cidr};
+           if (defined($nethash->{$cidr})) {
+               warn "ignoring duplicate ipset entry '$cidr'\n";
+               next;
+           }
+
+           $nethash->{$cidr} = $entry;
        }
 
        foreach my $cidr (sort keys %$nethash) {