diff options
-rw-r--r-- | conf.default/config.xml | 2 | ||||
-rw-r--r-- | etc/inc/functions.inc | 1 | ||||
-rw-r--r-- | etc/inc/itemid.inc | 85 | ||||
-rwxr-xr-x | usr/local/www/firewall_nat.php | 12 | ||||
-rwxr-xr-x | usr/local/www/firewall_nat_edit.php | 74 | ||||
-rwxr-xr-x | usr/local/www/firewall_rules.php | 17 | ||||
-rwxr-xr-x | usr/local/www/firewall_rules_edit.php | 12 | ||||
-rw-r--r-- | usr/local/www/themes/pfsense_ng/images/icons/icon_chain.png | bin | 0 -> 281 bytes |
8 files changed, 183 insertions, 20 deletions
diff --git a/conf.default/config.xml b/conf.default/config.xml index 67d6bfe..b617b23 100644 --- a/conf.default/config.xml +++ b/conf.default/config.xml @@ -449,6 +449,7 @@ <target></target> <local-port></local-port> <descr></descr> + <associated-filter-rule-id></associated-filter-rule-id> </rule> --> <!-- @@ -502,6 +503,7 @@ <!-- rule syntax: <rule> <disabled/> + <id>[0-9]*</id> <type>pass|block|reject</type> <descr>...</descr> <interface>lan|opt[n]|wan|pptp</interface> diff --git a/etc/inc/functions.inc b/etc/inc/functions.inc index c7189b5..79aa19d 100644 --- a/etc/inc/functions.inc +++ b/etc/inc/functions.inc @@ -83,5 +83,6 @@ require_once("vpn.inc"); require_once("vslb.inc"); require_once("cmd_chain.inc"); require_once("rrd.inc"); +require_once("itemid.inc"); ?> diff --git a/etc/inc/itemid.inc b/etc/inc/itemid.inc new file mode 100644 index 0000000..3a48e51 --- /dev/null +++ b/etc/inc/itemid.inc @@ -0,0 +1,85 @@ +<?php +/* $Id$ */ +/* + Copyright (C) 2009 Janne Enberg <janne.enberg@lietu.net> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + DISABLE_PHP_LINT_CHECKING +*/ + +/****f* itemid/delete_id + * NAME + * delete_id - delete an item with ['id'] = $id from $array + * INPUTS + * $id - int: The ID to delete + * $array - array to delete the item from + * RESULT + * boolean - true if item was found and deleted + ******/ +function delete_id($id, &$array){ + // Index to delete + $delete_index = NULL; + + // Search for the item in the array + foreach ($array as $key => $item){ + // If this item is the one we want to delete + if(isset($item['id']) && $item['id']==$id ){ + $delete_index = $key; + break; + } + } + + // If we found the item, unset it + if( $delete_index!==NULL ){ + unset($array[$delete_index]); + return true; + } else { + return false; + } + +} + +/****f* itemid/get_next_id + * NAME + * get_next_id - find the next available id from an item list + * INPUTS + * $array - array of items to get the id for + * RESULT + * integer - the next available id + ******/ +function get_next_id($array){ + // Default value + $next_id = 1; + + // Search for IDs + foreach ($array as $item){ + // If this item has an ID, and it's higher or equal to the current "next ID", use that + 1 as the next ID + if(isset($item['id']) && $item['id']>=$next_id ){ + $next_id = $item['id'] + 1; + } + } + return $next_id; +} + +?>
\ No newline at end of file diff --git a/usr/local/www/firewall_nat.php b/usr/local/www/firewall_nat.php index 741e15a..274a3f2 100755 --- a/usr/local/www/firewall_nat.php +++ b/usr/local/www/firewall_nat.php @@ -81,6 +81,12 @@ if (isset($_POST['del_x'])) { if (is_array($_POST['rule']) && count($_POST['rule'])) { foreach ($_POST['rule'] as $rulei) { $target = $rule['target']; + // Check for filter rule associations + if (isset($a_nat[$rulei]['associated-filter-rule-id'])){ + delete_id($a_nat[$rulei]['associated-filter-rule-id'], $config['filter']['rule']); + + mark_subsystem_dirty('filter'); + } unset($a_nat[$rulei]); } write_config(); @@ -217,7 +223,11 @@ echo "<script type=\"text/javascript\" language=\"javascript\" src=\"/javascript ?> <tr valign="top" id="fr<?=$nnats;?>"> <td class="listt"><input type="checkbox" id="frc<?=$nnats;?>" name="rule[]" value="<?=$i;?>" onClick="fr_bgcolor('<?=$nnats;?>')" style="margin: 0; padding: 0; width: 15px; height: 15px;"></td> - <td class="listt" align="center"></td> + <td class="listt" align="center"> + <?php if(isset($natent['associated-filter-rule-id']) && $natent['associated-filter-rule-id']>0): ?> + <img src="./themes/<?= $g['theme']; ?>/images/icons/icon_chain.png" width="17" height="17" title="Firewall rule ID <?=htmlspecialchars($natent['associated-filter-rule-id']); ?> is managed with this rule" border="0"> + <?php endif; ?> + </td> <td class="listlr" onClick="fr_toggle(<?=$nnats;?>)" id="frd<?=$nnats;?>" ondblclick="document.location='firewall_nat_edit.php?id=<?=$nnats;?>';"> <?php if (!$natent['interface'] || ($natent['interface'] == "wan")) diff --git a/usr/local/www/firewall_nat_edit.php b/usr/local/www/firewall_nat_edit.php index 10fb84d..d8a9fb6 100755 --- a/usr/local/www/firewall_nat_edit.php +++ b/usr/local/www/firewall_nat_edit.php @@ -61,6 +61,7 @@ if (isset($id) && $a_nat[$id]) { $pconfig['localbeginport'] = $a_nat[$id]['local-port']; $pconfig['descr'] = $a_nat[$id]['descr']; $pconfig['interface'] = $a_nat[$id]['interface']; + $pconfig['associated-filter-rule-id'] = $a_nat[$id]['associated-filter-rule-id']; $pconfig['nosync'] = isset($a_nat[$id]['nosync']); if (!$pconfig['interface']) $pconfig['interface'] = "wan"; @@ -181,24 +182,29 @@ if ($_POST) { $natent['local-port'] = $_POST['localbeginport']; $natent['interface'] = $_POST['interface']; $natent['descr'] = $_POST['descr']; + $natent['associated-filter-rule-id'] = $_POST['associated-filter-rule-id']; if($_POST['nosync'] == "yes") $natent['nosync'] = true; else unset($natent['nosync']); - if (isset($id) && $a_nat[$id]) - $a_nat[$id] = $natent; - else { - if (is_numeric($after)) - array_splice($a_nat, $after+1, 0, array($natent)); - else - $a_nat[] = $natent; - } + $need_filter_rule = false; + // Updating a rule with a filter rule associated + if( $natent['associated-filter-rule-id']>0 ) + $need_filter_rule = true; + // If creating a new rule, where we want to add the filter rule, associated or not + else if( isset($_POST['filter-rule-association']) && + ($_POST['filter-rule-association']=='add-associated' || + $_POST['filter-rule-association']=='add-unassociated') ) + $need_filter_rule = true; - mark_subsystem_dirty('natconf'); + if ($need_filter_rule) { + + // If we had a previous rule associated with this NAT rule, delete that + if( $natent['associated-filter-rule-id'] > 0 ) + delete_id($natent['associated-filter-rule-id'], $config['filter']['rule']); - if ($_POST['autoadd']) { /* auto-generate a matching firewall rule */ $filterent = array(); $filterent['interface'] = $_POST['interface']; @@ -221,11 +227,30 @@ if ($_POST) { */ $filterent['descr'] = substr("NAT " . $_POST['descr'], 0, 59); + // If we had a previous rule association, update this rule with that ID so we don't lose association + if ($natent['associated-filter-rule-id'] > 0) + $filterent['id'] = $natent['associated-filter-rule-id']; + // If we wanted this rule to be associated, make sure the NAT entry is updated with the same ID + else if($_POST['filter-rule-association']=='add-associated') + $natent['associated-filter-rule-id'] = $filterent['id'] = get_next_id($config['filter']['rule']); + $config['filter']['rule'][] = $filterent; mark_subsystem_dirty('filter'); } + // Update NAT entry after creating/updating the firewall rule, so we have it's rule ID if one was created + if (isset($id) && $a_nat[$id]) + $a_nat[$id] = $natent; + else { + if (is_numeric($after)) + array_splice($a_nat, $after+1, 0, array($natent)); + else + $a_nat[] = $natent; + } + + mark_subsystem_dirty('natconf'); + write_config(); header("Location: firewall_nat.php"); @@ -390,13 +415,34 @@ include("fbegin.inc"); ?> HINT: This prevents the rule from automatically syncing to other CARP members. </td> </tr> + <?php if (isset($id) && $a_nat[$id] && !isset($_GET['dup'])): ?> + <tr> + <td width="22%" valign="top" class="vncell">Filter rule association</td> + <td width="78%" class="vtable"> + <select name="associated-filter-rule-id"> + <option value="">None</option> + <?php foreach ($config['filter']['rule'] as $filter_rule): ?> + <?php if (isset($filter_rule['id']) && $filter_rule['id']>0): ?> + <option value="<?php echo $filter_rule['id']; ?>"<?php if($filter_rule['id']==$pconfig['associated-filter-rule-id']) echo " SELECTED"; ?>> + <?php echo htmlspecialchars('Rule ' . $filter_rule['id'] . ' - ' . $filter_rule['descr']); ?> + </option> + <?php endif; ?> + <?php endforeach; ?> + </select> + </td> + </tr> + <?php endif; ?> <?php if ((!(isset($id) && $a_nat[$id])) || (isset($_GET['dup']))): ?> <tr> - <td width="22%" valign="top"> </td> + <td width="22%" valign="top">Filter rule association</td> <td width="78%"> - <input name="autoadd" type="checkbox" id="autoadd" value="yes" CHECKED> - <strong>Auto-add a firewall rule to permit traffic through - this NAT rule</strong></td> + <select name="filter-rule-association" id="filter-rule-association"> + <option value="">None</option> + <option value="add-associated" selected="selected">Add associated rule</option> + <option value="add-unassociated">Add unassociated rule</option> + <option value="pass">Pass</option> + </select> + </td> </tr><?php endif; ?> <tr> <td width="22%" valign="top"> </td> diff --git a/usr/local/www/firewall_rules.php b/usr/local/www/firewall_rules.php index e084e4c..a6f5b38 100755 --- a/usr/local/www/firewall_rules.php +++ b/usr/local/www/firewall_rules.php @@ -249,15 +249,16 @@ echo "<script type=\"text/javascript\" language=\"javascript\" src=\"/javascript <tr id="frheader"> <td width="3%" class="list"> </td> <td width="5%" class="list"> </td> + <td width="3%" class="listhdrr">ID</td> <td width="6%" class="listhdrr">Proto</td> - <td width="15%" class="listhdrr">Source</td> + <td width="14%" class="listhdrr">Source</td> <td width="7%" class="listhdrr">Port</td> - <td width="15%" class="listhdrr">Destination</td> + <td width="14%" class="listhdrr">Destination</td> <td width="7%" class="listhdrr">Port</td> <td width="5%" class="listhdrr">Gateway</td> <td width="10%" class="listhdrr">Queue</td> <td width="5%" class="listhdrr">Schedule</td> - <td width="22%" class="listhdr">Description</td> + <td width="21%" class="listhdr">Description</td> <td width="10%" class="list"> <table border="0" cellspacing="0" cellpadding="1"> <tr> @@ -286,7 +287,8 @@ echo "<script type=\"text/javascript\" language=\"javascript\" src=\"/javascript <tr valign="top" id="frrfc1918"> <td width="3%" class="list"> </td> <td class="listt" align="center"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_block.gif" width="11" height="11" border="0"></td> - <td class="listlr" style="background-color: #e0e0e0">*</td> + <td class="listlr" style="background-color: #e0e0e0"></td> + <td class="listr" style="background-color: #e0e0e0">*</td> <td class="listr" style="background-color: #e0e0e0">RFC 1918 networks</td> <td class="listr" style="background-color: #e0e0e0">*</td> <td class="listr" style="background-color: #e0e0e0">*</td> @@ -313,7 +315,8 @@ echo "<script type=\"text/javascript\" language=\"javascript\" src=\"/javascript <tr valign="top" id="frrfc1918"> <td width="3%" class="list"> </td> <td class="listt" align="center"><img src="./themes/<?= $g['theme']; ?>/images/icons/icon_block.gif" width="11" height="11" border="0"></td> - <td class="listlr" style="background-color: #e0e0e0">*</td> + <td class="listlr" style="background-color: #e0e0e0"></td> + <td class="listr" style="background-color: #e0e0e0">*</td> <td class="listr" style="background-color: #e0e0e0">Reserved/not assigned by IANA</td> <td class="listr" style="background-color: #e0e0e0">*</td> <td class="listr" style="background-color: #e0e0e0">*</td> @@ -545,6 +548,9 @@ echo "<script type=\"text/javascript\" language=\"javascript\" src=\"/javascript } ?> <td class="listlr" onClick="fr_toggle(<?=$nrules;?>)" id="frd<?=$nrules;?>" ondblclick="document.location='firewall_rules_edit.php?id=<?=$i;?>';"> + <?=$textss;?><?php if (isset($filterent['id'])) echo $filterent['id']; else echo ""; ?><?=$textse;?> + </td> + <td class="listr" onClick="fr_toggle(<?=$nrules;?>)" id="frd<?=$nrules;?>" ondblclick="document.location='firewall_rules_edit.php?id=<?=$i;?>';"> <?=$textss;?><?php if (isset($filterent['protocol'])) echo strtoupper($filterent['protocol']); else echo "*"; ?><?=$textse;?> </td> <td class="listr" onClick="fr_toggle(<?=$nrules;?>)" id="frd<?=$nrules;?>" ondblclick="document.location='firewall_rules_edit.php?id=<?=$i;?>';"> @@ -611,6 +617,7 @@ echo "<script type=\"text/javascript\" language=\"javascript\" src=\"/javascript <td class="list"> </td> <td class="list"> </td> <td class="list"> </td> + <td class="list"> </td> <td class="list"> </td> <td class="list"> </td> <td class="list"> </td> diff --git a/usr/local/www/firewall_rules_edit.php b/usr/local/www/firewall_rules_edit.php index 67e98f2..d9bc01b 100755 --- a/usr/local/www/firewall_rules_edit.php +++ b/usr/local/www/firewall_rules_edit.php @@ -71,6 +71,9 @@ if (isset($_GET['dup'])) { if (isset($id) && $a_filter[$id]) { $pconfig['interface'] = $a_filter[$id]['interface']; + if (isset($a_filter[$id]['id'])) + $pconfig['ruleid'] = $a_filter[$id]['id']; + if (!isset($a_filter[$id]['type'])) $pconfig['type'] = "pass"; else @@ -337,6 +340,8 @@ if ($_POST) { else if ($dnpipe[0] == "?" && $pdnpipe[0] <> "?") $input_errors[] = "You cannot select one queue and one virtual interface for IN and Out. both must be from the same type."; } + if( !empty($_POST['ruleid']) && !ctype_digit($_POST['ruleid'])) + $input_errors[] = 'ID must be an integer'; if($_POST['l7container'] && $_POST['l7container'] != "none") { if(!($_POST['proto'] == "tcp" || $_POST['proto'] == "udp" || $_POST['proto'] == "tcp/udp")) $input_errors[] = "You can only select a layer7 container for tcp and/or udp protocols"; @@ -346,6 +351,7 @@ if ($_POST) { if (!$input_errors) { $filterent = array(); + $filterent['id'] = $_POST['ruleid']>0?$_POST['ruleid']:''; $filterent['type'] = $_POST['type']; if (isset($_POST['interface'] )) $filterent['interface'] = $_POST['interface']; @@ -493,6 +499,12 @@ include("head.inc"); <td colspan="2" valign="top" class="listtopic">Edit Firewall rule</td> </tr> <tr> + <td width="22%" valign="top" class="vncell">ID</td> + <td width="78%" class="vtable"> + <input name="ruleid" value="<?=(isset($pconfig['ruleid'])&&$pconfig['ruleid']>0)?htmlspecialchars($pconfig['ruleid']):''?>"> + </td> + </tr> + <tr> <td width="22%" valign="top" class="vncellreq">Action</td> <td width="78%" class="vtable"> <select name="type" class="formselect"> diff --git a/usr/local/www/themes/pfsense_ng/images/icons/icon_chain.png b/usr/local/www/themes/pfsense_ng/images/icons/icon_chain.png Binary files differnew file mode 100644 index 0000000..cd9a7cc --- /dev/null +++ b/usr/local/www/themes/pfsense_ng/images/icons/icon_chain.png |