From 678dfd0fa8d629bd45edad576c99d03aa8f40d70 Mon Sep 17 00:00:00 2001 From: Erik Fonnesbeck Date: Tue, 9 Nov 2010 05:14:29 -0700 Subject: [PATCH] Add a setting for the data type of values used with DHCP option numbers and input validation for each type. Fixes #962 --- etc/inc/services.inc | 11 +++++- usr/local/www/services_dhcp.php | 66 +++++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/etc/inc/services.inc b/etc/inc/services.inc index 487178e9e4..68a7128466 100644 --- a/etc/inc/services.inc +++ b/etc/inc/services.inc @@ -120,7 +120,11 @@ function services_dhcpd_configure() { foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) { if(is_array($dhcpifconf['numberoptions']) && is_array($dhcpifconf['numberoptions']['item'])) { foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) { - $custoptions .= "option custom-{$dhcpif}-{$itemidx} code {$item['number']} = text;\n"; + if(!empty($item['type'])) + $itemtype = $item['type']; + else + $itemtype = "text"; + $custoptions .= "option custom-{$dhcpif}-{$itemidx} code {$item['number']} = {$itemtype};\n"; } } } @@ -314,7 +318,10 @@ EOD; $dhcpdconf .= "\n"; if($dhcpifconf['numberoptions']['item']) { foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) { - $dhcpdconf .= " option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n"; + if(empty($item['type']) || $item['type'] == "text") + $dhcpdconf .= " option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n"; + else + $dhcpdconf .= " option custom-{$dhcpif}-{$itemidx} {$item['value']};\n"; } } diff --git a/usr/local/www/services_dhcp.php b/usr/local/www/services_dhcp.php index 0365ccb9c2..79fc1dca7f 100755 --- a/usr/local/www/services_dhcp.php +++ b/usr/local/www/services_dhcp.php @@ -198,7 +198,8 @@ if ($_POST) { if(isset($_POST["number{$x}"]) && ctype_digit($_POST["number{$x}"])) { $numbervalue = array(); $numbervalue['number'] = htmlspecialchars($_POST["number{$x}"]); - $numbervalue['value'] = htmlspecialchars($_POST["value{$x}"]); + $numbervalue['type'] = htmlspecialchars($_POST["itemtype{$x}"]); + $numbervalue['value'] = str_replace('"', '"', htmlspecialchars($_POST["value{$x}"])); $numberoptions['item'][] = $numbervalue; } } @@ -260,6 +261,31 @@ if ($_POST) { if ($_POST['staticarp'] && $noip) $input_errors[] = "Cannot enable static ARP when you have static map entries without IP addresses. Ensure all static maps have IP addresses and try again."; + if(is_array($pconfig['numberoptions']['item'])) { + foreach ($pconfig['numberoptions']['item'] as $numberoption) { + if ( $numberoption['type'] == 'text' && strstr($numberoption['value'], '"') ) + $input_errors[] = gettext("Text type cannot include quotation marks."); + else if ( $numberoption['type'] == 'string' && !preg_match('/^"[^"]*"$/', $numberoption['value']) && !preg_match('/^[0-9a-z]{2}(?:\:[0-9a-z]{2})*$/i', $numberoption['value']) ) + $input_errors[] = gettext("String type must be enclosed in quotes like \"this\" or must be a series of octets specified in hexadecimal, separated by colons, like 01:23:45:67:89:ab:cd:ef"); + else if ( $numberoption['type'] == 'flag' && $numberoption['value'] != 'true' && $numberoption['value'] != 'false' && $numberoption['value'] != 'on' && $numberoption['value'] != 'off' ) + $input_errors[] = gettext("Boolean type must be true, false, on, or off."); + else if ( $numberoption['type'] == 'uint8' && (!is_numeric($numberoption['value']) || $numberoption['value'] < 0 || $numberoption['value'] > 255) ) + $input_errors[] = gettext("Unsigned 8-bit integer type must be a number in the range 0 to 255."); + else if ( $numberoption['type'] == 'uint16' && (!is_numeric($numberoption['value']) || $numberoption['value'] < 0 || $numberoption['value'] > 65535) ) + $input_errors[] = gettext("Unsigned 16-bit integer type must be a number in the range 0 to 65535."); + else if ( $numberoption['type'] == 'uint32' && (!is_numeric($numberoption['value']) || $numberoption['value'] < 0 || $numberoption['value'] > 4294967295) ) + $input_errors[] = gettext("Unsigned 32-bit integer type must be a number in the range 0 to 4294967295."); + else if ( $numberoption['type'] == 'int8' && (!is_numeric($numberoption['value']) || $numberoption['value'] < -128 || $numberoption['value'] > 127) ) + $input_errors[] = gettext("Signed 8-bit integer type must be a number in the range -128 to 127."); + else if ( $numberoption['type'] == 'int16' && (!is_numeric($numberoption['value']) || $numberoption['value'] < -32768 || $numberoption['value'] > 32767) ) + $input_errors[] = gettext("Signed 16-bit integer type must be a number in the range -32768 to 32767."); + else if ( $numberoption['type'] == 'int32' && (!is_numeric($numberoption['value']) || $numberoption['value'] < -2147483648 || $numberoption['value'] > 2147483647) ) + $input_errors[] = gettext("Signed 32-bit integer type must be a number in the range -2147483648 to 2147483647."); + else if ( $numberoption['type'] == 'ip-address' && !is_ipaddr($numberoption['value']) && !is_hostname($numberoption['value']) ) + $input_errors[] = gettext("IP address or host type must be an IP address or host name."); + } + } + if (!$input_errors) { /* make sure the range lies within the current subnet */ $subnet_start = ip2ulong(long2ip32(ip2long($ifcfgip) & gen_subnet_mask_long($ifcfgsn))); @@ -401,12 +427,25 @@ include("head.inc");