From 32f0456f218d4af4558a1c33c5d9e025818547a1 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Mon, 10 Oct 2016 14:22:31 +0200 Subject: [PATCH 01/13] Fix TXT-record quoting --- zones.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/zones.php b/zones.php index b3618a0..90c58ed 100644 --- a/zones.php +++ b/zones.php @@ -387,6 +387,14 @@ case "createrecord": jtable_respond(null, 'error', "Please only use ASCII-characters in your fields"); } + if ($type === 'TXT') { + # empty TXT records are ok, otherwise require surrounding quotes: "..." + if (strlen($content) == 1 || substr($content, 0, 1) !== '"' || substr($content, -1) !== '"') { + # fix quoting: first escape all \, then all ", then surround with quotes. + $content = '"'.str_replace('"', '\\"', str_replace('\\', '\\\\', $content)).'"'; + } + } + $record = $zone->addRecord($name, $type, $content, $_POST['disabled'], $_POST['ttl'], $_POST['setptr']); $api->savezone($zone->export()); From 83e8a0eda67ac3347664d8b7f63e6f31b1e964c3 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Fri, 14 Oct 2016 14:14:17 +0200 Subject: [PATCH 02/13] TRAILING DOTSS!!!11eleven!!11!&$W*&@*@!@#& --- zones.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zones.php b/zones.php index 90c58ed..5f2b9b4 100644 --- a/zones.php +++ b/zones.php @@ -319,7 +319,7 @@ case "create": $api->savezone($zone->export()); foreach ($template['records'] as $record) { - $zone->addRecord($record['name'], $record['type'], $record['content']); + $zone->addRecord($record['name'].$zonename, $record['type'], $record['content']); } break; @@ -369,7 +369,6 @@ case "createrecord": $name = $zone->name; } elseif (string_ends_with($name, '.')) { # "absolute" name, shouldn't append zone[name] - but check. - $name = substr($name, 0, -1); if (!string_ends_with($name, $zone->name)) { jtable_respond(null, 'error', "Name $name not in zone ".$zone->name); } From b5d7fa818352d38210787f095debb381221819a3 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Fri, 14 Oct 2016 14:16:48 +0200 Subject: [PATCH 03/13] Don't forget the dot in between --- zones.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zones.php b/zones.php index 5f2b9b4..7b4849d 100644 --- a/zones.php +++ b/zones.php @@ -319,7 +319,7 @@ case "create": $api->savezone($zone->export()); foreach ($template['records'] as $record) { - $zone->addRecord($record['name'].$zonename, $record['type'], $record['content']); + $zone->addRecord(join(Array($record['name'],'.',$zonename)), $record['type'], $record['content']); } break; From 92ac4576ab9f6ebba43f6abf968e494948d6dd30 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Fri, 14 Oct 2016 14:20:07 +0200 Subject: [PATCH 04/13] An empty name is possible --- zones.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zones.php b/zones.php index 7b4849d..161ac18 100644 --- a/zones.php +++ b/zones.php @@ -319,7 +319,8 @@ case "create": $api->savezone($zone->export()); foreach ($template['records'] as $record) { - $zone->addRecord(join(Array($record['name'],'.',$zonename)), $record['type'], $record['content']); + $name = $record['name'] != '' ? join(Array($record['name'],'.',$zonename)) : $zonename; + $zone->addRecord($name, $record['type'], $record['content']); } break; From 77192d84b1ec16660feafd3b73f9fe0704bdbc09 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Wed, 19 Oct 2016 17:28:16 +0200 Subject: [PATCH 05/13] Don't close the database connection and make it global. Also, honour the account that is set in pdns, unless its empty --- includes/misc.inc.php | 17 +++++++---------- zones.php | 7 +++---- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/includes/misc.inc.php b/includes/misc.inc.php index a818cb2..e56b55d 100644 --- a/includes/misc.inc.php +++ b/includes/misc.inc.php @@ -85,10 +85,12 @@ function string_ends_with($string, $suffix) } function get_db() { - global $authdb; + global $authdb, $db; - $db = new SQLite3($authdb, SQLITE3_OPEN_READWRITE); - $db->exec('PRAGMA foreign_keys = 1'); + if (!isset($db)) { + $db = new SQLite3($authdb, SQLITE3_OPEN_READWRITE); + $db->exec('PRAGMA foreign_keys = 1'); + } return $db; } @@ -110,7 +112,6 @@ function get_user_info($u) { $q->bindValue(1, $u); $result = $q->execute(); $userinfo = $result->fetchArray(SQLITE3_ASSOC); - $db->close(); return $userinfo; } @@ -125,7 +126,6 @@ function do_db_auth($u, $p) { $q->bindValue(1, $u); $result = $q->execute(); $userinfo = $result->fetchArray(SQLITE3_ASSOC); - $db->close(); if ($userinfo and $userinfo['password'] and (crypt($p, $userinfo['password']) === $userinfo['password'])) { return TRUE; @@ -149,7 +149,6 @@ function add_user($username, $isadmin = FALSE, $password = '') { $q->bindValue(2, $password, SQLITE3_TEXT); $q->bindValue(3, (int)(bool) $isadmin, SQLITE3_INTEGER); $ret = $q->execute(); - $db->close(); if ($isadmin) { writelog("Added user $username as admin."); @@ -187,7 +186,6 @@ function update_user($id, $isadmin, $password) { writelog("Updating settings for $username. Admin: ".(int)(bool)$isadmin); } $ret = $q->execute(); - $db->close(); return $ret; } @@ -205,7 +203,6 @@ function delete_user($id) { $q = $db->prepare('DELETE FROM users WHERE id = ?'); $q->bindValue(1, $id, SQLITE3_INTEGER); $ret = $q->execute(); - $db->close(); writelog("Deleted user " . $userinfo['emailaddress'] . "."); return $ret; @@ -241,6 +238,8 @@ function jtable_respond($records, $method = 'multiple', $msg = 'Undefined errorm $jTableResult['RecordCount'] = count($records); } + $db = get_db(); + $db->close(); header('Content-Type: application/json'); print json_encode($jTableResult); exit(0); @@ -290,7 +289,6 @@ function clearlogs() { $db = get_db(); $q = $db->query('DELETE FROM logs;'); - $db->close(); writelog("Logtable truncated."); } @@ -368,7 +366,6 @@ function writelog($line, $user=False) { $q->bindValue(':user', $user, SQLITE3_TEXT); $q->bindValue(':log', $line, SQLITE3_TEXT); $q->execute(); - $db->close(); } catch (Exception $e) { return jtable_respond(null, 'error', $e->getMessage()); } diff --git a/zones.php b/zones.php index 161ac18..50e255e 100644 --- a/zones.php +++ b/zones.php @@ -112,7 +112,6 @@ function add_db_zone($zonename, $accountname) { $q->bindValue(1, $zonename, SQLITE3_TEXT); $q->bindValue(2, $accountname, SQLITE3_TEXT); $q->execute(); - $db->close(); } function delete_db_zone($zonename) { @@ -123,7 +122,6 @@ function delete_db_zone($zonename) { $q = $db->prepare("DELETE FROM zones WHERE zone = ?"); $q->bindValue(1, $zonename, SQLITE3_TEXT); $q->execute(); - $db->close(); } function get_zone_account($zonename, $default) { @@ -135,7 +133,6 @@ function get_zone_account($zonename, $default) { $q->bindValue(1, $zonename, SQLITE3_TEXT); $result = $q->execute(); $zoneinfo = $result->fetchArray(SQLITE3_ASSOC); - $db->close(); if (isset($zoneinfo['emailaddress']) && $zoneinfo['emailaddress'] != null ) { return $zoneinfo['emailaddress']; } @@ -165,7 +162,9 @@ case "listslaves": foreach ($api->listzones($q) as $sresult) { $zone = new Zone(); $zone->parse($sresult); - $zone->setAccount(get_zone_account($zone->name, 'admin')); + if ($zone->account == '') { + $zone->setAccount(get_zone_account($zone->name, 'admin')); + } if (!check_account($zone)) continue; From 94e0d22bf2fd8f2e23d7627f30048c8ac02bf074 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Tue, 25 Oct 2016 11:10:22 +0200 Subject: [PATCH 06/13] If we don't have a soa_edit_api for this zone yet, set it to our default --- includes/class/Zone.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class/Zone.php b/includes/class/Zone.php index ffc5588..c759dee 100644 --- a/includes/class/Zone.php +++ b/includes/class/Zone.php @@ -182,7 +182,7 @@ class Zone { $ret['kind'] = $this->kind; $ret['name'] = $this->name; $ret['soa_edit'] = $this->soa_edit; - $ret['soa_edit_api'] = $this->soa_edit_api; + $ret['soa_edit_api'] = ($this->soa_edit_api == "") ? $defaults['soa_edit_api'] : $this->soa_edit_api; if ($this->zone) { $ret['zone'] = $this->zone; return $ret; From 41801a73f6cafdbfa3e59ffe24648b03c3653554 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Tue, 25 Oct 2016 12:14:07 +0200 Subject: [PATCH 07/13] Try to set soa_edit_api, if it is not yet set --- includes/class/Zone.php | 21 +++++++++++++++------ zones.php | 12 +++++++++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/includes/class/Zone.php b/includes/class/Zone.php index c759dee..a429550 100644 --- a/includes/class/Zone.php +++ b/includes/class/Zone.php @@ -26,10 +26,10 @@ class Zone { $this->setAccount($data['account']); $this->setSerial($data['serial']); $this->url = $data['url']; - if (isset($data['soa_edit'])) + if (isset($data['soa_edit']) && $data['soa_edit'] != "") $this->setSoaEdit($data['soa_edit']); - if (isset($data['soa_edit_api'])) - $this->setSoaEditApi($data['soa_edit_api']); + if (isset($data['soa_edit_api']) && $data['soa_edit_api'] != "") + $this->setSoaEditApi($data['soa_edit_api'], True); foreach ($data['masters'] as $master) { $this->addMaster($master); @@ -76,7 +76,12 @@ class Zone { $this->soa_edit = $soaedit; } - public function setSoaEditApi($soaeditapi) { + public function setSoaEditApi($soaeditapi, $overwrite=False) { + if (isset($this->soa_edit_api) and $this->soa_edit_api != "") { + if ($overwrite === False) { + return False; + } + } $this->soa_edit_api = $soaeditapi; } public function setName($name) { @@ -181,8 +186,12 @@ class Zone { $ret['nameservers'] = $this->nameservers; $ret['kind'] = $this->kind; $ret['name'] = $this->name; - $ret['soa_edit'] = $this->soa_edit; - $ret['soa_edit_api'] = ($this->soa_edit_api == "") ? $defaults['soa_edit_api'] : $this->soa_edit_api; + if (isset($this->soa_edit) && $this->soa_edit != "") { + $ret['soa_edit'] = $this->soa_edit; + } + if (isset($this->soa_edit_api) && $this->soa_edit_api != "") { + $ret['soa_edit_api'] = $this->soa_edit_api; + } if ($this->zone) { $ret['zone'] = $this->zone; return $ret; diff --git a/zones.php b/zones.php index 50e255e..21e060b 100644 --- a/zones.php +++ b/zones.php @@ -272,7 +272,7 @@ case "create": $zone->importData($_POST['zone']); } if (isset($defaults['soa_edit_api'])) { - $zone->setSoaEditApi($defaults['soa_edit_api']); + $zone->setSoaEditApi($defaults['soa_edit_api'], True); } if (isset($defaults['soa_edit'])) { $zone->setSoaEdit($defaults['soa_edit']); @@ -334,6 +334,8 @@ case "create": case "update": $zone = new Zone(); $zone->parse($api->loadzone($_POST['id'])); + if ($zone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$zone->name); $zoneaccount = isset($_POST['account']) ? $_POST['account'] : $zone->account; if ($zone->account !== $zoneaccount) { @@ -360,6 +362,8 @@ case "update": case "createrecord": $zone = new Zone(); $zone->parse($api->loadzone($_GET['zoneid'])); + if ($zone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$zone->name); $name = isset($_POST['name']) ? $_POST['name'] : ''; $type = $_POST['type']; @@ -404,6 +408,8 @@ case "createrecord": case "editrecord": $zone = new Zone(); $zone->parse($api->loadzone($_GET['zoneid'])); + if ($zone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$zone->name); $old_record = decode_record_id(isset($_POST['id']) ? $_POST['id'] : ''); @@ -421,6 +427,8 @@ case "editrecord": case "deleterecord": $zone = new Zone(); $zone->parse($api->loadzone($_GET['zoneid'])); + if ($zone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$zone->name); $old_record = decode_record_id(isset($_POST['id']) ? $_POST['id'] : ''); $rrset = $zone->getRRSet($old_record['name'], $old_record['type']); @@ -451,6 +459,8 @@ case "clone": $srczone = new Zone(); $srczone->parse($api->loadzone($src)); + if ($srczone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$srczone->name); $srczone->setId(''); $srczone->setName($name); From 42b247d5c0d59cd3e7b0204dfc7d694b4c3db9b1 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Thu, 3 Nov 2016 10:11:24 +0100 Subject: [PATCH 08/13] Add missing types. Closes #130 --- index.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.php b/index.php index 8c764f4..d0649f3 100644 --- a/index.php +++ b/index.php @@ -616,6 +616,8 @@ $(document).ready(function () { 'SRV': 'SRV', 'SSHFP': 'SSHFP', 'TLSA': 'TLSA', + 'DNAME': 'DNAME', + 'DS': 'DS' }; } return { @@ -623,6 +625,8 @@ $(document).ready(function () { 'AAAA': 'AAAA', 'CERT': 'CERT', 'CNAME': 'CNAME', + 'DNAME': 'DNAME', + 'DS': 'DS', 'LOC': 'LOC', 'MX': 'MX', 'NAPTR': 'NAPTR', From ae00aa8ed9fafdd7c144ebcc0267134239f81796 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Fri, 18 Nov 2016 17:00:18 +0100 Subject: [PATCH 09/13] Fix quoting of TXT and SPF records --- zones.php | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/zones.php b/zones.php index 21e060b..2a86a37 100644 --- a/zones.php +++ b/zones.php @@ -12,10 +12,12 @@ if (!is_csrf_safe()) { jtable_respond(null, 'error', "Authentication required"); } + +$quoteus = array('TXT', 'SPF'); + /* This function is taken from: http://pageconfig.com/post/how-to-validate-ascii-text-in-php and got fixed by #powerdns */ - function is_ascii($string) { return ( bool ) ! preg_match( '/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x80-\\xff]/' , $string ); } @@ -140,6 +142,16 @@ function get_zone_account($zonename, $default) { return $default; } +function quote_content($content) { + # empty TXT records are ok, otherwise require surrounding quotes: "..." + if (strlen($content) == 1 || substr($content, 0, 1) !== '"' || substr($content, -1) !== '"') { + # fix quoting: first escape all \, then all ", then surround with quotes. + $content = '"'.str_replace('"', '\\"', str_replace('\\', '\\\\', $content)).'"'; + } + + return $content; +} + function check_account($zone) { return is_adminuser() or ($zone->account === get_sess_user()); } @@ -390,12 +402,8 @@ case "createrecord": jtable_respond(null, 'error', "Please only use ASCII-characters in your fields"); } - if ($type === 'TXT') { - # empty TXT records are ok, otherwise require surrounding quotes: "..." - if (strlen($content) == 1 || substr($content, 0, 1) !== '"' || substr($content, -1) !== '"') { - # fix quoting: first escape all \, then all ", then surround with quotes. - $content = '"'.str_replace('"', '\\"', str_replace('\\', '\\\\', $content)).'"'; - } + if (array_search($type, $quoteus) !== FALSE) { + $content = quote_content($content); } $record = $zone->addRecord($name, $type, $content, $_POST['disabled'], $_POST['ttl'], $_POST['setptr']); @@ -415,11 +423,17 @@ case "editrecord": $rrset = $zone->getRRSet($old_record['name'], $old_record['type']); $rrset->deleteRecord($old_record['content']); - $zone->addRecord($_POST['name'], $_POST['type'], $_POST['content'], $_POST['disabled'], $_POST['ttl'], $_POST['setptr']); + + $content = $_POST['content']; + if (array_search($type, $quoteus) !== FALSE) { + $content = quote_content($content); + } + + $zone->addRecord($_POST['name'], $_POST['type'], $content, $_POST['disabled'], $_POST['ttl'], $_POST['setptr']); $api->savezone($zone->export()); - $record = $zone->getRecord($_POST['name'], $_POST['type'], $_POST['content']); + $record = $zone->getRecord($_POST['name'], $_POST['type'], $content); writelog("Updated record ".$_POST['id']." to ".$record['id']); jtable_respond($record, 'single'); break; From 6737aa9b83f7c1e3a5d35680732c07e42c62f026 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Fri, 18 Nov 2016 17:01:48 +0100 Subject: [PATCH 10/13] Fix matching on zonename, we were missing the . --- zones.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zones.php b/zones.php index 2a86a37..055db9e 100644 --- a/zones.php +++ b/zones.php @@ -388,7 +388,7 @@ case "createrecord": if (!string_ends_with($name, $zone->name)) { jtable_respond(null, 'error', "Name $name not in zone ".$zone->name); } - } else if (!string_ends_with($name, $zone->name)) { + } else if (!string_ends_with($name.'.', $zone->name)) { $name = $name . '.' . $zone->name; } From 5c5f9f7abd88ab29b60dd3202c3fe74681ada890 Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Fri, 18 Nov 2016 17:07:49 +0100 Subject: [PATCH 11/13] Fix sorting --- zones.php | 1 + 1 file changed, 1 insertion(+) diff --git a/zones.php b/zones.php index 055db9e..dec5a12 100644 --- a/zones.php +++ b/zones.php @@ -527,6 +527,7 @@ case "getformnameservers": break; case "formzonelist": $zones = $api->listzones(); + usort($zones, "zone_compare"); $ret = array(); foreach ($zones as $zone) { if ($zone['kind'] == 'Slave') From 93c88cc1966bee1c528a867e4517a101462d469e Mon Sep 17 00:00:00 2001 From: Mark Schouten Date: Fri, 18 Nov 2016 17:11:22 +0100 Subject: [PATCH 12/13] If we get here, there is a value without dots... So add it --- zones.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zones.php b/zones.php index dec5a12..45f650d 100644 --- a/zones.php +++ b/zones.php @@ -390,6 +390,8 @@ case "createrecord": } } else if (!string_ends_with($name.'.', $zone->name)) { $name = $name . '.' . $zone->name; + } else { + $name = $name.'.'; } if (!_valid_label($name)) { From a3affccacd38865f346bee563f1455f09132d2b9 Mon Sep 17 00:00:00 2001 From: Krombel Date: Sat, 19 Nov 2016 02:50:09 +0100 Subject: [PATCH 13/13] fix switching of Views for non-admin-users (#135) --- index.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/index.php b/index.php index d0649f3..ea7e841 100644 --- a/index.php +++ b/index.php @@ -1177,6 +1177,18 @@ $(document).ready(function () { entry: $('#searchlogs-entry').val() }); }); + + $('#AboutMe').hide(); + $('#aboutme').click(function () { + $('#MasterZones').hide(); + $('#SlaveZones').hide(); + $('#AboutMe').show(); + }); + $('#zoneadmin').click(function () { + $('#AboutMe').hide(); + $('#MasterZones').show(); + $('#SlaveZones').show(); + }); $('#MasterZones').jtable('load');