diff --git a/api_FTL.php b/api_FTL.php
index 3e1b350a..ed6741dd 100644
--- a/api_FTL.php
+++ b/api_FTL.php
@@ -321,7 +321,7 @@ else
$allQueries = array();
foreach($return as $line)
{
- $tmp = explode(" ",$line);
+ $tmp = str_getcsv($line," ");
// UTF-8 encode domain
$tmp[2] = utf8_encode(str_replace("~"," ",$tmp[2]));
// UTF-8 encode client host name
diff --git a/api_db.php b/api_db.php
index e40ac160..427fc3cc 100644
--- a/api_db.php
+++ b/api_db.php
@@ -11,6 +11,7 @@ header('Content-type: application/json');
require("scripts/pi-hole/php/database.php");
require("scripts/pi-hole/php/password.php");
require("scripts/pi-hole/php/auth.php");
+require_once("scripts/pi-hole/php/func.php");
check_cors();
// Set maximum execution time to 10 minutes
@@ -31,7 +32,7 @@ function resolveHostname($clientip, $printIP)
return $clientname;
}
- else if(filter_var($clientip, FILTER_VALIDATE_IP))
+ else if(validIP($clientip))
{
// Get host name of client and convert to lower case
$clientname = strtolower(gethostbyaddr($ipaddr));
diff --git a/index.php b/index.php
index fd0c7ba7..ff8e71ea 100644
--- a/index.php
+++ b/index.php
@@ -150,7 +150,7 @@
-
Queries answered by
+
Upstream servers
diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js
index e8e787ef..80344564 100644
--- a/scripts/pi-hole/js/queries.js
+++ b/scripts/pi-hole/js/queries.js
@@ -75,29 +75,37 @@ $(function () {
tableApi = $("#all-queries").DataTable({
rowCallback: function (row, data) {
+ var replyid = parseInt(data[5], 10);
// DNSSEC status
var dnssecStatus;
+ var ede = data[11];
switch (data[6]) {
case "1":
- dnssecStatus = ' SECURE';
+ dnssecStatus = ' SECURE';
break;
case "2":
- dnssecStatus = ' INSECURE';
+ dnssecStatus = ' INSECURE';
break;
case "3":
- dnssecStatus = ' BOGUS';
+ dnssecStatus = ' BOGUS';
break;
case "4":
- dnssecStatus = ' ABANDONED';
+ dnssecStatus = ' ABANDONED';
break;
case "5":
- dnssecStatus = ' UNKNOWN';
+ dnssecStatus = ' UNKNOWN';
break;
default:
// No DNSSEC
dnssecStatus = "";
}
+ if (dnssecStatus.length > 0) {
+ if (ede.length > 0) dnssecStatus += " (" + ede + ")";
+ else if (replyid === 7) dnssecStatus += " (refused upstream)";
+ dnssecStatus += "";
+ }
+
// Query status
var fieldtext,
buttontext,
@@ -114,10 +122,10 @@ $(function () {
break;
case "2":
colorClass = "text-green";
- fieldtext =
- "OK (forwarded to " +
+ fieldtext = replyid === 0 ? "OK, sent to " : "OK, answered by ";
+ fieldtext +=
+ " " +
(data.length > 10 && data[10] !== "N/A" ? data[10] : "") +
- ")" +
dnssecStatus;
buttontext =
'';
@@ -208,6 +216,12 @@ $(function () {
buttontext = "";
}
+ // Add EDE here if available and not included in dnssecStatus
+ if (ede.length > 0 && dnssecStatus.length === 0) fieldtext += " (" + ede + ")";
+
+ // Cannot block internal queries of this type
+ if ((data[1] === "DNSKEY" || data[1] === "DS") && data[3] === "pi.hole") buttontext = "";
+
fieldtext += '';
if (colorClass !== false) {
@@ -252,7 +266,6 @@ $(function () {
}
// Check for existence of sixth column and display only if not Pi-holed
- var replyid = data[5];
var replytext =
replyid >= 0 && replyid < replyTypes.length ? replyTypes[replyid] : "? (" + replyid + ")";
diff --git a/scripts/pi-hole/php/auth.php b/scripts/pi-hole/php/auth.php
index 83e51995..16a7390e 100644
--- a/scripts/pi-hole/php/auth.php
+++ b/scripts/pi-hole/php/auth.php
@@ -126,7 +126,7 @@ function check_csrf($token) {
function check_domain(&$domains) {
foreach($domains as &$domain)
{
- $validDomain = is_valid_domain_name($domain);
+ $validDomain = validDomain($domain);
if(!$validDomain){
log_and_die(htmlspecialchars($domain. ' is not a valid domain'));
}
diff --git a/scripts/pi-hole/php/func.php b/scripts/pi-hole/php/func.php
index a3e82eb1..c2e42b48 100644
--- a/scripts/pi-hole/php/func.php
+++ b/scripts/pi-hole/php/func.php
@@ -6,11 +6,86 @@
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
-function is_valid_domain_name($domain_name)
+// Credit: http://stackoverflow.com/a/4694816/2087442
+// Modified because of https://github.com/pi-hole/AdminLTE/pull/533
+ini_set("pcre.recursion_limit", 1500);
+function validDomain($domain_name, &$message = NULL)
{
- return (preg_match("/^((-|_)*[a-z\d]((-|_)*[a-z\d])*(-|_)*)(\.(-|_)*([a-z\d]((-|_)*[a-z\d])*))*$/i", $domain_name) && // Valid chars check
- preg_match("/^.{1,253}$/", $domain_name) && // Overall length check
- preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name)); // Length of each label
+ if(!preg_match("/^((-|_)*[a-z\d]((-|_)*[a-z\d])*(-|_)*)(\.(-|_)*([a-z\d]((-|_)*[a-z\d])*))*$/i", $domain_name)) {
+ if($message !== NULL)
+ $message = "it contains invalid characters";
+ return false;
+ }
+ if(!preg_match("/^.{1,253}$/", $domain_name)) {
+ if($message !== NULL)
+ $message = "its length is invalid";
+ return false;
+ }
+ if(!preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name)) {
+ if($message !== NULL)
+ $message = "at least one label is of invalid length";
+ return false;
+ }
+
+ // everything is okay
+ return true;
+}
+
+function validDomainWildcard($domain_name)
+{
+ // There has to be either no or at most one "*" at the beginning of a line
+ $validChars = preg_match("/^((\*.)?[_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([_a-z\d])*)*$/i", $domain_name);
+ $lengthCheck = preg_match("/^.{1,253}$/", $domain_name);
+ $labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name);
+ return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label
+}
+
+function validIP($address){
+ if (preg_match('/[.:0]/', $address) && !preg_match('/[1-9a-f]/', $address)) {
+ // Test if address contains either `:` or `0` but not 1-9 or a-f
+ return false;
+ }
+ return !filter_var($address, FILTER_VALIDATE_IP) === false;
+}
+
+function validCIDRIP($address){
+ // This validation strategy has been taken from ../js/groups-common.js
+ $isIPv6 = strpos($address, ":") !== false;
+ if($isIPv6) {
+ // One IPv6 element is 16bit: 0000 - FFFF
+ $v6elem = "[0-9A-Fa-f]{1,4}";
+ // CIDR for IPv6 is any multiple of 4 from 4 up to 128 bit
+ $v6cidr = "(4";
+ for ($i=8; $i <= 128; $i+=4) {
+ $v6cidr .= "|$i";
+ }
+ $v6cidr .= ")";
+ $validator = "/^(((?:$v6elem))((?::$v6elem))*::((?:$v6elem))((?::$v6elem))*|((?:$v6elem))((?::$v6elem)){7})\/$v6cidr$/";
+ return preg_match($validator, $address);
+ } else {
+ // One IPv4 element is 8bit: 0 - 256
+ $v4elem = "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)";
+ // Note that rev-server accepts only /8, /16, /24, and /32
+ $allowedv4cidr = "(8|16|24|32)";
+ $validator = "/^$v4elem\.$v4elem\.$v4elem\.$v4elem\/$allowedv4cidr$/";
+ return preg_match($validator, $address);
+ }
+}
+
+function validMAC($mac_addr)
+{
+ // Accepted input format: 00:01:02:1A:5F:FF (characters may be lower case)
+ return !filter_var($mac_addr, FILTER_VALIDATE_MAC) === false;
+}
+
+function validEmail($email)
+{
+ return filter_var($email, FILTER_VALIDATE_EMAIL)
+ // Make sure that the email does not contain special characters which
+ // may be used to execute shell commands, even though they may be valid
+ // in an email address. If the escaped email does not equal the original
+ // email, it is not safe to store in setupVars.
+ && escapeshellcmd($email) === $email;
}
function get_ip_type($ip)
@@ -145,7 +220,7 @@ function addCustomDNSEntry($ip="", $domain="", $json=true)
if (empty($domain))
return returnError("Domain must be set", $json);
- if (!is_valid_domain_name($domain))
+ if (!validDomain($domain))
return returnError("Domain must be valid", $json);
// Only check for duplicates if adding new records from the web UI (not through Teleporter)
@@ -302,13 +377,13 @@ function addCustomCNAMEEntry($domain="", $target="", $json=true)
if (empty($target))
return returnError("Target must be set", $json);
- if (!is_valid_domain_name($target))
+ if (!validDomain($target))
return returnError("Target must be valid", $json);
// Check if each submitted domain is valid
$domains = array_map('trim', explode(",", $domain));
foreach ($domains as $d) {
- if (!is_valid_domain_name($d))
+ if (!validDomain($d))
return returnError("Domain '$d' is not valid", $json);
}
diff --git a/scripts/pi-hole/php/groups.php b/scripts/pi-hole/php/groups.php
index 6bc423e6..49a8d51c 100644
--- a/scripts/pi-hole/php/groups.php
+++ b/scripts/pi-hole/php/groups.php
@@ -649,15 +649,16 @@ if ($_POST['action'] == 'get_groups') {
{
// If adding to the exact lists, we convert the domain lower case and check whether it is valid
$domain = strtolower($domain);
- if(filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) === false)
+ $msg = "";
+ if(!validDomain($domain, $msg))
{
// This is the case when idn_to_ascii() modified the string
if($input !== $domain && strlen($domain) > 0)
- $errormsg = 'Domain ' . htmlentities($input) . ' (converted to "' . htmlentities(utf8_encode($domain)) . '") is not a valid domain.';
+ $errormsg = 'Domain ' . htmlentities($input) . ' (converted to "' . htmlentities(utf8_encode($domain)) . '") is not a valid domain because ' . $msg . '.';
elseif($input !== $domain)
- $errormsg = 'Domain ' . htmlentities($input) . ' is not a valid domain.';
+ $errormsg = 'Domain ' . htmlentities($input) . ' is not a valid domain because ' . $msg . '.';
else
- $errormsg = 'Domain ' . htmlentities(utf8_encode($domain)) . ' is not a valid domain.';
+ $errormsg = 'Domain ' . htmlentities(utf8_encode($domain)) . ' is not a valid domain because ' . $msg . '.';
throw new Exception($errormsg . ' Added ' . $added . " out of ". $total . " domains");
}
}
diff --git a/scripts/pi-hole/php/queryads.php b/scripts/pi-hole/php/queryads.php
index f247c87a..38d4e8d2 100644
--- a/scripts/pi-hole/php/queryads.php
+++ b/scripts/pi-hole/php/queryads.php
@@ -9,6 +9,7 @@
while (ob_get_level() > 0) {
ob_end_flush();
}
+require_once("func.php");
ini_set("output_buffering", "0");
ob_implicit_flush(true);
header('Content-Type: text/event-stream');
@@ -21,22 +22,12 @@ function echoEvent($datatext) {
echo $datatext;
}
-// Credit: http://stackoverflow.com/a/4694816/2087442
-ini_set("pcre.recursion_limit", 1500);
-function is_valid_domain_name($domain_name)
-{
- return ($domain_name[0] !== '-' // Don't allow domains to appear as command line options
- && preg_match("/^((-|_)*[a-z\d]((-|_)*[a-z\d])*(-|_)*)(\.(-|_)*([a-z\d]((-|_)*[a-z\d])*))*$/i", $domain_name) // Valid chars check
- && preg_match("/^.{1,253}$/", $domain_name) // Overall length check
- && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name) ); // Length of each label
-}
-
// Test if domain is set
if(isset($_GET["domain"]))
{
// Is this a valid domain?
$url = $_GET["domain"];
- if(!is_valid_domain_name($url))
+ if(!validDomain($url))
{
echoEvent("Invalid domain!");
die();
diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php
index 36f8def4..e987e27f 100644
--- a/scripts/pi-hole/php/savesettings.php
+++ b/scripts/pi-hole/php/savesettings.php
@@ -6,43 +6,13 @@
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
+require_once("func.php");
+
if(!in_array(basename($_SERVER['SCRIPT_FILENAME']), ["settings.php", "teleporter.php"], true))
{
die("Direct access to this script is forbidden!");
}
-function validIP($address){
- if (preg_match('/[.:0]/', $address) && !preg_match('/[1-9a-f]/', $address)) {
- // Test if address contains either `:` or `0` but not 1-9 or a-f
- return false;
- }
- return !filter_var($address, FILTER_VALIDATE_IP) === false;
-}
-
-function validCIDRIP($address){
- // This validation strategy has been taken from ../js/groups-common.js
- $isIPv6 = strpos($address, ":") !== false;
- if($isIPv6) {
- // One IPv6 element is 16bit: 0000 - FFFF
- $v6elem = "[0-9A-Fa-f]{1,4}";
- // CIDR for IPv6 is any multiple of 4 from 4 up to 128 bit
- $v6cidr = "(4";
- for ($i=8; $i <= 128; $i+=4) {
- $v6cidr .= "|$i";
- }
- $v6cidr .= ")";
- $validator = "/^(((?:$v6elem))((?::$v6elem))*::((?:$v6elem))((?::$v6elem))*|((?:$v6elem))((?::$v6elem)){7})\/$v6cidr$/";
- return preg_match($validator, $address);
- } else {
- // One IPv4 element is 8bit: 0 - 256
- $v4elem = "(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)";
- // Note that rev-server accepts only /8, /16, /24, and /32
- $allowedv4cidr = "(8|16|24|32)";
- $validator = "/^$v4elem\.$v4elem\.$v4elem\.$v4elem\/$allowedv4cidr$/";
- return preg_match($validator, $address);
- }
-}
-
// Check for existance of variable
// and test it only if it exists
function istrue(&$argument) {
@@ -56,30 +26,6 @@ function istrue(&$argument) {
return false;
}
-// Credit: http://stackoverflow.com/a/4694816/2087442
-function validDomain($domain_name)
-{
- $validChars = preg_match("/^([_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([_a-z\d])*)*$/i", $domain_name);
- $lengthCheck = preg_match("/^.{1,253}$/", $domain_name);
- $labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name);
- return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label
-}
-
-function validDomainWildcard($domain_name)
-{
- // There has to be either no or at most one "*" at the beginning of a line
- $validChars = preg_match("/^((\*\.)?[_a-z\d](-*[_a-z\d])*)(\.([_a-z\d](-*[a-z\d])*))*(\.([_a-z\d])*)*$/i", $domain_name);
- $lengthCheck = preg_match("/^.{1,253}$/", $domain_name);
- $labelLengthCheck = preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name);
- return ( $validChars && $lengthCheck && $labelLengthCheck ); //length of each label
-}
-
-function validMAC($mac_addr)
-{
- // Accepted input format: 00:01:02:1A:5F:FF (characters may be lower case)
- return !filter_var($mac_addr, FILTER_VALIDATE_MAC) === false;
-}
-
function formatMAC($mac_addr)
{
preg_match("/([0-9a-fA-F]{2}[:]){5}([0-9a-fA-F]{2})/", $mac_addr, $matches);
@@ -88,16 +34,6 @@ function formatMAC($mac_addr)
return null;
}
-function validEmail($email)
-{
- return filter_var($email, FILTER_VALIDATE_EMAIL)
- // Make sure that the email does not contain special characters which
- // may be used to execute shell commands, even though they may be valid
- // in an email address. If the escaped email does not equal the original
- // email, it is not safe to store in setupVars.
- && escapeshellcmd($email) === $email;
-}
-
$dhcp_static_leases = array();
function readStaticLeasesFile($origin_file="/etc/dnsmasq.d/04-pihole-static-dhcp.conf")
{
diff --git a/settings.php b/settings.php
index a59fe423..d08d17fb 100644
--- a/settings.php
+++ b/settings.php
@@ -63,9 +63,7 @@ if (isset($_POST["submit"])) {