From ccda9a2630106ef95e300e49d82bbbe3c804befa Mon Sep 17 00:00:00 2001 From: TheME Date: Wed, 15 Nov 2017 00:09:47 +0100 Subject: [PATCH 01/41] replace Alerts with Modal * * and add specific css style-sheet for it --- queries.php | 75 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/queries.php b/queries.php index ebd06443..2a73626a 100644 --- a/queries.php +++ b/queries.php @@ -76,6 +76,40 @@ if(strlen($showing) > 0) $showing = "(".$showing.")"; } ?> + + @@ -88,18 +122,35 @@ if(strlen($showing) > 0) --> - - - -
-
- - - - - - - - - - - - - - - - - - - - - -
TimeTypeDomainClientStatusAction
TimeTypeDomainClientStatusAction
-
-
+ + + + + + + + + + + + + + + + + + + + + +
TimeTypeDomainClientStatusAction
TimeTypeDomainClientStatusAction
+ diff --git a/queries.php b/queries.php index ebd06443..bd9df8fe 100644 --- a/queries.php +++ b/queries.php @@ -110,32 +110,30 @@ if(strlen($showing) > 0)
-
- - - - - - - - - - - - - - - - - - - - - -
TimeTypeDomainClientStatusAction
TimeTypeDomainClientStatusAction
-
- -
+ + + + + + + + + + + + + + + + + + + + + +
TimeTypeDomainClientStatusAction
TimeTypeDomainClientStatusAction
+ + diff --git a/scripts/pi-hole/js/db_queries.js b/scripts/pi-hole/js/db_queries.js index 8551e9dc..8a47df5c 100644 --- a/scripts/pi-hole/js/db_queries.js +++ b/scripts/pi-hole/js/db_queries.js @@ -201,13 +201,13 @@ $(document).ready(function() { else if (data[4] === 2) { $(row).css("color","green"); - $("td:eq(4)", row).html( "OK (forwarded)" ); + $("td:eq(4)", row).html( "OK (forwarded)" ); $("td:eq(5)", row).html( "" ); } else if (data[4] === 3) { $(row).css("color","green"); - $("td:eq(4)", row).html( "OK (cached)" ); + $("td:eq(4)", row).html( "OK (cached)" ); $("td:eq(5)", row).html( "" ); // statistics[1]++; @@ -215,20 +215,20 @@ $(document).ready(function() { else if (data[4] === 4) { $(row).css("color","red"); - $("td:eq(4)", row).html( "Pi-holed (wildcard)" ); + $("td:eq(4)", row).html( "Pi-holed (wildcard)" ); $("td:eq(5)", row).html( "" ); // statistics[3]++; } else { - $("td:eq(4)", row).html( "Unknown ("+data[4]+")" ); + $("td:eq(4)", row).html( "Unknown ("+data[4]+")" ); $("td:eq(5)", row).html( "" ); } // statistics[0]++; }, dom: "<'row'<'col-sm-12'f>>" + "<'row'<'col-sm-4'l><'col-sm-8'p>>" + - "<'row'<'col-sm-12'tr>>" + + "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", "ajax": {"url": APIstring, "error": handleAjaxError }, "autoWidth" : false, @@ -236,12 +236,12 @@ $(document).ready(function() { "deferRender": true, "order" : [[0, "desc"]], "columns": [ - { "width" : "20%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD HH:mm:ss z");}else{return data;} }}, + { "width" : "15%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD []HH:mm:ss z");}else{return data;} }}, { "width" : "10%" }, { "width" : "40%" }, + { "width" : "20%" }, { "width" : "10%" }, - { "width" : "10%" }, - { "width" : "10%" }, + { "width" : "5%" }, ], "lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]], "columnDefs": [ { diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js index 24e37b88..50bf40a9 100644 --- a/scripts/pi-hole/js/queries.js +++ b/scripts/pi-hole/js/queries.js @@ -136,26 +136,26 @@ $(document).ready(function() { else if (data[4] === "2") { $(row).css("color","green"); - $("td:eq(4)", row).html( "OK (forwarded)" ); + $("td:eq(4)", row).html( "OK (forwarded)" ); $("td:eq(5)", row).html( "" ); } else if (data[4] === "3") { $(row).css("color","green"); - $("td:eq(4)", row).html( "OK (cached)" ); + $("td:eq(4)", row).html( "OK (cached)" ); $("td:eq(5)", row).html( "" ); } else if (data[4] === "4") { $(row).css("color","red"); - $("td:eq(4)", row).html( "Pi-holed (wildcard)" ); + $("td:eq(4)", row).html( "Pi-holed (wildcard)" ); $("td:eq(5)", row).html( "" ); } else if (data[4] === "5") { $(row).css("color","red"); - $("td:eq(4)", row).html( "Pi-holed (blacklist)" ); + $("td:eq(4)", row).html( "Pi-holed (blacklist)" ); $("td:eq(5)", row).html( "" ); } else @@ -166,19 +166,19 @@ $(document).ready(function() { }, dom: "<'row'<'col-sm-12'f>>" + "<'row'<'col-sm-4'l><'col-sm-8'p>>" + - "<'row'<'col-sm-12'tr>>" + + "<'row'<'col-sm-12'<'table-responsive'tr>>>" + "<'row'<'col-sm-5'i><'col-sm-7'p>>", "ajax": {"url": APIstring, "error": handleAjaxError }, "autoWidth" : false, "processing": true, "order" : [[0, "desc"]], "columns": [ - { "width" : "20%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD HH:mm:ss z");}else{return data;} }}, + { "width" : "15%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD []HH:mm:ss z");}else{return data;} }}, { "width" : "10%" }, { "width" : "40%", "render": $.fn.dataTable.render.text() }, - { "width" : "10%", "render": $.fn.dataTable.render.text() }, - { "width" : "10%" }, + { "width" : "20%", "render": $.fn.dataTable.render.text() }, { "width" : "10%" }, + { "width" : "5%" }, ], "lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]], "columnDefs": [ { diff --git a/style/pi-hole.css b/style/pi-hole.css index 3fc896c8..9cf11441 100644 --- a/style/pi-hole.css +++ b/style/pi-hole.css @@ -36,12 +36,47 @@ a.lookatme { -webkit-animation-iteration-count: infinite; animation-iteration-count: infinite; } -#all-queries { - table-layout: fixed; + +.table-responsive { + -webkit-overflow-scrolling: touch; } -#all-queries tbody { - word-wrap: break-word; + +/* Optimize Queries-Table for small screens */ +#all-queries td:nth-of-type(1), /* Time column */ +#all-queries td:nth-of-type(5) { /* Status column */ + white-space: nowrap; } +#all-queries td:nth-of-type(3) { /* Domain column */ + min-width: 200px; + word-break: break-all; + white-space: pre-wrap; +} +#all-queries_info { /* Allow Info String to wrap (useful while filtering entries on small screen) */ + white-space: unset; +} +#all-queries_wrapper .pagination > li > a { /* adjust the buttons width */ + padding-left: 6px; + padding-right: 6px; + min-width: 34px; + text-align: center; +} +@media screen and (max-width: 500px), + screen and (min-width: 767px) and (max-width: 1000px) { + /* Hide "Previous" & "Next"-Buttons in Pagination */ + #all-queries_wrapper .pagination > li.previous, + #all-queries_wrapper .pagination > li.next { + display: none; + } + #all-queries_wrapper .pagination > li:nth-of-type(2) a { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + } + #all-queries_wrapper .pagination > li:nth-last-of-type(2) a { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + } +} + .main-header>.navbar { height: 50px; } From bc1f6f9be631b9d2d01d94d1c43dab516c81ed8e Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 30 Dec 2017 18:26:49 +0100 Subject: [PATCH 10/41] Add quad9 secondary IPv4 server Signed-off-by: DL6ER --- scripts/pi-hole/php/savesettings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php index ad1b0eae..3d56f53b 100644 --- a/scripts/pi-hole/php/savesettings.php +++ b/scripts/pi-hole/php/savesettings.php @@ -123,7 +123,7 @@ function isinserverlist($addr) { "Norton" => ["v4_1" => "199.85.126.10", "v4_2" => "199.85.127.10"], "Comodo" => ["v4_1" => "8.26.56.26", "v4_2" => "8.20.247.20"], "DNS.WATCH" => ["v4_1" => "84.200.69.80", "v4_2" => "84.200.70.40", "v6_1" => "2001:1608:10:25:0:0:1c04:b12f", "v6_2" => "2001:1608:10:25:0:0:9249:d69b"], - "Quad9" => ["v4_1" => "9.9.9.9", "v6_1" => "2620:fe::fe"] + "Quad9" => ["v4_1" => "9.9.9.9", "v4_2" => "149.112.112.112", "v6_1" => "2620:fe::fe"] ]; $adlist = []; From 78a8aa8b31936512a9e348ddc8f4d47853c00317 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 30 Dec 2017 23:44:01 +0100 Subject: [PATCH 11/41] Check if $results is boolean and use fetchArray() only if it isn't Signed-off-by: DL6ER --- api_db.php | 95 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 34 deletions(-) diff --git a/api_db.php b/api_db.php index e624296c..2263bade 100644 --- a/api_db.php +++ b/api_db.php @@ -62,20 +62,17 @@ if(!$db) if (isset($_GET['getAllQueries']) && $auth) { - if($_GET['getAllQueries'] === "empty") - { - $allQueries = array(); - } - else + $allQueries = array(); + if($_GET['getAllQueries'] !== "empty") { $from = intval($_GET["from"]); $until = intval($_GET["until"]); $results = $db->query('SELECT timestamp,type,domain,client,status FROM queries WHERE timestamp >= '.$from.' AND timestamp <= '.$until.' ORDER BY timestamp ASC'); - $allQueries = array(); - while ($row = $results->fetchArray()) - { - $allQueries[] = [$row[0],$row[1] == 1 ? "IPv4" : "IPv6",$row[2],$row[3],$row[4]]; - } + if(!is_bool($results)) + while ($row = $results->fetchArray()) + { + $allQueries[] = [$row[0],$row[1] == 1 ? "IPv4" : "IPv6",$row[2],$row[3],$row[4]]; + } } $result = array('data' => $allQueries); $data = array_merge($data, $result); @@ -98,12 +95,15 @@ if (isset($_GET['topClients']) && $auth) $limit = "WHERE timestamp <= ".$_GET["until"]; } $results = $db->query('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 10'); + $clients = array(); - while ($row = $results->fetchArray()) - { - $clients[$row[0]] = intval($row[1]); - // var_dump($row); - } + + if(!is_bool($results)) + while ($row = $results->fetchArray()) + { + $clients[$row[0]] = intval($row[1]); + // var_dump($row); + } $result = array('top_sources' => $clients); $data = array_merge($data, $result); } @@ -125,11 +125,14 @@ if (isset($_GET['topDomains']) && $auth) $limit = " AND timestamp <= ".$_GET["until"]; } $results = $db->query('SELECT domain,count(domain) FROM queries WHERE (STATUS == 2 OR STATUS == 3)'.$limit.' GROUP by domain order by count(domain) desc limit 10'); + $domains = array(); - while ($row = $results->fetchArray()) - { - $domains[$row[0]] = intval($row[1]); - } + + if(!is_bool($results)) + while ($row = $results->fetchArray()) + { + $domains[$row[0]] = intval($row[1]); + } $result = array('top_domains' => $domains); $data = array_merge($data, $result); } @@ -151,11 +154,14 @@ if (isset($_GET['topAds']) && $auth) $limit = " AND timestamp <= ".$_GET["until"]; } $results = $db->query('SELECT domain,count(domain) FROM queries WHERE (STATUS == 1 OR STATUS == 4)'.$limit.' GROUP by domain order by count(domain) desc limit 10'); + $addomains = array(); - while ($row = $results->fetchArray()) - { - $addomains[$row[0]] = intval($row[1]); - } + + if(!is_bool($results)) + while ($row = $results->fetchArray()) + { + $addomains[$row[0]] = intval($row[1]); + } $result = array('top_ads' => $addomains); $data = array_merge($data, $result); } @@ -163,21 +169,36 @@ if (isset($_GET['topAds']) && $auth) if (isset($_GET['getMinTimestamp']) && $auth) { $results = $db->query('SELECT MIN(timestamp) FROM queries'); - $result = array('mintimestamp' => $results->fetchArray()[0]); + + if(!is_bool($results)) + $result = array('mintimestamp' => $results->fetchArray()[0]); + else + $result = array(); + $data = array_merge($data, $result); } if (isset($_GET['getMaxTimestamp']) && $auth) { $results = $db->query('SELECT MAX(timestamp) FROM queries'); - $result = array('maxtimestamp' => $results->fetchArray()[0]); + + if(!is_bool($results)) + $result = array('maxtimestamp' => $results->fetchArray()[0]); + else + $result = array(); + $data = array_merge($data, $result); } if (isset($_GET['getQueriesCount']) && $auth) { $results = $db->query('SELECT COUNT(timestamp) FROM queries'); - $result = array('count' => $results->fetchArray()[0]); + + if(!is_bool($results)) + $result = array('count' => $results->fetchArray()[0]); + else + $result = array(); + $data = array_merge($data, $result); } @@ -216,21 +237,27 @@ if (isset($_GET['getGraphData']) && $auth) // Count permitted queries in intervals $results = $db->query('SELECT (timestamp/'.$interval.')*'.$interval.' interval, COUNT(*) FROM queries WHERE (status == 2 OR status == 3)'.$limit.' GROUP by interval ORDER by interval'); + $domains = array(); - while ($row = $results->fetchArray()) - { - $domains[$row[0]] = intval($row[1]); - } + + if(!is_bool($results)) + while ($row = $results->fetchArray()) + { + $domains[$row[0]] = intval($row[1]); + } $result = array('domains_over_time' => $domains); $data = array_merge($data, $result); // Count blocked queries in intervals $results = $db->query('SELECT (timestamp/'.$interval.')*'.$interval.' interval, COUNT(*) FROM queries WHERE (status == 1 OR status == 4 OR status == 5)'.$limit.' GROUP by interval ORDER by interval'); + $addomains = array(); - while ($row = $results->fetchArray()) - { - $addomains[$row[0]] = intval($row[1]); - } + + if(!is_bool($results)) + while ($row = $results->fetchArray()) + { + $addomains[$row[0]] = intval($row[1]); + } $result = array('ads_over_time' => $addomains); $data = array_merge($data, $result); } From b5adf6d28a14550de5581a1e7700a6c3ca41a7d8 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 31 Dec 2017 16:41:27 +0100 Subject: [PATCH 12/41] Show DNSSEC result in Query Log (if available) Signed-off-by: DL6ER --- queries.php | 2 ++ scripts/pi-hole/js/queries.js | 36 +++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/queries.php b/queries.php index f511f8d1..705a22d6 100644 --- a/queries.php +++ b/queries.php @@ -119,6 +119,7 @@ if(strlen($showing) > 0) Domain Client Status + DNSSEC Action @@ -129,6 +130,7 @@ if(strlen($showing) > 0) Domain Client Status + DNSSEC Action diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js index 984215bc..246c20bf 100644 --- a/scripts/pi-hole/js/queries.js +++ b/scripts/pi-hole/js/queries.js @@ -135,37 +135,56 @@ $(document).ready(function() { { $(row).css("color","red"); $("td:eq(4)", row).html( "Pi-holed" ); - $("td:eq(5)", row).html( "" ); + $("td:eq(6)", row).html( "" ); } else if (data[4] === "2") { $(row).css("color","green"); $("td:eq(4)", row).html( "OK (forwarded)" ); - $("td:eq(5)", row).html( "" ); + $("td:eq(6)", row).html( "" ); } else if (data[4] === "3") { $(row).css("color","green"); $("td:eq(4)", row).html( "OK (cached)" ); - $("td:eq(5)", row).html( "" ); + $("td:eq(6)", row).html( "" ); } else if (data[4] === "4") { $(row).css("color","red"); $("td:eq(4)", row).html( "Pi-holed (wildcard)" ); - $("td:eq(5)", row).html( "" ); + $("td:eq(6)", row).html( "" ); } else if (data[4] === "5") { $(row).css("color","red"); $("td:eq(4)", row).html( "Pi-holed (blacklist)" ); - $("td:eq(5)", row).html( "" ); + $("td:eq(6)", row).html( "" ); } else { $("td:eq(4)", row).html( "Unknown" ); - $("td:eq(5)", row).html( "" ); + $("td:eq(6)", row).html( "" ); + } + if (data[5] === "1") + { + $("td:eq(5)", row).css("color","green"); + $("td:eq(5)", row).html( "SECURE" ); + } + else if (data[5] === "2") + { + $("td:eq(5)", row).css("color","orange"); + $("td:eq(5)", row).html( "INSECURE" ); + } + else if (data[5] === "5") + { + $("td:eq(5)", row).css("color","red"); + $("td:eq(5)", row).html( "BOGUS" ); + } + else + { + $("td:eq(5)", row).html( "-" ); } }, dom: "<'row'<'col-sm-12'f>>" + @@ -179,9 +198,10 @@ $(document).ready(function() { "columns": [ { "width" : "20%", "render": function (data, type, full, meta) { if(type === "display"){return moment.unix(data).format("Y-MM-DD HH:mm:ss z");}else{return data;} }}, { "width" : "10%" }, - { "width" : "40%", "render": $.fn.dataTable.render.text() }, - { "width" : "10%", "render": $.fn.dataTable.render.text() }, + { "width" : "37%", "render": $.fn.dataTable.render.text() }, + { "width" : "8%", "render": $.fn.dataTable.render.text() }, { "width" : "10%" }, + { "width" : "5%" }, { "width" : "10%" }, ], "lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]], From d9d477f7fbab001120eb61baa79d5c623df69255 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 31 Dec 2017 16:50:31 +0100 Subject: [PATCH 13/41] Add "BOGUS" and unknown ("?") Signed-off-by: DL6ER --- scripts/pi-hole/js/queries.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js index 246c20bf..3642248b 100644 --- a/scripts/pi-hole/js/queries.js +++ b/scripts/pi-hole/js/queries.js @@ -177,11 +177,16 @@ $(document).ready(function() { $("td:eq(5)", row).css("color","orange"); $("td:eq(5)", row).html( "INSECURE" ); } - else if (data[5] === "5") + else if (data[5] === "3") { $("td:eq(5)", row).css("color","red"); $("td:eq(5)", row).html( "BOGUS" ); } + else if (data[5] === "4") + { + $("td:eq(5)", row).css("color","red"); + $("td:eq(5)", row).html( "?" ); + } else { $("td:eq(5)", row).html( "-" ); From f5930e134cd165fb5b6a8c5e0ff77cef5aff0a1d Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 31 Dec 2017 17:19:21 +0100 Subject: [PATCH 14/41] Add ABANDONED result Signed-off-by: DL6ER --- scripts/pi-hole/js/queries.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js index 3642248b..cc9df897 100644 --- a/scripts/pi-hole/js/queries.js +++ b/scripts/pi-hole/js/queries.js @@ -183,6 +183,11 @@ $(document).ready(function() { $("td:eq(5)", row).html( "BOGUS" ); } else if (data[5] === "4") + { + $("td:eq(5)", row).css("color","red"); + $("td:eq(5)", row).html( "ABANDONED" ); + } + else if (data[5] === "5") { $("td:eq(5)", row).css("color","red"); $("td:eq(5)", row).html( "?" ); From 6500d4628967f6c077fdd06c94bd7c568846a12a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 31 Dec 2017 17:20:41 +0100 Subject: [PATCH 15/41] Unspecified is no error, so make it black Signed-off-by: DL6ER --- scripts/pi-hole/js/queries.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pi-hole/js/queries.js b/scripts/pi-hole/js/queries.js index cc9df897..bb83e777 100644 --- a/scripts/pi-hole/js/queries.js +++ b/scripts/pi-hole/js/queries.js @@ -194,6 +194,7 @@ $(document).ready(function() { } else { + $("td:eq(5)", row).css("color","black"); $("td:eq(5)", row).html( "-" ); } }, From f2a0b622f1f8c38bb2c4a070a62b19d589b77c1d Mon Sep 17 00:00:00 2001 From: Mark Drobnak Date: Tue, 2 Jan 2018 11:59:51 -0500 Subject: [PATCH 16/41] Fix preg_split warning Warning was: `preg_split(): Delimiter must not be alphanumeric or backslash` Signed-off-by: Mark Drobnak --- scripts/pi-hole/php/auth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pi-hole/php/auth.php b/scripts/pi-hole/php/auth.php index 85d38f8f..f5032488 100644 --- a/scripts/pi-hole/php/auth.php +++ b/scripts/pi-hole/php/auth.php @@ -119,7 +119,7 @@ function check_csrf($token) { function check_domain() { if(isset($_POST['domain'])){ - $domains = preg_split('\s+', $_POST['domain']); + $domains = preg_split('/\s+/', $_POST['domain']); foreach($domains as $domain) { $validDomain = is_valid_domain_name($domain); From 746df3b63fd0d94524b645a25916dd5345c9643b Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 5 Jan 2018 23:19:02 +0100 Subject: [PATCH 17/41] Decide whether FTL is on any custom branch by looking for "vDev" in the beginning of the version string Signed-off-by: DL6ER --- scripts/pi-hole/php/update_checker.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pi-hole/php/update_checker.php b/scripts/pi-hole/php/update_checker.php index 9bd4ab06..d479318a 100644 --- a/scripts/pi-hole/php/update_checker.php +++ b/scripts/pi-hole/php/update_checker.php @@ -44,12 +44,12 @@ else /********** Get Pi-hole FTL (not a git repository) **********/ $FTL_branch = $branches[2]; - if($FTL_branch !== "master") { + if(substr($versions[2], 0, 4) === "vDev") { $FTL_current = "vDev"; $FTL_commit = $versions[2]; } else { - $FTL_current = explode("-",$versions[2])[0]; + $FTL_current = $versions[2]; } // Get data from GitHub From b0a56e9017c7649be6306d4312554b23d437da0e Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Fri, 5 Jan 2018 17:48:53 -0500 Subject: [PATCH 18/41] Add warning to block lists tab of settings page Signed-off-by: Mcat12 --- settings.php | 1 + 1 file changed, 1 insertion(+) diff --git a/settings.php b/settings.php index a032c9ee..0af4711e 100644 --- a/settings.php +++ b/settings.php @@ -288,6 +288,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists" From f0f32e82a5282714a22e7154c5d9d1c3bb5c4bf2 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 7 Jan 2018 17:49:55 +0100 Subject: [PATCH 19/41] Convert all client host names to lower case when requesting api_db.php?topClients Signed-off-by: DL6ER --- api_db.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_db.php b/api_db.php index 2263bade..161f8d87 100644 --- a/api_db.php +++ b/api_db.php @@ -94,7 +94,7 @@ if (isset($_GET['topClients']) && $auth) { $limit = "WHERE timestamp <= ".$_GET["until"]; } - $results = $db->query('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 10'); + $results = $db->query('SELECT LOWER(client),count(LOWER(client)) FROM queries '.$limit.' GROUP by LOWER(client) order by count(LOWER(client)) desc limit 10'); $clients = array(); From 047329a4aeabbeccfefa1882dd270a852b64382d Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 7 Jan 2018 18:02:13 +0100 Subject: [PATCH 20/41] Reset the SQL syntax - directly doing it in PHP is obviously much faster! Signed-off-by: DL6ER --- api_db.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/api_db.php b/api_db.php index 161f8d87..df64176d 100644 --- a/api_db.php +++ b/api_db.php @@ -94,15 +94,25 @@ if (isset($_GET['topClients']) && $auth) { $limit = "WHERE timestamp <= ".$_GET["until"]; } - $results = $db->query('SELECT LOWER(client),count(LOWER(client)) FROM queries '.$limit.' GROUP by LOWER(client) order by count(LOWER(client)) desc limit 10'); + $results = $db->query('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 10'); $clients = array(); if(!is_bool($results)) while ($row = $results->fetchArray()) { - $clients[$row[0]] = intval($row[1]); - // var_dump($row); + // Convert client to lower case + $c = strtolower($row[0]); + if(array_key_exists($c, $clients)) + { + // Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database) + $clients[$c] += intval($row[1]); + } + else + { + // Entry does not yet exist + $clients[$c] = intval($row[1]); + } } $result = array('top_sources' => $clients); $data = array_merge($data, $result); From 9cc8062c88ce6b562ccbcd6c05a83e4fde2e524f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 7 Jan 2018 18:07:39 +0100 Subject: [PATCH 21/41] Fetch up to 20 clients and limit the list to 10 results in PHP Signed-off-by: DL6ER --- api_db.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api_db.php b/api_db.php index df64176d..ff723d43 100644 --- a/api_db.php +++ b/api_db.php @@ -94,12 +94,13 @@ if (isset($_GET['topClients']) && $auth) { $limit = "WHERE timestamp <= ".$_GET["until"]; } - $results = $db->query('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 10'); + $results = $db->query('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 20'); $clients = array(); + $num = 0; if(!is_bool($results)) - while ($row = $results->fetchArray()) + while (($row = $results->fetchArray()) && $num < 10) { // Convert client to lower case $c = strtolower($row[0]); @@ -112,6 +113,8 @@ if (isset($_GET['topClients']) && $auth) { // Entry does not yet exist $clients[$c] = intval($row[1]); + // Increase number of clients + $num++; } } $result = array('top_sources' => $clients); From 84012074de5952452859499a8e9c414d026d26bf Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 7 Jan 2018 18:15:08 +0100 Subject: [PATCH 22/41] Add the same logic for topDomains Signed-off-by: DL6ER --- api_db.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/api_db.php b/api_db.php index ff723d43..dd4e1ecc 100644 --- a/api_db.php +++ b/api_db.php @@ -137,14 +137,28 @@ if (isset($_GET['topDomains']) && $auth) { $limit = " AND timestamp <= ".$_GET["until"]; } - $results = $db->query('SELECT domain,count(domain) FROM queries WHERE (STATUS == 2 OR STATUS == 3)'.$limit.' GROUP by domain order by count(domain) desc limit 10'); + $results = $db->query('SELECT domain,count(domain) FROM queries WHERE (STATUS == 2 OR STATUS == 3)'.$limit.' GROUP by domain order by count(domain) desc limit 20'); $domains = array(); + $num = 0; if(!is_bool($results)) - while ($row = $results->fetchArray()) + while (($row = $results->fetchArray()) && $num < 10) { - $domains[$row[0]] = intval($row[1]); + // Convert client to lower case + $c = strtolower($row[0]); + if(array_key_exists($c, $domains)) + { + // Entry already exists, add to it (might appear multiple times due to mixed capitalization in the database) + $domains[$c] += intval($row[1]); + } + else + { + // Entry does not yet exist + $domains[$c] = intval($row[1]); + // Increase number of domains + $num++; + } } $result = array('top_domains' => $domains); $data = array_merge($data, $result); From 0fbd8608277bdd0dc5078e7a1938732215c8f8e8 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 7 Jan 2018 19:13:58 +0100 Subject: [PATCH 23/41] Process all returned data before sorting and slicing the data Signed-off-by: DL6ER --- api_db.php | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/api_db.php b/api_db.php index dd4e1ecc..04980e94 100644 --- a/api_db.php +++ b/api_db.php @@ -97,10 +97,9 @@ if (isset($_GET['topClients']) && $auth) $results = $db->query('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 20'); $clients = array(); - $num = 0; if(!is_bool($results)) - while (($row = $results->fetchArray()) && $num < 10) + while ($row = $results->fetchArray()) { // Convert client to lower case $c = strtolower($row[0]); @@ -113,10 +112,15 @@ if (isset($_GET['topClients']) && $auth) { // Entry does not yet exist $clients[$c] = intval($row[1]); - // Increase number of clients - $num++; } } + + // Sort by number of hits + arsort($clients); + + // Extract only the first ten entries + $clients = array_slice($clients, 0, 10); + $result = array('top_sources' => $clients); $data = array_merge($data, $result); } @@ -140,10 +144,9 @@ if (isset($_GET['topDomains']) && $auth) $results = $db->query('SELECT domain,count(domain) FROM queries WHERE (STATUS == 2 OR STATUS == 3)'.$limit.' GROUP by domain order by count(domain) desc limit 20'); $domains = array(); - $num = 0; if(!is_bool($results)) - while (($row = $results->fetchArray()) && $num < 10) + while ($row = $results->fetchArray()) { // Convert client to lower case $c = strtolower($row[0]); @@ -156,10 +159,15 @@ if (isset($_GET['topDomains']) && $auth) { // Entry does not yet exist $domains[$c] = intval($row[1]); - // Increase number of domains - $num++; } } + + // Sort by number of hits + arsort($domains); + + // Extract only the first ten entries + $domains = array_slice($domains, 0, 10); + $result = array('top_domains' => $domains); $data = array_merge($data, $result); } From 081f0bb98c27f4b21414ad467e81f6f921933477 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sun, 7 Jan 2018 14:04:38 -0500 Subject: [PATCH 24/41] Add timeout warning to database pages Signed-off-by: Mcat12 --- db_graph.php | 6 +++++- db_lists.php | 5 +++++ db_queries.php | 5 +++++ scripts/pi-hole/js/db_graph.js | 4 ++++ scripts/pi-hole/js/db_lists.js | 17 +++++++++++++++++ scripts/pi-hole/js/db_queries.js | 4 ++++ 6 files changed, 40 insertions(+), 1 deletion(-) diff --git a/db_graph.php b/db_graph.php index 9dbdba73..2642bf14 100644 --- a/db_graph.php +++ b/db_graph.php @@ -22,7 +22,6 @@ $token = $_SESSION['token'];

Compute graphical statistics from the Pi-hole query database

-
@@ -39,6 +38,11 @@ $token = $_SESSION['token'];
+ + +
diff --git a/db_lists.php b/db_lists.php index 0ddc9dda..c0e39408 100644 --- a/db_lists.php +++ b/db_lists.php @@ -39,6 +39,11 @@ $token = $_SESSION['token'];
+ + + + + +
diff --git a/scripts/pi-hole/js/db_graph.js b/scripts/pi-hole/js/db_graph.js index d543f16b..8da24ad6 100644 --- a/scripts/pi-hole/js/db_graph.js +++ b/scripts/pi-hole/js/db_graph.js @@ -14,6 +14,8 @@ var from = moment(start__).utc().valueOf()/1000; var end__ = moment(); var until = moment(end__).utc().valueOf()/1000; +var timeoutWarning = $("#timeoutWarning"); + $(function () { $("#querytime").daterangepicker( { @@ -80,6 +82,7 @@ function compareNumbers(a, b) { function updateQueriesOverTime() { $("#queries-over-time .overlay").show(); + timeoutWarning.show(); $.getJSON("api_db.php?getGraphData&from="+from+"&until="+until, function(data) { // convert received objects to arrays @@ -135,6 +138,7 @@ function updateQueriesOverTime() { timeLineChart.options.scales.xAxes[0].display=true; $("#queries-over-time .overlay").hide(); + timeoutWarning.hide(); timeLineChart.update(); }); } diff --git a/scripts/pi-hole/js/db_lists.js b/scripts/pi-hole/js/db_lists.js index 75a21746..89c460c1 100644 --- a/scripts/pi-hole/js/db_lists.js +++ b/scripts/pi-hole/js/db_lists.js @@ -14,6 +14,9 @@ var from = moment(start__).utc().valueOf()/1000; var end__ = moment(); var until = moment(end__).utc().valueOf()/1000; +var timeoutWarning = $("#timeoutWarning"); +var listsStillLoading = 0; + $(function () { $("#querytime").daterangepicker( { @@ -97,6 +100,10 @@ function updateTopClientsChart() { } $("#client-frequency .overlay").hide(); + + listsStillLoading--; + if(listsStillLoading == 0) + timeoutWarning.hide(); }); } @@ -135,6 +142,10 @@ function updateTopDomainsChart() { } $("#domain-frequency .overlay").hide(); + + listsStillLoading--; + if(listsStillLoading == 0) + timeoutWarning.hide(); }); } @@ -171,10 +182,16 @@ function updateTopAdsChart() { } $("#ad-frequency .overlay").hide(); + + listsStillLoading--; + if(listsStillLoading == 0) + timeoutWarning.hide(); }); } $("#querytime").on("apply.daterangepicker", function(ev, picker) { + timeoutWarning.show(); + listsStillLoading = 3; updateTopClientsChart(); updateTopDomainsChart(); updateTopAdsChart(); diff --git a/scripts/pi-hole/js/db_queries.js b/scripts/pi-hole/js/db_queries.js index 8551e9dc..459d87ce 100644 --- a/scripts/pi-hole/js/db_queries.js +++ b/scripts/pi-hole/js/db_queries.js @@ -16,6 +16,8 @@ var until = moment(end__).utc().valueOf()/1000; var instantquery = false; var daterange; +var timeoutWarning = $("#timeoutWarning"); + // Do we want to filter queries? var GETDict = {}; location.search.substr(1).split("&").forEach(function(item) {GETDict[item.split("=")[0]] = item.split("=")[1];}); @@ -141,6 +143,7 @@ function handleAjaxError( xhr, textStatus, error ) { var reloadCallback = function() { + timeoutWarning.hide(); statistics = [0,0,0,0]; var data = tableApi.rows().data(); for (var i = 0; i < data.length; i++) { @@ -171,6 +174,7 @@ var reloadCallback = function() }; function refreshTableData() { + timeoutWarning.show(); var APIstring = "api_db.php?getAllQueries&from="+from+"&until="+until; statistics = [0,0,0]; tableApi.ajax.url(APIstring).load(reloadCallback); From 322f73fcacc29a6063d2f8e0c0dba7be017221c5 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sun, 7 Jan 2018 14:13:57 -0500 Subject: [PATCH 25/41] Use triple equals Signed-off-by: Mcat12 --- scripts/pi-hole/js/db_lists.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pi-hole/js/db_lists.js b/scripts/pi-hole/js/db_lists.js index 89c460c1..3358cf33 100644 --- a/scripts/pi-hole/js/db_lists.js +++ b/scripts/pi-hole/js/db_lists.js @@ -102,7 +102,7 @@ function updateTopClientsChart() { $("#client-frequency .overlay").hide(); listsStillLoading--; - if(listsStillLoading == 0) + if(listsStillLoading === 0) timeoutWarning.hide(); }); } From afe2f73bef30feac6ff1335299de10ff561270f7 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sun, 7 Jan 2018 14:20:41 -0500 Subject: [PATCH 26/41] Use triple equals in the other places too Signed-off-by: Mcat12 --- scripts/pi-hole/js/db_lists.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pi-hole/js/db_lists.js b/scripts/pi-hole/js/db_lists.js index 3358cf33..43e569f7 100644 --- a/scripts/pi-hole/js/db_lists.js +++ b/scripts/pi-hole/js/db_lists.js @@ -144,7 +144,7 @@ function updateTopDomainsChart() { $("#domain-frequency .overlay").hide(); listsStillLoading--; - if(listsStillLoading == 0) + if(listsStillLoading === 0) timeoutWarning.hide(); }); } @@ -184,7 +184,7 @@ function updateTopAdsChart() { $("#ad-frequency .overlay").hide(); listsStillLoading--; - if(listsStillLoading == 0) + if(listsStillLoading === 0) timeoutWarning.hide(); }); } From 0fdebd070c96b4cc57c3f147051bb23ad30be24a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 7 Jan 2018 20:22:38 +0100 Subject: [PATCH 27/41] Set maximum execution time to 10 minutes in api_db.php Signed-off-by: DL6ER --- api_db.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api_db.php b/api_db.php index 04980e94..45b98919 100644 --- a/api_db.php +++ b/api_db.php @@ -12,6 +12,9 @@ require("scripts/pi-hole/php/password.php"); require("scripts/pi-hole/php/auth.php"); check_cors(); +// Set maximum execution time to 10 minutes +ini_set("max_execution_time","600"); + $data = array(); // Get posible non-standard location of FTL's database From 60814298ef7270db30afdf342f3fea80d87a3e7a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 7 Jan 2018 20:46:15 +0100 Subject: [PATCH 28/41] Total queries should be (all of them) not only (forwarded + cached) Signed-off-by: DL6ER --- api_db.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_db.php b/api_db.php index 45b98919..2cd99bf8 100644 --- a/api_db.php +++ b/api_db.php @@ -274,7 +274,7 @@ if (isset($_GET['getGraphData']) && $auth) } // Count permitted queries in intervals - $results = $db->query('SELECT (timestamp/'.$interval.')*'.$interval.' interval, COUNT(*) FROM queries WHERE (status == 2 OR status == 3)'.$limit.' GROUP by interval ORDER by interval'); + $results = $db->query('SELECT (timestamp/'.$interval.')*'.$interval.' interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval'); $domains = array(); From a2d9e7c1ac7e413e26f672fba05cfb4c32c717c0 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Mon, 8 Jan 2018 22:03:27 -0500 Subject: [PATCH 29/41] Add auditlog.list to the Teleporter Signed-off-by: Mcat12 --- scripts/pi-hole/php/teleporter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/pi-hole/php/teleporter.php b/scripts/pi-hole/php/teleporter.php index 0427b7c0..9efe7fd1 100644 --- a/scripts/pi-hole/php/teleporter.php +++ b/scripts/pi-hole/php/teleporter.php @@ -176,6 +176,7 @@ else archive_add_file("/etc/pihole/","blacklist.txt"); archive_add_file("/etc/pihole/","adlists.list"); archive_add_file("/etc/pihole/","setupVars.conf"); + archive_add_file("/etc/pihole/","auditlog.list"); archive_add_directory("/etc/dnsmasq.d/"); $archive["wildcardblocking.txt"] = getWildcardListContent(); From 323b3a7a8b169ed95782d87d3daddbb539762813 Mon Sep 17 00:00:00 2001 From: Mark Drobnak Date: Wed, 10 Jan 2018 15:53:16 -0500 Subject: [PATCH 30/41] Fix Top Clients filter It expected IP addresses, but only let in domains Signed-off-by: Mark Drobnak --- scripts/pi-hole/php/savesettings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php index 3d56f53b..a85b65ce 100644 --- a/scripts/pi-hole/php/savesettings.php +++ b/scripts/pi-hole/php/savesettings.php @@ -320,7 +320,7 @@ function readAdlists() $first = true; foreach($clients as $client) { - if(!validDomainWildcard($client)) + if(!validIP($domain)) { $error .= "Top Clients entry ".htmlspecialchars($client)." is invalid (use only IP addresses)!
"; } From 34b6c3751624d615634dec0cbf7bb019ca2cc0c3 Mon Sep 17 00:00:00 2001 From: Mark Drobnak Date: Thu, 11 Jan 2018 15:33:31 -0500 Subject: [PATCH 31/41] Fix IP check and allow host names in Top Clients filter Signed-off-by: Mark Drobnak --- scripts/pi-hole/php/savesettings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php index a85b65ce..7b67ffed 100644 --- a/scripts/pi-hole/php/savesettings.php +++ b/scripts/pi-hole/php/savesettings.php @@ -320,9 +320,9 @@ function readAdlists() $first = true; foreach($clients as $client) { - if(!validIP($domain)) + if(!validDomainWildcard($client) && !validIP($client)) { - $error .= "Top Clients entry ".htmlspecialchars($client)." is invalid (use only IP addresses)!
"; + $error .= "Top Clients entry ".htmlspecialchars($client)." is invalid (use only host names and IP addresses)!
"; } if(!$first) { From a5cd0d193eb2d8214d98e2442e508f8d808cdb95 Mon Sep 17 00:00:00 2001 From: Chris Hollenbeck <1334439+hollec@users.noreply.github.com> Date: Sat, 13 Jan 2018 13:27:38 -0500 Subject: [PATCH 32/41] Clean up formatting in settings page Signed-off-by: Chris Hollenbeck <1334439+hollec@users.noreply.github.com> --- settings.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/settings.php b/settings.php index 0af4711e..f6e5de1e 100644 --- a/settings.php +++ b/settings.php @@ -786,14 +786,14 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
+ ?>>Never forward non-FQDNs
+ ?>>Never forward reverse lookups for private IP ranges

Note that enabling these two options may increase your privacy @@ -1068,7 +1068,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists" - Pi-hole hostname + Pi-hole hostname: From 86e4dbec94c3da964ca40367a312e401fba1f6ab Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 16 Jan 2018 22:12:05 +0100 Subject: [PATCH 33/41] Use "lan" as suggested TLD for DHCP generated domains Signed-off-by: DL6ER --- settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.php b/settings.php index f6e5de1e..741eb649 100644 --- a/settings.php +++ b/settings.php @@ -345,7 +345,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists" if (isset($setupVars["PIHOLE_DOMAIN"])) { $piHoleDomain = $setupVars["PIHOLE_DOMAIN"]; } else { - $piHoleDomain = "local"; + $piHoleDomain = "lan"; } ?>

From 78f6cb37515412975ebfa299c9e85ccbde0f1d8b Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 18 Jan 2018 17:09:20 +0100 Subject: [PATCH 34/41] Add option to disable logging without flushing logs (for temporary disabling without wanting to nuke the logs). Signed-off-by: DL6ER --- scripts/pi-hole/js/settings.js | 21 +++++++++++++++++++-- scripts/pi-hole/php/savesettings.php | 7 ++++++- settings.php | 15 +++++++++++++-- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/scripts/pi-hole/js/settings.js b/scripts/pi-hole/js/settings.js index 0edae1bc..257ab7d4 100644 --- a/scripts/pi-hole/js/settings.js +++ b/scripts/pi-hole/js/settings.js @@ -85,7 +85,7 @@ $(".confirm-flushlogs").confirm({ }); $(".confirm-disablelogging").confirm({ - text: "Note that disabling query logging will render graphs on the web user interface useless. Are you sure you want to disable your logging?", + text: "Note that disabling query logging will render graphs on the web user interface useless. Are you sure you want to disable logging and flush your Pi-hole logs?", title: "Confirmation required", confirm(button) { $("#disablelogsform").submit(); @@ -93,7 +93,7 @@ $(".confirm-disablelogging").confirm({ cancel(button) { // nothing to do }, - confirmButton: "Yes, disable logs", + confirmButton: "Yes, disable logs and flush my logs", cancelButton: "No, go back", post: true, confirmButtonClass: "btn-danger", @@ -101,6 +101,23 @@ $(".confirm-disablelogging").confirm({ dialogClass: "modal-dialog modal-mg" }); +$(".confirm-disablelogging-noflush").confirm({ + text: "Note that disabling query logging will render graphs on the web user interface useless after this point. Are you sure you want to disable logging?", + title: "Confirmation required", + confirm(button) { + $("#disablelogsform-noflush").submit(); + }, + cancel(button) { + // nothing to do + }, + confirmButton: "Yes, disable logs", + cancelButton: "No, go back", + post: true, + confirmButtonClass: "btn-warning", + cancelButtonClass: "btn-success", + dialogClass: "modal-dialog modal-mg" +}); + $(".api-token").confirm({ text: "Make sure that nobody else can scan this code around you. They will have full access to the API without having to know the password. Note that the generation of the QR code will take some time.", title: "Confirmation required", diff --git a/scripts/pi-hole/php/savesettings.php b/scripts/pi-hole/php/savesettings.php index 7b67ffed..64914e77 100644 --- a/scripts/pi-hole/php/savesettings.php +++ b/scripts/pi-hole/php/savesettings.php @@ -278,7 +278,12 @@ function readAdlists() if($_POST["action"] === "Disable") { exec("sudo pihole -l off"); - $success .= "Logging has been disabled"; + $success .= "Logging has been disabled and logs have been flushed"; + } + elseif($_POST["action"] === "Disable-noflush") + { + exec("sudo pihole -l off noflush"); + $success .= "Logging has been disabled, your logs have not been flushed"; } else { diff --git a/settings.php b/settings.php index f6e5de1e..b01d0b25 100644 --- a/settings.php +++ b/settings.php @@ -1149,7 +1149,7 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
- + @@ -1160,7 +1160,13 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists"
-
+
+ + + +
+ +
@@ -1188,6 +1194,11 @@ if (isset($_GET['tab']) && in_array($_GET['tab'], array("sysadmin", "blocklists" +
+ + + +
From ad614a2b937383dca99e0b87ebf3f5bdb437116d Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Fri, 19 Jan 2018 16:57:47 -0500 Subject: [PATCH 35/41] Fix list_verify XSS Signed-off-by: Mcat12 --- scripts/pi-hole/php/auth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/pi-hole/php/auth.php b/scripts/pi-hole/php/auth.php index f5032488..7bebba29 100644 --- a/scripts/pi-hole/php/auth.php +++ b/scripts/pi-hole/php/auth.php @@ -146,7 +146,7 @@ function list_verify($type) { require("password.php"); if($wrongpassword || !$auth) { - log_and_die("Wrong password - ".htmlspecialchars($type)."listing of ${_POST['domain']} not permitted"); + log_and_die("Wrong password - ".htmlspecialchars($type)."listing of ".htmlspecialchars($_POST['domain'])." not permitted"); } } else From a2b30e9fe9e1f8a5d8f6bb73e0ae89efaa94f620 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Fri, 19 Jan 2018 17:08:05 -0500 Subject: [PATCH 36/41] Sanitize debug text before sending Signed-off-by: Mcat12 --- scripts/pi-hole/php/debug.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/pi-hole/php/debug.php b/scripts/pi-hole/php/debug.php index 39d5c8ea..27a23545 100644 --- a/scripts/pi-hole/php/debug.php +++ b/scripts/pi-hole/php/debug.php @@ -18,10 +18,12 @@ $token = isset($_GET["token"]) ? $_GET["token"] : ""; check_csrf($token); function echoEvent($datatext) { + $data = htmlspecialchars($datatext); + if(!isset($_GET["IE"])) - echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n"; + echo "data: ".implode("\ndata: ", explode("\n", $data))."\n\n"; else - echo $datatext; + echo $data; } if(isset($_GET["upload"])) From f89cbee1aac94fe524809f035d87d1c29ae37e26 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Fri, 19 Jan 2018 17:40:04 -0500 Subject: [PATCH 37/41] Fix SQL injections Signed-off-by: Mcat12 --- api_db.php | 56 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/api_db.php b/api_db.php index 2cd99bf8..70d6e96d 100644 --- a/api_db.php +++ b/api_db.php @@ -70,7 +70,10 @@ if (isset($_GET['getAllQueries']) && $auth) { $from = intval($_GET["from"]); $until = intval($_GET["until"]); - $results = $db->query('SELECT timestamp,type,domain,client,status FROM queries WHERE timestamp >= '.$from.' AND timestamp <= '.$until.' ORDER BY timestamp ASC'); + $stmt = $db->prepare("SELECT timestamp, type, domain, client, status FROM queries WHERE timestamp >= :from AND timestamp <= :until ORDER BY timestamp ASC"); + $stmt->bindValue(":from", $from); + $stmt->bindValue(":until", $until); + $results = $stmt->execute(); if(!is_bool($results)) while ($row = $results->fetchArray()) { @@ -87,17 +90,20 @@ if (isset($_GET['topClients']) && $auth) $limit = ""; if(isset($_GET["from"]) && isset($_GET["until"])) { - $limit = "WHERE timestamp >= ".$_GET["from"]." AND timestamp <= ".$_GET["until"]; + $limit = "WHERE timestamp >= :from AND timestamp <= :until"; } elseif(isset($_GET["from"]) && !isset($_GET["until"])) { - $limit = "WHERE timestamp >= ".$_GET["from"]; + $limit = "WHERE timestamp >= :from"; } elseif(!isset($_GET["from"]) && isset($_GET["until"])) { - $limit = "WHERE timestamp <= ".$_GET["until"]; + $limit = "WHERE timestamp <= :until"; } - $results = $db->query('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 20'); + $stmt = $db->prepare('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 20'); + $stmt->bindValue(":from", $_GET['from']); + $stmt->bindValue(":until", $_GET['until']); + $results = $stmt->execute(); $clients = array(); @@ -134,17 +140,20 @@ if (isset($_GET['topDomains']) && $auth) if(isset($_GET["from"]) && isset($_GET["until"])) { - $limit = " AND timestamp >= ".$_GET["from"]." AND timestamp <= ".$_GET["until"]; + $limit = " AND timestamp >= :from AND timestamp <= :until"; } elseif(isset($_GET["from"]) && !isset($_GET["until"])) { - $limit = " AND timestamp >= ".$_GET["from"]; + $limit = " AND timestamp >= :from"; } elseif(!isset($_GET["from"]) && isset($_GET["until"])) { - $limit = " AND timestamp <= ".$_GET["until"]; + $limit = " AND timestamp <= :until"; } - $results = $db->query('SELECT domain,count(domain) FROM queries WHERE (STATUS == 2 OR STATUS == 3)'.$limit.' GROUP by domain order by count(domain) desc limit 20'); + $stmt = $db->prepare('SELECT domain,count(domain) FROM queries WHERE (STATUS == 2 OR STATUS == 3)'.$limit.' GROUP by domain order by count(domain) desc limit 20'); + $stmt->bindValue(":from", $_GET['from']); + $stmt->bindValue(":until", $_GET['until']); + $results = $stmt->execute(); $domains = array(); @@ -181,17 +190,20 @@ if (isset($_GET['topAds']) && $auth) if(isset($_GET["from"]) && isset($_GET["until"])) { - $limit = " AND timestamp >= ".$_GET["from"]." AND timestamp <= ".$_GET["until"]; + $limit = " AND timestamp >= :from AND timestamp <= :until"; } elseif(isset($_GET["from"]) && !isset($_GET["until"])) { - $limit = " AND timestamp >= ".$_GET["from"]; + $limit = " AND timestamp >= :from"; } elseif(!isset($_GET["from"]) && isset($_GET["until"])) { - $limit = " AND timestamp <= ".$_GET["until"]; + $limit = " AND timestamp <= :until"; } - $results = $db->query('SELECT domain,count(domain) FROM queries WHERE (STATUS == 1 OR STATUS == 4)'.$limit.' GROUP by domain order by count(domain) desc limit 10'); + $stmt = $db->prepare('SELECT domain,count(domain) FROM queries WHERE (STATUS == 1 OR STATUS == 4)'.$limit.' GROUP by domain order by count(domain) desc limit 10'); + $stmt->bindValue(":from", $_GET['from']); + $stmt->bindValue(":until", $_GET['until']); + $results = $stmt->execute(); $addomains = array(); @@ -253,15 +265,15 @@ if (isset($_GET['getGraphData']) && $auth) if(isset($_GET["from"]) && isset($_GET["until"])) { - $limit = " AND timestamp >= ".intval($_GET["from"])." AND timestamp <= ".intval($_GET["until"]); + $limit = " AND timestamp >= :from AND timestamp <= :until"; } elseif(isset($_GET["from"]) && !isset($_GET["until"])) { - $limit = " AND timestamp >= ".intval($_GET["from"]); + $limit = " AND timestamp >= :from"; } elseif(!isset($_GET["from"]) && isset($_GET["until"])) { - $limit = " AND timestamp <= ".intval($_GET["until"]); + $limit = " AND timestamp <= :until"; } $interval = 600; @@ -274,7 +286,11 @@ if (isset($_GET['getGraphData']) && $auth) } // Count permitted queries in intervals - $results = $db->query('SELECT (timestamp/'.$interval.')*'.$interval.' interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval'); + $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval'); + $stmt->bindValue(":from", intval($_GET['from'])); + $stmt->bindValue(":until", intval($_GET['until'])); + $stmt->bindValue(":interval", $interval); + $results = $stmt->execute(); $domains = array(); @@ -287,7 +303,11 @@ if (isset($_GET['getGraphData']) && $auth) $data = array_merge($data, $result); // Count blocked queries in intervals - $results = $db->query('SELECT (timestamp/'.$interval.')*'.$interval.' interval, COUNT(*) FROM queries WHERE (status == 1 OR status == 4 OR status == 5)'.$limit.' GROUP by interval ORDER by interval'); + $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status == 1 OR status == 4 OR status == 5)'.$limit.' GROUP by interval ORDER by interval'); + $stmt->bindValue(":from", intval($_GET['from'])); + $stmt->bindValue(":until", intval($_GET['until'])); + $stmt->bindValue(":interval", $interval); + $results = $stmt->execute(); $addomains = array(); From 862db2ba9ec4085674bfe4dff6b16147499b5d91 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Fri, 19 Jan 2018 17:52:06 -0500 Subject: [PATCH 38/41] Use hash_equals in password.php (and move it to funcs.php) Signed-off-by: Mcat12 --- scripts/pi-hole/php/auth.php | 20 -------------------- scripts/pi-hole/php/func.php | 20 ++++++++++++++++++++ scripts/pi-hole/php/password.php | 8 +++++--- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/scripts/pi-hole/php/auth.php b/scripts/pi-hole/php/auth.php index 7bebba29..5bfa6351 100644 --- a/scripts/pi-hole/php/auth.php +++ b/scripts/pi-hole/php/auth.php @@ -92,26 +92,6 @@ function check_csrf($token) { session_start(); } - // Credit: http://php.net/manual/en/function.hash-equals.php#119576 - if(!function_exists('hash_equals')) { - function hash_equals($known_string, $user_string) { - $ret = 0; - - if (strlen($known_string) !== strlen($user_string)) { - $user_string = $known_string; - $ret = 1; - } - - $res = $known_string ^ $user_string; - - for ($i = strlen($res) - 1; $i >= 0; --$i) { - $ret |= ord($res[$i]); - } - - return !$ret; - } - } - if(!isset($_SESSION['token']) || empty($token) || !hash_equals($_SESSION['token'], $token)) { log_and_die("Wrong token"); } diff --git a/scripts/pi-hole/php/func.php b/scripts/pi-hole/php/func.php index f3beaf9e..bc353218 100644 --- a/scripts/pi-hole/php/func.php +++ b/scripts/pi-hole/php/func.php @@ -25,4 +25,24 @@ function checkfile($filename) { } } +// Credit: http://php.net/manual/en/function.hash-equals.php#119576 +if(!function_exists('hash_equals')) { + function hash_equals($known_string, $user_string) { + $ret = 0; + + if (strlen($known_string) !== strlen($user_string)) { + $user_string = $known_string; + $ret = 1; + } + + $res = $known_string ^ $user_string; + + for ($i = strlen($res) - 1; $i >= 0; --$i) { + $ret |= ord($res[$i]); + } + + return !$ret; + } +} + ?> diff --git a/scripts/pi-hole/php/password.php b/scripts/pi-hole/php/password.php index 77ee2863..605640bc 100644 --- a/scripts/pi-hole/php/password.php +++ b/scripts/pi-hole/php/password.php @@ -6,6 +6,8 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ + require('func.php'); + // Start a new PHP session (or continue an existing one) session_start(); @@ -37,7 +39,7 @@ if(isset($_POST["pw"])) { $postinput = hash('sha256',hash('sha256',$_POST["pw"])); - if($postinput == $pwhash) + if(hash_equals($pwhash, $postinput)) { $_SESSION["hash"] = $pwhash; @@ -57,13 +59,13 @@ // Compare auth hash with saved hash else if (isset($_SESSION["hash"])) { - if($_SESSION["hash"] == $pwhash) + if(hash_equals($pwhash, $_SESSION["hash"])) $auth = true; } // API can use the hash to get data without logging in via plain-text password else if (isset($api) && isset($_GET["auth"])) { - if($_GET["auth"] == $pwhash) + if(hash_equals($pwhash, $_GET["auth"])) $auth = true; } else From 3f4421da4b07020b250ffa3b45d8f6e0f0603fc8 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sat, 20 Jan 2018 10:58:41 -0500 Subject: [PATCH 39/41] Use intval() and SQLITE3_INTEGER in api_db.php Signed-off-by: Mcat12 --- api_db.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/api_db.php b/api_db.php index 70d6e96d..21f1106d 100644 --- a/api_db.php +++ b/api_db.php @@ -71,8 +71,8 @@ if (isset($_GET['getAllQueries']) && $auth) $from = intval($_GET["from"]); $until = intval($_GET["until"]); $stmt = $db->prepare("SELECT timestamp, type, domain, client, status FROM queries WHERE timestamp >= :from AND timestamp <= :until ORDER BY timestamp ASC"); - $stmt->bindValue(":from", $from); - $stmt->bindValue(":until", $until); + $stmt->bindValue(":from", intval($from), SQLITE3_INTEGER); + $stmt->bindValue(":until", intval($until), SQLITE3_INTEGER); $results = $stmt->execute(); if(!is_bool($results)) while ($row = $results->fetchArray()) @@ -101,8 +101,8 @@ if (isset($_GET['topClients']) && $auth) $limit = "WHERE timestamp <= :until"; } $stmt = $db->prepare('SELECT client,count(client) FROM queries '.$limit.' GROUP by client order by count(client) desc limit 20'); - $stmt->bindValue(":from", $_GET['from']); - $stmt->bindValue(":until", $_GET['until']); + $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER); + $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER); $results = $stmt->execute(); $clients = array(); @@ -151,8 +151,8 @@ if (isset($_GET['topDomains']) && $auth) $limit = " AND timestamp <= :until"; } $stmt = $db->prepare('SELECT domain,count(domain) FROM queries WHERE (STATUS == 2 OR STATUS == 3)'.$limit.' GROUP by domain order by count(domain) desc limit 20'); - $stmt->bindValue(":from", $_GET['from']); - $stmt->bindValue(":until", $_GET['until']); + $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER); + $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER); $results = $stmt->execute(); $domains = array(); @@ -201,8 +201,8 @@ if (isset($_GET['topAds']) && $auth) $limit = " AND timestamp <= :until"; } $stmt = $db->prepare('SELECT domain,count(domain) FROM queries WHERE (STATUS == 1 OR STATUS == 4)'.$limit.' GROUP by domain order by count(domain) desc limit 10'); - $stmt->bindValue(":from", $_GET['from']); - $stmt->bindValue(":until", $_GET['until']); + $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER); + $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER); $results = $stmt->execute(); $addomains = array(); @@ -287,9 +287,9 @@ if (isset($_GET['getGraphData']) && $auth) // Count permitted queries in intervals $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status != 0 )'.$limit.' GROUP by interval ORDER by interval'); - $stmt->bindValue(":from", intval($_GET['from'])); - $stmt->bindValue(":until", intval($_GET['until'])); - $stmt->bindValue(":interval", $interval); + $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER); + $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER); + $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER); $results = $stmt->execute(); $domains = array(); @@ -304,9 +304,9 @@ if (isset($_GET['getGraphData']) && $auth) // Count blocked queries in intervals $stmt = $db->prepare('SELECT (timestamp/:interval)*:interval interval, COUNT(*) FROM queries WHERE (status == 1 OR status == 4 OR status == 5)'.$limit.' GROUP by interval ORDER by interval'); - $stmt->bindValue(":from", intval($_GET['from'])); - $stmt->bindValue(":until", intval($_GET['until'])); - $stmt->bindValue(":interval", $interval); + $stmt->bindValue(":from", intval($_GET['from']), SQLITE3_INTEGER); + $stmt->bindValue(":until", intval($_GET['until']), SQLITE3_INTEGER); + $stmt->bindValue(":interval", $interval, SQLITE3_INTEGER); $results = $stmt->execute(); $addomains = array(); From 289b62abf3213dfad5602586024e4ac87c96507b Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Sat, 20 Jan 2018 10:59:05 -0500 Subject: [PATCH 40/41] Fix header.php importing func.php twice Signed-off-by: Mcat12 --- scripts/pi-hole/php/auth.php | 2 +- scripts/pi-hole/php/password.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pi-hole/php/auth.php b/scripts/pi-hole/php/auth.php index 5bfa6351..0b32c732 100644 --- a/scripts/pi-hole/php/auth.php +++ b/scripts/pi-hole/php/auth.php @@ -6,7 +6,7 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ -require('func.php'); +require_once('func.php'); $ERRORLOG = getenv('PHP_ERROR_LOG'); if (empty($ERRORLOG)) { $ERRORLOG = '/var/log/lighttpd/error.log'; diff --git a/scripts/pi-hole/php/password.php b/scripts/pi-hole/php/password.php index 605640bc..ad8cbd08 100644 --- a/scripts/pi-hole/php/password.php +++ b/scripts/pi-hole/php/password.php @@ -6,7 +6,7 @@ * This file is copyright under the latest version of the EUPL. * Please see LICENSE file for your rights under this license. */ - require('func.php'); + require_once('func.php'); // Start a new PHP session (or continue an existing one) session_start(); From e3b4554a20d958f7f8e5c07ad581b245c4b8d57e Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sun, 28 Jan 2018 01:04:07 +0000 Subject: [PATCH 41/41] Requested change by @DL6ER Signed-off-by: Adam Warner --- settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.php b/settings.php index 3d030292..e319e252 100644 --- a/settings.php +++ b/settings.php @@ -812,7 +812,7 @@ if (in_array($_GET['tab'], array("sysadmin", "blocklists", "dns", "piholedhcp",

Validate DNS replies and cache DNSSEC data. When forwarding DNS queries, Pi-hole requests the DNSSEC records needed to validate - the replies. Use Google, Norton or DNS.WATCH DNS servers when activating + the replies. Use Google, Norton, DNS.WATCH or Quad9 DNS servers when activating DNSSEC. Note that the size of your log might increase significantly when enabling DNSSEC. A DNSSEC resolver test can be found here.