mirror of
https://github.com/pfsense/pfsense.git
synced 2025-10-26 11:38:35 +00:00
Merge pull request #1297 from phil-davis/patch-23
This commit is contained in:
commit
7c1997914f
@ -384,8 +384,8 @@ function ip2ulong($ip) {
|
||||
/* Find out how many IPs are contained within a given IP range
|
||||
* e.g. 192.168.0.0 to 192.168.0.255 returns 256
|
||||
*/
|
||||
function ip_range_size($startip, $endip) {
|
||||
if (is_ipaddr($startip) && is_ipaddr($endip)) {
|
||||
function ip_range_size_v4($startip, $endip) {
|
||||
if (is_ipaddrv4($startip) && is_ipaddrv4($endip)) {
|
||||
// Operate as unsigned long because otherwise it wouldn't work
|
||||
// when crossing over from 127.255.255.255 / 128.0.0.0 barrier
|
||||
return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
|
||||
@ -396,7 +396,7 @@ function ip_range_size($startip, $endip) {
|
||||
/* Find the smallest possible subnet mask which can contain a given number of IPs
|
||||
* e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
|
||||
*/
|
||||
function find_smallest_cidr($number) {
|
||||
function find_smallest_cidr_v4($number) {
|
||||
$smallest = 1;
|
||||
for ($b=32; $b > 0; $b--) {
|
||||
$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
|
||||
@ -428,9 +428,37 @@ function ip_greater_than($ip1, $ip2) {
|
||||
return ip2ulong($ip1) > ip2ulong($ip2);
|
||||
}
|
||||
|
||||
/* Convert a range of IPs to an array of subnets which can contain the range. */
|
||||
/* Convert a range of IPv4 addresses to an array of individual addresses. */
|
||||
/* Note: IPv6 ranges are not yet supported here. */
|
||||
function ip_range_to_address_array($startip, $endip, $max_size = 5000) {
|
||||
if (!is_ipaddrv4($startip) || !is_ipaddrv4($endip)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ip_greater_than($startip, $endip)) {
|
||||
// Swap start and end so we can process sensibly.
|
||||
$temp = $startip;
|
||||
$startip = $endip;
|
||||
$endip = $temp;
|
||||
}
|
||||
|
||||
if (ip_range_size_v4($startip, $endip) > $max_size)
|
||||
return false;
|
||||
|
||||
// Container for IP addresses within this range.
|
||||
$rangeaddresses = array();
|
||||
$end_int = ip2ulong($endip);
|
||||
for ($ip_int = ip2ulong($startip); $ip_int <= $end_int; $ip_int++) {
|
||||
$rangeaddresses[] = long2ip($ip_int);
|
||||
}
|
||||
|
||||
return $rangeaddresses;
|
||||
}
|
||||
|
||||
/* Convert a range of IPv4 addresses to an array of subnets which can contain the range. */
|
||||
/* Note: IPv6 ranges are not yet supported here. */
|
||||
function ip_range_to_subnet_array($startip, $endip) {
|
||||
if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
|
||||
if (!is_ipaddrv4($startip) || !is_ipaddrv4($endip)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
@ -445,7 +473,7 @@ function ip_range_to_subnet_array($startip, $endip) {
|
||||
$rangesubnets = array();
|
||||
|
||||
// Figure out what the smallest subnet is that holds the number of IPs in the given range.
|
||||
$cidr = find_smallest_cidr(ip_range_size($startip, $endip));
|
||||
$cidr = find_smallest_cidr_v4(ip_range_size_v4($startip, $endip));
|
||||
|
||||
// Loop here to reduce subnet size and retest as needed. We need to make sure
|
||||
// that the target subnet is wholly contained between $startip and $endip.
|
||||
@ -496,12 +524,19 @@ function ip_range_to_subnet_array($startip, $endip) {
|
||||
return $rangesubnets;
|
||||
}
|
||||
|
||||
/* returns true if $range is a valid pair of IPv4 or IPv6 addresses separated by a "-"
|
||||
false - if not a valid pair
|
||||
true (numeric 4 or 6) - if valid, gives type of addresses */
|
||||
function is_iprange($range) {
|
||||
if (substr_count($range, '-') != 1) {
|
||||
return false;
|
||||
}
|
||||
list($ip1, $ip2) = explode ('-', $range);
|
||||
return (is_ipaddr($ip1) && is_ipaddr($ip2));
|
||||
if (is_ipaddrv4($ip1) && is_ipaddrv4($ip2))
|
||||
return 4;
|
||||
if (is_ipaddrv6($ip1) && is_ipaddrv6($ip2))
|
||||
return 6;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* returns true if $ipaddr is a valid dotted IPv4 address or a IPv6 */
|
||||
|
||||
@ -63,6 +63,7 @@ if (is_array($config['load_balancer']['lbpool']))
|
||||
|
||||
$reserved_ifs = get_configured_interface_list(false, true);
|
||||
$reserved_keywords = array_merge($reserved_keywords, $reserved_ifs, $reserved_table_names);
|
||||
$max_alias_addresses = 5000;
|
||||
|
||||
if (!is_array($config['aliases']['alias']))
|
||||
$config['aliases']['alias'] = array();
|
||||
@ -202,7 +203,7 @@ if ($_POST) {
|
||||
$desc_fmt_err_found = false;
|
||||
|
||||
/* item is a url type */
|
||||
for($x=0; $x<4999; $x++) {
|
||||
for($x=0; $x<$max_alias_addresses-1; $x++) {
|
||||
$_POST['address' . $x] = trim($_POST['address' . $x]);
|
||||
if($_POST['address' . $x]) {
|
||||
/* fetch down and add in */
|
||||
@ -280,54 +281,153 @@ if ($_POST) {
|
||||
/* item is a normal alias type */
|
||||
$wrongaliases = "";
|
||||
$desc_fmt_err_found = false;
|
||||
for($x=0; $x<4999; $x++) {
|
||||
$alias_address_count = 0;
|
||||
|
||||
// First trim and expand the input data.
|
||||
// Users can paste strings like "10.1.2.0/24 10.3.0.0/16 9.10.11.0/24" into an address box.
|
||||
// They can also put an IP range.
|
||||
// This loop expands out that stuff so it can easily be validated.
|
||||
for($x=0; $x<($max_alias_addresses-1); $x++) {
|
||||
if($_POST["address{$x}"] <> "") {
|
||||
$_POST["address{$x}"] = trim($_POST["address{$x}"]);
|
||||
if (is_alias($_POST["address{$x}"])) {
|
||||
if (!alias_same_type($_POST["address{$x}"], $_POST['type']))
|
||||
// But alias type network can include alias type urltable. Feature#1603.
|
||||
if (!($_POST['type'] == 'network' &&
|
||||
preg_match("/urltable/i", alias_get_type($_POST["address{$x}"]))))
|
||||
$wrongaliases .= " " . $_POST["address{$x}"];
|
||||
} else if ($_POST['type'] == "port") {
|
||||
if (!is_port($_POST["address{$x}"]) && !is_portrange($_POST["address{$x}"]))
|
||||
$input_errors[] = $_POST["address{$x}"] . " " . gettext("is not a valid port or alias.");
|
||||
} else if ($_POST['type'] == "host" || $_POST['type'] == "network") {
|
||||
if (is_subnet($_POST["address{$x}"]) || (!is_ipaddr($_POST["address{$x}"])
|
||||
&& !is_hostname($_POST["address{$x}"])
|
||||
&& !is_iprange($_POST["address{$x}"])))
|
||||
$input_errors[] = sprintf(gettext('%1$s is not a valid %2$s alias.'), $_POST["address{$x}"], $_POST['type']);
|
||||
}
|
||||
if (is_iprange($_POST["address{$x}"])) {
|
||||
list($startip, $endip) = explode('-', $_POST["address{$x}"]);
|
||||
$rangesubnets = ip_range_to_subnet_array($startip, $endip);
|
||||
$address = array_merge($address, $rangesubnets);
|
||||
} else {
|
||||
$tmpaddress = $_POST["address{$x}"];
|
||||
if($_POST['type'] != "host" && is_ipaddr($_POST["address{$x}"]) && $_POST["address_subnet{$x}"] <> "") {
|
||||
if (!is_subnet($_POST["address{$x}"] . "/" . $_POST["address_subnet{$x}"]))
|
||||
$input_errors[] = sprintf(gettext('%s/%s is not a valid subnet.'), $_POST["address{$x}"], $_POST["address_subnet{$x}"]);
|
||||
else
|
||||
$tmpaddress .= "/" . $_POST["address_subnet{$x}"];
|
||||
}
|
||||
$address[] = $tmpaddress;
|
||||
}
|
||||
if ($_POST["detail{$x}"] <> "") {
|
||||
if ((strpos($_POST["detail{$x}"], "||") === false) && (substr($_POST["detail{$x}"], 0, 1) != "|") && (substr($_POST["detail{$x}"], -1, 1) != "|")) {
|
||||
$final_address_details[] = $_POST["detail{$x}"];
|
||||
$detail_text = $_POST["detail{$x}"];
|
||||
} else {
|
||||
/* Remove leading and trailing vertical bars and replace multiple vertical bars with single, */
|
||||
/* and put in the output array so the text is at least redisplayed for the user. */
|
||||
$final_address_details[] = preg_replace('/\|\|+/', '|', trim($_POST["detail{$x}"], "|"));
|
||||
$detail_text = preg_replace('/\|\|+/', '|', trim($_POST["detail{$x}"], "|"));
|
||||
if (!$desc_fmt_err_found) {
|
||||
$input_errors[] = $vertical_bar_err_text;
|
||||
$desc_fmt_err_found = true;
|
||||
}
|
||||
}
|
||||
} else
|
||||
$final_address_details[] = sprintf(gettext("Entry added %s"), date('r'));
|
||||
} else {
|
||||
$detail_text = sprintf(gettext("Entry added %s"), date('r'));
|
||||
}
|
||||
$address_items = explode(" ", trim($_POST["address{$x}"]));
|
||||
foreach ($address_items as $address_item) {
|
||||
$iprange_type = is_iprange($address_item);
|
||||
if ($iprange_type == 4) {
|
||||
list($startip, $endip) = explode('-', $address_item);
|
||||
if ($_POST['type'] == "network") {
|
||||
// For network type aliases, expand an IPv4 range into an array of subnets.
|
||||
$rangesubnets = ip_range_to_subnet_array($startip, $endip);
|
||||
foreach ($rangesubnets as $rangesubnet) {
|
||||
if ($alias_address_count > $max_alias_addresses) {
|
||||
break;
|
||||
}
|
||||
list($address_part, $subnet_part) = explode("/", $rangesubnet);
|
||||
$input_addresses[] = $address_part;
|
||||
$input_address_subnet[] = $subnet_part;
|
||||
$final_address_details[] = $detail_text;
|
||||
$alias_address_count++;
|
||||
}
|
||||
} else {
|
||||
// For host type aliases, expand an IPv4 range into a list of individual IPv4 addresses.
|
||||
$rangeaddresses = ip_range_to_address_array($startip, $endip, $max_alias_addresses - $alias_address_count);
|
||||
if (is_array($rangeaddresses)) {
|
||||
foreach ($rangeaddresses as $rangeaddress) {
|
||||
$input_addresses[] = $rangeaddress;
|
||||
$input_address_subnet[] = "";
|
||||
$final_address_details[] = $detail_text;
|
||||
$alias_address_count++;
|
||||
}
|
||||
} else {
|
||||
$input_errors[] = sprintf(gettext('Range is too large to expand into individual host IP addresses (%s)'), $address_item);
|
||||
$input_errors[] = sprintf(gettext('The maximum number of entries in an alias is %s'), $max_alias_addresses);
|
||||
// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
|
||||
$input_addresses[] = $address_item;
|
||||
$input_address_subnet[] = "";
|
||||
$final_address_details[] = $detail_text;
|
||||
}
|
||||
}
|
||||
} else if ($iprange_type == 6) {
|
||||
$input_errors[] = sprintf(gettext('IPv6 address ranges are not supported (%s)'), $address_item);
|
||||
// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
|
||||
$input_addresses[] = $address_item;
|
||||
$input_address_subnet[] = "";
|
||||
$final_address_details[] = $detail_text;
|
||||
} else {
|
||||
$subnet_type = is_subnet($address_item);
|
||||
if (($_POST['type'] == "host") && $subnet_type) {
|
||||
if ($subnet_type == 4) {
|
||||
// For host type aliases, if the user enters an IPv4 subnet, expand it into a list of individual IPv4 addresses.
|
||||
if (subnet_size($address_item) <= ($max_alias_addresses - $alias_address_count)) {
|
||||
$rangeaddresses = subnetv4_expand($address_item);
|
||||
foreach ($rangeaddresses as $rangeaddress) {
|
||||
$input_addresses[] = $rangeaddress;
|
||||
$input_address_subnet[] = "";
|
||||
$final_address_details[] = $detail_text;
|
||||
$alias_address_count++;
|
||||
}
|
||||
} else {
|
||||
$input_errors[] = sprintf(gettext('Subnet is too large to expand into individual host IP addresses (%s)'), $address_item);
|
||||
$input_errors[] = sprintf(gettext('The maximum number of entries in an alias is %s'), $max_alias_addresses);
|
||||
// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
|
||||
$input_addresses[] = $address_item;
|
||||
$input_address_subnet[] = "";
|
||||
$final_address_details[] = $detail_text;
|
||||
}
|
||||
} else {
|
||||
$input_errors[] = sprintf(gettext('IPv6 subnets are not supported in host aliases (%s)'), $address_item);
|
||||
// Put the user-entered data in the output anyway, so it will be re-displayed for correction.
|
||||
$input_addresses[] = $address_item;
|
||||
$input_address_subnet[] = "";
|
||||
$final_address_details[] = $detail_text;
|
||||
}
|
||||
} else {
|
||||
list($address_part, $subnet_part) = explode("/", $address_item);
|
||||
if (!empty($subnet_part)) {
|
||||
if (is_subnet($address_item)) {
|
||||
$input_addresses[] = $address_part;
|
||||
$input_address_subnet[] = $subnet_part;
|
||||
} else {
|
||||
// The user typed something like "1.2.3.444/24" or "1.2.3.0/36" or similar rubbish.
|
||||
// Feed it through without splitting it apart, then it will be caught by the validation loop below.
|
||||
$input_addresses[] = $address_item;
|
||||
$input_address_subnet[] = "";
|
||||
}
|
||||
} else {
|
||||
$input_addresses[] = $address_part;
|
||||
$input_address_subnet[] = $_POST["address_subnet{$x}"];
|
||||
}
|
||||
$final_address_details[] = $detail_text;
|
||||
$alias_address_count++;
|
||||
}
|
||||
}
|
||||
if ($alias_address_count > $max_alias_addresses) {
|
||||
$input_errors[] = sprintf(gettext('The maximum number of entries in an alias has been exceeded (%s)'), $max_alias_addresses);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the input data expanded above.
|
||||
foreach($input_addresses as $idx => $input_address) {
|
||||
if (is_alias($input_address)) {
|
||||
if (!alias_same_type($input_address, $_POST['type']))
|
||||
// But alias type network can include alias type urltable. Feature#1603.
|
||||
if (!($_POST['type'] == 'network' &&
|
||||
preg_match("/urltable/i", alias_get_type($input_address))))
|
||||
$wrongaliases .= " " . $input_address;
|
||||
} else if ($_POST['type'] == "port") {
|
||||
if (!is_port($input_address) && !is_portrange($input_address))
|
||||
$input_errors[] = $input_address . " " . gettext("is not a valid port or alias.");
|
||||
} else if ($_POST['type'] == "host" || $_POST['type'] == "network") {
|
||||
if (is_subnet($input_address) ||
|
||||
(!is_ipaddr($input_address) && !is_hostname($input_address)))
|
||||
$input_errors[] = sprintf(gettext('%1$s is not a valid %2$s address, FQDN or alias.'), $input_address, $_POST['type']);
|
||||
}
|
||||
$tmpaddress = $input_address;
|
||||
if ($_POST['type'] != "host" && is_ipaddr($input_address) && $input_address_subnet[$idx] <> "") {
|
||||
if (!is_subnet($input_address . "/" . $input_address_subnet[$idx]))
|
||||
$input_errors[] = sprintf(gettext('%s/%s is not a valid subnet.'), $input_address, $input_address_subnet[$idx]);
|
||||
else
|
||||
$tmpaddress .= "/" . $input_address_subnet[$idx];
|
||||
}
|
||||
$address[] = $tmpaddress;
|
||||
}
|
||||
unset($desc_fmt_err_found);
|
||||
if ($wrongaliases <> "")
|
||||
$input_errors[] = sprintf(gettext('The alias(es): %s cannot be nested because they are not of the same type.'), $wrongaliases);
|
||||
@ -491,7 +591,7 @@ $urltable_ports_str = gettext("URL Table (Ports)");
|
||||
$update_freq_str = gettext("Update Freq. (days)");
|
||||
|
||||
$networks_help = gettext("Networks are specified in CIDR format. Select the CIDR mask that pertains to each entry. /32 specifies a single IPv4 host, /128 specifies a single IPv6 host, /24 specifies 255.255.255.0, /64 specifies a normal IPv6 network, etc. Hostnames (FQDNs) may also be specified, using a /32 mask for IPv4 or /128 for IPv6. You may also enter an IP range such as 192.168.1.1-192.168.1.254 and a list of CIDR networks will be derived to fill the range.");
|
||||
$hosts_help = gettext("Enter as many hosts as you would like. Hosts must be specified by their IP address or fully qualified domain name (FQDN). FQDN hostnames are periodically re-resolved and updated. If multiple IPs are returned by a DNS query, all are used.");
|
||||
$hosts_help = gettext("Enter as many hosts as you would like. Hosts must be specified by their IP address or fully qualified domain name (FQDN). FQDN hostnames are periodically re-resolved and updated. If multiple IPs are returned by a DNS query, all are used. You may also enter an IP range such as 192.168.1.1-192.168.1.10 or a small subnet such as 192.168.1.16/28 and a list of individual IP addresses will be generated.");
|
||||
$ports_help = gettext("Enter as many ports as you wish. Port ranges can be expressed by separating with a colon.");
|
||||
$url_help = sprintf(gettext("Enter as many URLs as you wish. After saving %s will download the URL and import the items into the alias. Use only with small sets of IP addresses (less than 3000)."), $g['product_name']);
|
||||
$url_ports_help = sprintf(gettext("Enter as many URLs as you wish. After saving %s will download the URL and import the items into the alias. Use only with small sets of Ports (less than 3000)."), $g['product_name']);
|
||||
@ -703,7 +803,7 @@ if (empty($tab)) {
|
||||
$addresses = explode(" ", $pconfig['address']);
|
||||
$details = explode("||", $pconfig['detail']);
|
||||
while ($counter < count($addresses)):
|
||||
if (is_subnet($addresses[$counter])) {
|
||||
if (($pconfig['type'] != "host") && is_subnet($addresses[$counter])) {
|
||||
list($address, $address_subnet) = explode("/", $addresses[$counter]);
|
||||
} else {
|
||||
$address = $addresses[$counter];
|
||||
|
||||
@ -101,12 +101,15 @@ if($_POST['aliasimport'] <> "") {
|
||||
$impdesc = trim($implinea[1]);
|
||||
if (strlen($impdesc) < 200) {
|
||||
if ((strpos($impdesc, "||") === false) && (substr($impdesc, 0, 1) != "|") && (substr($impdesc, -1, 1) != "|")) {
|
||||
if (is_iprange($impip)) {
|
||||
$iprange_type = is_iprange($impip);
|
||||
if ($iprange_type == 4) {
|
||||
list($startip, $endip) = explode('-', $impip);
|
||||
$rangesubnets = ip_range_to_subnet_array($startip, $endip);
|
||||
$imported_ips = array_merge($imported_ips, $rangesubnets);
|
||||
$rangedescs = array_fill(0, count($rangesubnets), $impdesc);
|
||||
$imported_descs = array_merge($imported_descs, $rangedescs);
|
||||
} else if ($iprange_type == 6) {
|
||||
$input_errors[] = sprintf(gettext('IPv6 address ranges are not supported (%s)'), $impip);
|
||||
} else if (!is_ipaddr($impip) && !is_subnet($impip) && !is_hostname($impip) && !empty($impip)) {
|
||||
$input_errors[] = sprintf(gettext("%s is not an IP address. Please correct the error to continue"), $impip);
|
||||
} elseif (!empty($impip)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user