summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Mazoyer <respawneral@gmail.com>2014-09-03 11:19:56 +0200
committerGuillaume Mazoyer <respawneral@gmail.com>2014-09-03 11:19:56 +0200
commit0512ffb7f70f85223a71ffd539b74459793178af (patch)
tree9c97d86b9b3f4ba908f2f217c70a777dbb03b5a5
parentd9fcd2d238eaf8ab61de5c8a1ef5ad6fbd5d1778 (diff)
Add config to disallow the use of private and reserved IP ranges.
-rw-r--r--execute.php6
-rw-r--r--includes/config.defaults.php13
-rw-r--r--includes/utils.php88
-rw-r--r--routers/bird.php2
-rw-r--r--routers/cisco.php2
-rw-r--r--routers/juniper.php2
-rw-r--r--routers/quagga.php2
7 files changed, 104 insertions, 11 deletions
diff --git a/execute.php b/execute.php
index 330e070..26e91af 100644
--- a/execute.php
+++ b/execute.php
@@ -78,9 +78,9 @@ if (isset($_POST['doc']) && !empty($_POST['doc'])) {
if (isset($_POST['query']) && !empty($_POST['query']) &&
isset($_POST['routers']) && !empty($_POST['routers']) &&
isset($_POST['parameters']) && !empty($_POST['parameters'])) {
- $query = htmlspecialchars($_POST['query']);
- $hostname = htmlspecialchars($_POST['routers']);
- $parameters = htmlspecialchars($_POST['parameters']);
+ $query = trim($_POST['query']);
+ $hostname = trim($_POST['routers']);
+ $parameters = trim($_POST['parameters']);
// Do the processing
$router = Router::instance($hostname, $requester);
diff --git a/includes/config.defaults.php b/includes/config.defaults.php
index 06fac62..aca58ff 100644
--- a/includes/config.defaults.php
+++ b/includes/config.defaults.php
@@ -28,7 +28,12 @@ $config = array(
// Logs file when commands will be written
'logs' => '/var/log/looking-glass.log',
// Allow private ASN
- 'allow_private_asn' => false
+ 'allow_private_asn' => false,
+ // Allow RFC1918 IPv4 and FD/FC IPv6 as parameters
+ 'allow_private_ip' => true,
+ // Allow reserved IPv4 addresses (0.0.0.0/8, 169.254.0.0/16,
+ // 192.0.2.0/24 and 224.0.0.0/4)
+ 'allow_reserved_ip' => true
),
// Documentation (must be HTML)
@@ -37,7 +42,7 @@ $config = array(
'bgp' => array(
'command' => 'show route IP_ADDRESS',
'description' => 'Show the best routes to a given destination.',
- 'parameter' => 'The parameter must be a valid destination. Destination means an IPv4/IPv6 address or a subnet. Masks are also accepted as part of a valid IPv4/IPv6 address.<br />Please note that some routers always need a mask to be given when looking for an IPv6 address.<br /><br />Example of valid arguments:<br /><ul><li>10.1.1.1</li><li>172.16.0.0/12</li><li>2001:db8:1337::42</li><li>2001:db8::/32</li>'
+ 'parameter' => 'The parameter must be a valid destination. Destination means an IPv4/IPv6 address or a subnet. Masks are also accepted as part of a valid IPv4/IPv6 address.<br />RFC1918 addresses, IPv6 starting with FD or FC, and IPv4 reserved ranges (0.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24 and 224.0.0.0/4) may be refused.<br />Please note that some routers always need a mask to be given when looking for an IPv6 address.<br /><br />Example of valid arguments:<br /><ul><li>8.8.8.8</li><li>8.8.4.0/24</li><li>2001:db8:1337::42</li><li>2001:db8::/32</li>'
),
// Documentation for the 'as-path-regex' query
'as-path-regex' => array(
@@ -55,13 +60,13 @@ $config = array(
'ping' => array(
'command' => 'ping IP_ADDRESS',
'description' => 'Send 10 pings to the given destination.',
- 'parameter' => 'The parameter must be an IPv4/IPv6 address (without mask) or a fully qualified domain name.<br /><br />Example of valid arguments:<br /><ul><li>10.1.1.1</li><li>2001:db8:1337::42</li><li>example.com</li></ul>'
+ 'parameter' => 'The parameter must be an IPv4/IPv6 address (without mask) or a fully qualified domain name.<br />RFC1918 addresses, IPv6 starting with FD or FC, and IPv4 reserved ranges (0.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24 and 224.0.0.0/4) may be refused.<br /><br />Example of valid arguments:<br /><ul><li>8.8.8.8</li><li>2001:db8:1337::42</li><li>example.com</li></ul>'
),
// Documentation for the 'traceroute' query
'traceroute' => array(
'command' =>'traceroute IP_ADDRESS',
'description' => 'Display the path to a given destination.',
- 'parameter' => 'The parameter must be an IPv4/IPv6 address (without mask) or a fully qualified domain name.<br /><br />Example of valid arguments:<br /><ul><li>10.1.1.1</li><li>2001:db8:1337::42</li><li>example.com</li></ul>'
+ 'parameter' => 'The parameter must be an IPv4/IPv6 address (without mask) or a fully qualified domain name.<br />RFC1918 addresses, IPv6 starting with FD or FC, and IPv4 reserved ranges (0.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24 and 224.0.0.0/4) may be refused.<br /><br />Example of valid arguments:<br /><ul><li>8.8.8.8</li><li>2001:db8:1337::42</li><li>example.com</li></ul>'
)
)
diff --git a/includes/utils.php b/includes/utils.php
index 1319690..01b034c 100644
--- a/includes/utils.php
+++ b/includes/utils.php
@@ -22,6 +22,40 @@
require_once 'config.php';
/**
+ * Test if a given parameter is a private IPv4 or IPv6.
+ *
+ * @param string $ip the parameter to test.
+ * @return boolean true if the parameter is a private IP address, false
+ * otherwise.
+ */
+function match_private_ip_range($ip) {
+ if (empty($ip)) {
+ return false;
+ }
+
+ $is_private = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
+
+ return (!$is_private ? true : false);
+}
+
+/**
+ * Test if a given parameter is a reserved IPv4.
+ *
+ * @param string $ip the parameter to test.
+ * @return boolean true if the parameter is a reserved IPv4 address, false
+ * otherwise.
+ */
+function match_reserved_ip_range($ip) {
+ if (empty($ip)) {
+ return false;
+ }
+
+ $is_reserved = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE);
+
+ return (!$is_reserved ? true : false);
+}
+
+/**
* Test if a given parameter is an IPv4 or not.
*
* @param string $ip the parameter to test.
@@ -33,12 +67,38 @@ require_once 'config.php';
* otherwise.
*/
function match_ipv4($ip, $ip_only = true) {
+ global $config;
+
+ if (empty($ip)) {
+ return false;
+ }
+
if (strrpos($ip, '/') && !$ip_only) {
$ip_and_mask = explode('/', $ip, 2);
+ if (!$config['misc']['allow_private_ip'] &&
+ match_private_ip_range($ip_and_mask[0])) {
+ return false;
+ }
+
+ if (!$config['misc']['allow_reserved_ip'] &&
+ match_reserved_ip_range($ip_and_mask[0])) {
+ return false;
+ }
+
return filter_var($ip_and_mask[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) &&
filter_var($ip_and_mask[1], FILTER_VALIDATE_INT);
} else {
+ if (!$config['misc']['allow_private_ip'] &&
+ match_private_ip_range($ip)) {
+ return false;
+ }
+
+ if (!$config['misc']['allow_reserved_ip'] &&
+ match_reserved_ip_range($ip)) {
+ return false;
+ }
+
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
}
}
@@ -55,12 +115,28 @@ function match_ipv4($ip, $ip_only = true) {
* otherwise.
*/
function match_ipv6($ip, $ip_only = true) {
+ global $config;
+
+ if (empty($ip)) {
+ return false;
+ }
+
if (strrpos($ip, '/') && !$ip_only) {
$ip_and_mask = explode('/', $ip, 2);
+ if (!$config['misc']['allow_private_ip'] &&
+ match_private_ip_range($ip_and_mask[0])) {
+ return false;
+ }
+
return filter_var($ip_and_mask[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) &&
filter_var($ip_and_mask[1], FILTER_VALIDATE_INT);
} else {
+ if (!$config['misc']['allow_private_ip'] &&
+ match_private_ip_range($ip)) {
+ return false;
+ }
+
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
}
}
@@ -74,6 +150,10 @@ function match_ipv6($ip, $ip_only = true) {
function match_fqdn($fqdn) {
$regex = '/(?=^.{4,255}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}$)/';
+ if (empty($fqdn)) {
+ return false;
+ }
+
if ((preg_match($regex, $fqdn) === false) ||
(preg_match($regex, $fqdn) === 0)) {
return false;
@@ -101,6 +181,10 @@ function match_as($as) {
'options' => array('min_range' => 4200000000, 'max_range' => 4294967294)
);
+ if (empty($as)) {
+ return false;
+ }
+
if (!filter_var($as, FILTER_VALIDATE_INT, $options_wide_range)) {
return false;
}
@@ -119,6 +203,10 @@ function match_as($as) {
}
function match_aspath_regex($aspath_regex) {
+ if (empty($aspath_regex)) {
+ return false;
+ }
+
// TODO: validate a regex with a regex?
return true;
}
diff --git a/routers/bird.php b/routers/bird.php
index a9fec59..25d7544 100644
--- a/routers/bird.php
+++ b/routers/bird.php
@@ -47,7 +47,7 @@ final class Bird extends Router {
$commands[] = $birdc6.' \'show route where bgp_path ~ [= '.
$parameters.' =]\'';
} else {
- throw new Exception('The parameter is not an AS-Path regular expression like ".*XXXX YYYY.*".');
+ throw new Exception('The parameter is not an AS-Path regular expression.');
}
break;
diff --git a/routers/cisco.php b/routers/cisco.php
index b7eb01c..304cb56 100644
--- a/routers/cisco.php
+++ b/routers/cisco.php
@@ -42,7 +42,7 @@ final class Cisco extends Router {
$commands[] = 'show bgp ipv4 unicast quote-regexp "'.$parameters.'"';
$commands[] = 'show bgp ipv6 unicast quote-regexp "'.$parameters.'"';
} else {
- throw new Exception('The parameter is not an AS-Path regular expression like ".*XXXX YYYY.*".');
+ throw new Exception('The parameter is not an AS-Path regular expression.');
}
break;
diff --git a/routers/juniper.php b/routers/juniper.php
index 99da240..d80b4f8 100644
--- a/routers/juniper.php
+++ b/routers/juniper.php
@@ -46,7 +46,7 @@ final class Juniper extends Router {
$commands[] = 'show route aspath-regex "'.$parameters.
'" protocol bgp table inet6.0';
} else {
- throw new Exception('The parameter is not an AS-Path regular expression like ".*XXXX YYYY.*".');
+ throw new Exception('The parameter is not an AS-Path regular expression.');
}
break;
diff --git a/routers/quagga.php b/routers/quagga.php
index 642ff4e..2dc7dc2 100644
--- a/routers/quagga.php
+++ b/routers/quagga.php
@@ -44,7 +44,7 @@ final class Quagga extends Router {
$commands[] = $vtysh.'show ip bgp regexp '.$parameters.'"';
$commands[] = $vtysh.'show ipv6 bgp regexp '.$parameters.'"';
} else {
- throw new Exception('The parameter is not an AS-Path regular expression like ".*XXXX YYYY.*".');
+ throw new Exception('The parameter is not an AS-Path regular expression.');
}
break;