From 9a44b33eb13624f957c2859b3cb826fa4196b34a Mon Sep 17 00:00:00 2001 From: "David P. Discher" Date: Fri, 20 Apr 2018 19:18:31 +0000 Subject: [PATCH 1/7] BIND-DLZ w/ v6 and INET function compatibility, see docs/DPD-DLZ-INET-Chanages --- docs/DPD-DLZ-INET-Chanages.md | 34 ++++++ inet-functions.php | 142 ++++++++++++++++++++++++++ inet-functions.sql | 4 + install/inet-functions.php | 132 ++++++++++++++++++++++++ install/inet-functions.sql | 4 + www/config/config.inc.php | 31 +++--- www/include/functions_db.inc.php | 5 +- www/include/functions_general.inc.php | 15 ++- www/include/functions_gui.inc.php | 2 +- www/include/functions_inet_format.php | 17 +++ www/modules/ona/dns_record.inc.php | 31 ++++-- www/modules/ona/domain.inc.php | 28 +++++ www/modules/ona/interface.inc.php | 7 +- www/winc/list_records.inc.php | 2 + 14 files changed, 427 insertions(+), 27 deletions(-) create mode 100644 docs/DPD-DLZ-INET-Chanages.md create mode 100644 inet-functions.php create mode 100644 inet-functions.sql create mode 100644 install/inet-functions.php create mode 100644 install/inet-functions.sql create mode 100644 www/include/functions_inet_format.php diff --git a/docs/DPD-DLZ-INET-Chanages.md b/docs/DPD-DLZ-INET-Chanages.md new file mode 100644 index 00000000..12e20d95 --- /dev/null +++ b/docs/DPD-DLZ-INET-Chanages.md @@ -0,0 +1,34 @@ +OpenNetAdmin - dpd's BIND-DLZ w/ v6 and INET function compatibility +============ + +ONA allowed for BIND-DLZ extension to perform dynamic lookups via your +ONA MySQL database. However, this didn't support PTR (very well) or V6 +and required a really convoluted view that made it very difficult to fix +the v6 et al issues that arrose. + +So, I have design a very small delta patch, that should allow for v6 and +and both v4 and v6 PTR, NS, MX and SOA records to be severed correctly, +with a horrible long, but easier to use query. + +The PHP code is changes, but two install scripts need to be run manually. + +--- +**Changes** + + * `install/inet-functions.sql` + Very minimal schema changes, just adding one column to interfaces, for the VARBINARY(16), so the the inet6_atoi/inet6_ntoi and php's inet_pton/inet_ntop can be used. Also adds three indexes for fields that DLZ uses to search by. + * `install/inet-functions.php` base script copied from 2-to-3.php. This will do a few things + * Finds/Creates all domains and creates a meta "SOA" type row in the DNS table. Because of how DLZ queries (without a "type", just the string of lookup) - it is much easier to have this via one table, and use cases in the sql to change up the data formating. So a fake SOA record is here, pretty much just linking the domain ID and type together. All other fields are ignored. Doesn't break backwards compat, ONA seems to ignore the SOA type. Code changes provides the creation of SOAs upon domain creation. + * Updates the dns.name of all PTR records. Again, how Bind DLZ does queries, there was no good way to do reverse lookups. ONA already ignored the dns.name field, for v4 PTRs, so, in this case overloading dns.name with the last two octets. Again, a strange things with BIND-DLZ ... is it will not lookup the first octet + in-arpa for the domain name ($zone$, ex 10.in-addr.arpa, but it will search 2.10.in-addr.arpa ) and DLZ will only successfully search the first octet of .ip6.arpa), with the $record$ slowly building out in reverse octets. + * add in all two-octet in-addr.arpa domains, as encounter by IP. Because of the above, will auto create all the needed in-addr.arpa for v4. Should also handle v6 as well. + * Populate the ip_addr_inet field. Will scan all interfaces, and update the IP address for both v4 and v6. ip_addr_inet is not used by ONA, other than to updated durning edit or insert (code changes provided). + +**Notable Code Changes** + * Fixed undefined PHP warnings using isset() checks, especially running in CLI. It was hard to see my own debugging output. By far, not extensive fixes, but proper PHP syntax/usage/style. + * Allow AAAA to be AAAA. Removed a few stops where v6 quad-a records are remapped to A. Was required for some reason. + * random PHP 7.x fix. (functions_gui.inc.php) (Testing & developed using PHP 7.2.3 on FreeBSD, w/ file based sessions) + * modules/ona/domain.inc.php - adds the SOA dns record. + * modules/ona/interface.inc.php - populates and updates `ip_addr_inet` base on ip_addr & ip_mangle() + * modules/ona/dns_record.inc.php - various tweaks for v6, as well as setting dns.name for PTR records. + + diff --git a/inet-functions.php b/inet-functions.php new file mode 100644 index 00000000..aa6240ee --- /dev/null +++ b/inet-functions.php @@ -0,0 +1,142 @@ + Couldn't find include folder {$include}!\n"; exit; } +require_once($base . '/config/config.inc.php'); +/* --------------------------------------------------------- */ + +global $conf, $self, $onadb; + +// Uncomment the following to get a ton o' debug +//$conf['debug'] = 6; +echo "Checking for SOA meta records:\n"; + +list($status, $rows, $domains) = db_get_records($onadb, 'domains', 'id > 0'); +#print_r ( $domains ); +foreach ( $domains as $d ) { + list($status, $rows, $soa) = db_get_records($onadb, 'dns', "type = 'SOA' and domain_id = '" . $d['id'] . "' "); + if ( $rows == 0 ) { + printf ("{%36s} - doesn't have an SOA DNS Record. \n", $d['name'] ); + // Add the dns record + $dns_id = ona_get_next_id('dns'); + list($status, $rows) = db_insert_record( + $onadb, + 'dns', + array( + 'id' => $dns_id, + 'domain_id' => $d['id'], + 'interface_id' => 0, + 'dns_id' => 0, + 'type' => 'SOA', + 'ttl' => 0, + 'name' => '', + 'mx_preference' => '0', + 'txt' => '', + 'srv_pri' => 0, + 'srv_weight' => 0, + 'srv_port' => 0, + 'notes' => '', + 'dns_view_id' => 0 + ) + ); + if ($status or !$rows) { + printf ("{%36s} - SOA DNS Record insert FAILED. \n", $d['name'] ); + } else { + printf ("{%36s} - SOA DNS Record created. \n", $d['name'] ); + } + + } else { + printf ("{%36s} - has an SOA DNS Record. \n", $d['name'] ); + } +} + +// Get the PTR records that dont have a domain_id +list($status, $rows, $ptrs) = db_get_records($onadb, 'dns', "type = 'PTR'", ''); +echo "Found {$rows} PTR with ptr records - will update all of them\n"; + +foreach ($ptrs as $ptr) { + list($status, $rows, $interface) = ona_get_interface_record(array('id' => $ptr['interface_id'])); + + // Print an error if it doesnt find an IP + if (!$interface['ip_addr']) { + echo "Possible orphan PTR record in dns table at ID: {$ptr['id']}. You should delete this record manually.\n"; + continue; + } + + $ipflip = ip_mangle($interface['ip_addr'],'flip'); + $octets = explode(".",$ipflip); + if (count($octets) > 4) { + $arpa = 'ip6.arpa'; + $octcount = 31; + #$domain = $arpa; + $a = array (); + for ($i=$octcount; $i>$octcount-11; $i--) { + array_push ($a, $octets[$i]); + } + array_push ($a, $arap ); + $domain = implode (".", $a); + $_name = ''; + $a = array (); + for ($i=$octcount-11; $i>=0; $i--) { + array_push ($a, $octets[$i]); + } + $_name = implode (".", $a); + } else { + $arpa = 'in-addr.arpa'; + $octcount = 3; + $domain = $octets[2] . "." . $octets[3] . "." . $arpa; + $_name = $octets[0] . "." . $octets[1]; + } + // Find a pointer zone for this record to associate with. + echo " Searching for $domain \n"; + list($status, $prows, $ptrdomain) = ona_find_domain($domain); + echo " => Found for $domain => " . $ptrdomain['id'] . " " . $ptrdomain['name'] ."\n" ; + + // print_r ( $ptrdomain ); + // CRAPPY security cludge + $_SESSION['ona']['auth']['user']['username'] = 'PTRFIX'; + $_SESSION['ona']['auth']['perms']['advanced'] = 'Y'; + $_SESSION['ona']['auth']['perms']['host_modify'] = 'Y'; + + if (!$ptrdomain['id'] or ($domain != $ptrdomain['name']) ) { + echo " {$interface['ip_addr_text']}: Unable to find a pointer domain for this IP! Creating the following DNS domain: {$domain} \n"; + list($status, $output) = run_module('domain_add', array('name' => $domain)); + if ($status) { + echo "ERROR => {$output}\n"; + exit($status); + } + list($status, $rows, $ptrdomain) = ona_find_domain($domain); + } + + // Found a domain to put them in. + echo " Updating PTR for IP {$interface['ip_addr_text']} to $ipflip.in-addr.arpa\n"; + + // Change the actual DNS record + list($status, $rows) = db_update_record($onadb, 'dns', array('id' => $ptr['id']), array( 'name' => $_name, 'domain_id' => $ptrdomain['id'] )); + // if ($status or !$rows) { + // echo "ERROR => SQL Query failed updating dns record: " . $self['error'] . " $status \n" ; + // exit(2); + // } + + +} + +list($status, $rows, $interfaces) = db_get_records($onadb, 'interfaces', "ip_addr is not null", ''); +foreach ($interfaces as $interface ) { + echo " Adding inet6_atoi field " . $interface['id'] . "\n"; + list($status, $rows) = db_update_record($onadb, 'interfaces', array('id' => $interface['id']), array ('ip_addr_inet' => inet_format($interface['ip_addr']) )); + +} + +exit(0); + +?> diff --git a/inet-functions.sql b/inet-functions.sql new file mode 100644 index 00000000..a5a2e13b --- /dev/null +++ b/inet-functions.sql @@ -0,0 +1,4 @@ +alter table interfaces add `ip_addr_inet` varbinary(16) default NULL; +CREATE INDEX domains_name_index ON domains (name); +CREATE INDEX dns_name_index ON dns (name); +CREATE INDEX type_index ON dns (type); diff --git a/install/inet-functions.php b/install/inet-functions.php new file mode 100644 index 00000000..17fd2f33 --- /dev/null +++ b/install/inet-functions.php @@ -0,0 +1,132 @@ + Couldn't find include folder {$include}!\n"; exit; } +require_once($base . '/config/config.inc.php'); +/* --------------------------------------------------------- */ + +global $conf, $self, $onadb; + +// Uncomment the following to get a ton o' debug +//$conf['debug'] = 6; +echo "Checking for SOA meta records:\n"; + +list($status, $rows, $domains) = db_get_records($onadb, 'domains', 'id > 0'); +#print_r ( $domains ); +foreach ( $domains as $d ) { + list($status, $rows, $soa) = db_get_records($onadb, 'dns', "type = 'SOA' and domain_id = '" . $d['id'] . "' "); + if ( $rows == 0 ) { + printf ("{%36s} - doesn't have an SOA DNS Record. \n", $d['name'] ); + // Add the dns record + $dns_id = ona_get_next_id('dns'); + list($status, $rows) = db_insert_record( + $onadb, + 'dns', + array( + 'id' => $dns_id, + 'domain_id' => $d['id'], + 'interface_id' => 0, + 'dns_id' => 0, + 'type' => 'SOA', + 'ttl' => 0, + 'name' => '', + 'mx_preference' => '0', + 'txt' => '', + 'srv_pri' => 0, + 'srv_weight' => 0, + 'srv_port' => 0, + 'notes' => '', + 'dns_view_id' => 0 + ) + ); + if ($status or !$rows) { + printf ("{%36s} - SOA DNS Record insert FAILED. \n", $d['name'] ); + } else { + printf ("{%36s} - SOA DNS Record created. \n", $d['name'] ); + } + + } else { + printf ("{%36s} - has an SOA DNS Record. \n", $d['name'] ); + } +} + +// Get the PTR records that dont have a domain_id +list($status, $rows, $ptrs) = db_get_records($onadb, 'dns', "type = 'PTR'", ''); +echo "Found {$rows} PTR with ptr records - will update all of them\n"; + +foreach ($ptrs as $ptr) { + list($status, $rows, $interface) = ona_get_interface_record(array('id' => $ptr['interface_id'])); + + // Print an error if it doesnt find an IP + if (!$interface['ip_addr']) { + echo "Possible orphan PTR record in dns table at ID: {$ptr['id']}. You should delete this record manually.\n"; + continue; + } + + $ipflip = ip_mangle($interface['ip_addr'],'flip'); + $octets = explode(".",$ipflip); + if (count($octets) > 4) { + $arpa = 'ip6.arpa'; + $octcount = 31; + $a = array_reverse ( $octets ) + $domain = implode (".", $a); + $_name = ''; + $domain = implode (".", array ($a[0], $arpa) ); + } else { + $arpa = 'in-addr.arpa'; + $octcount = 3; + $domain = $octets[2] . "." . $octets[3] . "." . $arpa; + $_name = $octets[0] . "." . $octets[1]; + } + // Find a pointer zone for this record to associate with. + echo " Searching for $domain \n"; + list($status, $prows, $ptrdomain) = ona_find_domain($domain); + echo " => Found for $domain => " . $ptrdomain['id'] . " " . $ptrdomain['name'] ."\n" ; + + // CRAPPY security cludge + $_SESSION['ona']['auth']['user']['username'] = 'PTRFIX'; + $_SESSION['ona']['auth']['perms']['advanced'] = 'Y'; + $_SESSION['ona']['auth']['perms']['host_modify'] = 'Y'; + + if (!$ptrdomain['id'] or ($domain != $ptrdomain['name']) ) { + echo " {$interface['ip_addr_text']}: Unable to find a pointer domain for this IP! Creating the following DNS domain: {$domain} \n"; + list($status, $output) = run_module('domain_add', array('name' => $domain)); + if ($status) { + echo "ERROR => {$output}\n"; + exit($status); + } + list($status, $rows, $ptrdomain) = ona_find_domain($domain); + } + + // Found a domain to put them in. + echo " Updating PTR for IP {$interface['ip_addr_text']} to $ipflip.in-addr.arpa\n"; + + // Change the actual DNS record + list($status, $rows) = db_update_record($onadb, 'dns', array('id' => $ptr['id']), array( 'name' => $_name, 'domain_id' => $ptrdomain['id'] )); + // if ($status or !$rows) { + // echo "ERROR => SQL Query failed updating dns record: " . $self['error'] . " $status \n" ; + // exit(2); + // } + + +} + +list($status, $rows, $interfaces) = db_get_records($onadb, 'interfaces', "ip_addr is not null", ''); +foreach ($interfaces as $interface ) { + echo " Adding inet6_atoi field " . $interface['id'] . "\n"; + list($status, $rows) = db_update_record($onadb, 'interfaces', array('id' => $interface['id']), array ('ip_addr_inet' => inet_format($interface['ip_addr']) )); + +} + +exit(0); + +?> diff --git a/install/inet-functions.sql b/install/inet-functions.sql new file mode 100644 index 00000000..a5a2e13b --- /dev/null +++ b/install/inet-functions.sql @@ -0,0 +1,4 @@ +alter table interfaces add `ip_addr_inet` varbinary(16) default NULL; +CREATE INDEX domains_name_index ON domains (name); +CREATE INDEX dns_name_index ON dns (name); +CREATE INDEX type_index ON dns (type); diff --git a/www/config/config.inc.php b/www/config/config.inc.php index 47be897a..1c558ff1 100644 --- a/www/config/config.inc.php +++ b/www/config/config.inc.php @@ -30,9 +30,9 @@ // Get any query info -parse_str($_SERVER['QUERY_STRING']); - - +if ( isset($_SERVER['QUERY_STRING']) ) { + parse_str($_SERVER['QUERY_STRING']); +} // Many of these settings serve as defaults. They can be overridden by the settings in // the table "sys_config" @@ -58,6 +58,7 @@ "inc_functions_gui" => "$include/functions_gui.inc.php", "inc_functions_db" => "$include/functions_db.inc.php", "inc_functions_auth" => "$include/functions_auth.inc.php", + "inc_functions_inetformat" => "$include/functions_inet_format.php", "inc_db_sessions" => "$include/adodb_sessions.inc.php", "inc_adodb" => "$include/adodb/adodb.inc.php", "inc_adodb_xml" => "$include/adodb/adodb-xmlschema03.inc.php", @@ -69,7 +70,7 @@ "plugin_dir" => "$base/local/plugins", /* Defaults for some user definable options normally in sys_config table */ - "debug" => "2", + "debug" => "16", "syslog" => "0", "stdout" => "0", "log_to_db" => "0", @@ -105,7 +106,7 @@ ); // If the server port is 443 then this is a secure page // This is basically used to put a padlock icon on secure pages. -if ($_SERVER['SERVER_PORT'] == 443) { $self['secure'] = 1; } +if (isset ($_SERVER['SERVER_PORT']) && ($_SERVER['SERVER_PORT'] == 443) ) { $self['secure'] = 1; } @@ -168,6 +169,7 @@ // Include the basic system functions // any $conf settings used in this "require" should not be user adjusted in the sys_config table require_once($conf['inc_functions']); +require_once($conf['inc_functions_inetformat']); // Include the basic database functions require_once($conf['inc_functions_db']); @@ -217,7 +219,7 @@ } // Include functions that replace the default session handler with one that uses MySQL as a backend -require_once($conf['inc_db_sessions']); +# require_once($conf['inc_db_sessions']); // Include the GUI functions require_once($conf['inc_functions_gui']); @@ -229,20 +231,25 @@ startSession(); // Set session inactivity threshold -ini_set("session.gc_maxlifetime", $conf['cookie_life']); +if ( isset ($_SERVER['REQUEST_METHOD']) ) { + ini_set("session.gc_maxlifetime", $conf['cookie_life']); +} // if search_results_per_page is in the session, set the $conf variable to it. this fixes the /rows command if (isset($_SESSION['search_results_per_page'])) $conf['search_results_per_page'] = $_SESSION['search_results_per_page']; // Set up our page to https if requested for our URL links -if (@($conf['force_https'] == 1) or ($_SERVER['SERVER_PORT'] == 443)) { +if (@($conf['force_https'] == 1) or (isset ($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443)) { $https = "https://{$_SERVER['SERVER_NAME']}"; } else { - if ($_SERVER['SERVER_PORT'] != 80) { - $https = "http://{$_SERVER['SERVER_NAME']}:{$_SERVER['SERVER_PORT']}"; - } else { - $https = "http://{$_SERVER['SERVER_NAME']}"; + if ( isset ($_SERVER['SERVER_PORT'] ) ) + { + if ( $_SERVER['SERVER_PORT'] != 80) { + $https = "http://{$_SERVER['SERVER_NAME']}:{$_SERVER['SERVER_PORT']}"; + } else { + $https = "http://{$_SERVER['SERVER_NAME']}"; + } } } diff --git a/www/include/functions_db.inc.php b/www/include/functions_db.inc.php index 5be4e9e6..0631b4b6 100644 --- a/www/include/functions_db.inc.php +++ b/www/include/functions_db.inc.php @@ -1142,7 +1142,7 @@ function ona_get_domain_record($array='', $order='') { function ona_get_dns_record($array='', $order='') { list($status, $rows, $record) = ona_get_record($array, 'dns', $order); - if ($record['type'] == 'A' or $record['type'] == 'TXT') { + if ($record['type'] == 'A' or $record['type'] == 'AAAA' or $record['type'] == 'TXT') { $record['fqdn'] = $record['name'].'.'.ona_build_domain_name($record['domain_id']); $record['domain_fqdn'] = ona_build_domain_name($record['domain_id']); } @@ -1672,6 +1672,9 @@ function ona_find_domain($fqdn="", $returndefault=0) { // } // FIXME: MP rows is not right here.. need to look at fixing it.. rowsa/rowsb above doesnt translate.. do I even need that? + if ( !isset($rows) or !is_int($rows) ) { + $rows = 0; + } return(array($status, $rows, $domain)); } diff --git a/www/include/functions_general.inc.php b/www/include/functions_general.inc.php index 99adbffc..40082be1 100644 --- a/www/include/functions_general.inc.php +++ b/www/include/functions_general.inc.php @@ -145,7 +145,18 @@ function ona_logmsg($message, $logfile="") { } // Build the exact line we want to write to the file - $logdata = date("M j G:i:s ") . "{$uname['nodename']} {$username}@{$_SERVER['REMOTE_ADDR']}: [{$self['context_name']}] {$message}\n"; + // Prevent Undefined index notice when running CLI. + if (isset ( $_SERVER['REMOTE_ADDR'] ) ) { + $_remote_addr = $_SERVER['REMOTE_ADDR']; + } else { + $_remote_addr = ''; + } + if ( isset($self['context_name']) ) { + $_cn = $self['context_name']; + } else { + $_cn = ''; + } + $logdata = date("M j G:i:s ") . "{$uname['nodename']} {$username}@{$_remote_addr}: [{$_cn}] {$message}\n"; // Write the line to the file if (!fwrite($file, $logdata)) { @@ -1222,7 +1233,7 @@ function startSession() { global $conf; // If the command line agent, dcm.pl, is making the request, don't really start a session. - if (preg_match('/console-module-interface/', $_SERVER['HTTP_USER_AGENT'])) { + if ( isset ($_SERVER['HTTP_USER_AGENT']) && preg_match('/console-module-interface/', $_SERVER['HTTP_USER_AGENT'])) { // Pretend to log them in if (preg_match('/unix_username=([^&]+?)(&|$)/', $_REQUEST['options'], $matches)) { diff --git a/www/include/functions_gui.inc.php b/www/include/functions_gui.inc.php index cd4f4162..4c5cd635 100644 --- a/www/include/functions_gui.inc.php +++ b/www/include/functions_gui.inc.php @@ -141,7 +141,7 @@ function workspace_plugin_loader($modulename, $record=array(), $extravars=array( global $conf, $self, $base, $images, $color, $style, $onadb; $modhtml = ''; $modjs = ''; - $modwsmenu = ''; + $modwsmenu = array(); $modbodyhtml = ''; $ws_plugin_dir = "{$base}/workspace_plugins"; diff --git a/www/include/functions_inet_format.php b/www/include/functions_inet_format.php new file mode 100644 index 00000000..dd0be4fa --- /dev/null +++ b/www/include/functions_inet_format.php @@ -0,0 +1,17 @@ + diff --git a/www/modules/ona/dns_record.inc.php b/www/modules/ona/dns_record.inc.php index 7812d15b..032f534b 100644 --- a/www/modules/ona/dns_record.inc.php +++ b/www/modules/ona/dns_record.inc.php @@ -136,7 +136,7 @@ function dns_record_add($options="") { $add_srv_port = 0; // force AAAA to A to keep it consistant.. we'll display it properly as needed - if ($options['type'] == 'AAAA') $options['type'] = 'A'; + // if ($options['type'] == 'AAAA') $options['type'] = 'A'; // If the name we were passed has a leading or trailing . in it then remove the dot. $options['name'] = preg_replace("/^\./", '', $options['name']); @@ -234,7 +234,7 @@ function dns_record_add($options="") { } // Validate that there isn't already any dns record named $hostname in the domain $domain_id. - list($d_status, $d_rows, $d_record) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'interface_id' => $interface['id'],'type' => 'A', 'dns_view_id' => $add_viewid)); + list($d_status, $d_rows, $d_record) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'interface_id' => $interface['id'],'type' => $options['type'], 'dns_view_id' => $add_viewid)); if ($d_status or $d_rows) { printmsg("ERROR => Another DNS A record named {$hostname}.{$domain['fqdn']} with IP {$interface['ip_addr_text']} already exists!{$viewmsg}",3); $self['error'] = "ERROR => Another DNS A record named {$hostname}.{$domain['fqdn']} with IP {$interface['ip_addr_text']} already exists!{$viewmsg}"; @@ -310,7 +310,16 @@ function dns_record_add($options="") { // Find the dns record that it will point to list($status, $rows, $arecord) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'interface_id' => $interface['id'], 'type' => 'A','dns_view_id' => $add_viewid)); - if ($status or !$rows) { + list($status2, $rows2, $arecord2) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'interface_id' => $interface['id'], 'type' => 'AAAA','dns_view_id' => $add_viewid)); + if ( !isset($arecord['id']) ) + { + if ( isset($arecord2['id'] ) ) { + $arecord = $arecord2; + $rows = $rows2; + $status = $status2; + } + } + if ($status or $status2 or !$rows or !$rows2) { printmsg("ERROR => Unable to find DNS A record to point PTR entry to! Check that the IP you chose is associated with the name you chose.{$viewmsg}",3); $self['error'] = "ERROR => Unable to find DNS A record to point PTR entry to! Check that the IP you chose is associated with the name you chose.{$viewmsg}"; @@ -329,7 +338,6 @@ function dns_record_add($options="") { return(array(66, $self['error'] . "\n")); } - $ipflip = ip_mangle($interface['ip_addr'],'flip'); $octets = explode(".",$ipflip); if (count($octets) > 4) { @@ -353,7 +361,12 @@ function dns_record_add($options="") { } // PTR records dont need a name set. - $add_name = ''; + // but we are going to add it, so that Bind DLZ can query it + // name has to be the ip flip, sans the in-addr arap string and hex/octets of the IP. + + $add_name = preg_replace ('/\.' . $ptrdomain['name'] . '/', '', $ipflip.$arpa ); + // $add_name = $ipflip.$arpa; + // PTR records should not have domain_ids $add_domainid = $ptrdomain['id']; $add_interfaceid = $interface['id']; @@ -790,7 +803,7 @@ function dns_record_add($options="") { 'srv_port' => $add_srv_port, 'ebegin' => $options['ebegin'], 'notes' => $options['notes'], - 'dns_view_id' => $add_viewid + 'dns_view_id' => $add_viewid ) ); if ($status or !$rows) { @@ -802,7 +815,7 @@ function dns_record_add($options="") { $text = ''; // If it is an A record and they have specified to auto add the PTR record for it. - if ($options['addptr'] == 'Y' and $options['type'] == 'A') { + if ($options['addptr'] == 'Y' and ( $options['type'] == 'A' or $options['type'] == 'AAAA' ) ) { printmsg("DEBUG => Auto adding a PTR record for {$options['name']}.", 4); // Run dns_record_add as a PTR type list($status, $output) = run_module('dns_record_add', array('name' => $options['name'],'domain' => $domain['fqdn'],'ip' => $options['ip'],'ebegin' => $options['ebegin'],'type' => 'PTR','view' => $add_viewid)); @@ -1249,7 +1262,7 @@ function dns_record_modify($options="") { // If it is an A record and they have specified to auto add the PTR record for it. - if ($options['set_addptr'] == 'Y' and $options['set_type'] == 'A') { + if ($options['set_addptr'] == 'Y' and ( $options['set_type'] == 'A' || $options['set_type'] == 'AAAA' ) ) { printmsg("DEBUG => Auto adding a PTR record for {$options['set_name']}.", 0); // Run dns_record_add as a PTR type // Always use the $current_name variable as the name might change during the update @@ -1346,7 +1359,7 @@ function dns_record_modify($options="") { // Make sure we us A type for both A and AAAA - if ($SET['type'] == 'AAAA') $SET['type'] = 'A'; + // if ($SET['type'] == 'AAAA') $SET['type'] = 'A'; // Change the actual DNS record list($status, $rows) = db_update_record($onadb, 'dns', array('id' => $dns['id']), $SET); diff --git a/www/modules/ona/domain.inc.php b/www/modules/ona/domain.inc.php index 9e8ab250..b534d92b 100644 --- a/www/modules/ona/domain.inc.php +++ b/www/modules/ona/domain.inc.php @@ -209,6 +209,34 @@ function domain_add($options="") { $self['error'] = "ERROR => domain_add() SQL Query failed: " . $self['error']; printmsg($self['error'],0); return(array(7, $self['error'] . "\n")); + } else { + // FIXME: HACK for Bind-DLZ - need an SOA record in + // interface ID doesn't matter + $dns_id = ona_get_next_id('dns'); + + // Add the dns record + list($status, $rows) = db_insert_record( + $onadb, + 'dns', + array( + 'id' => $dns_id, + 'domain_id' => $id, + 'interface_id' => 0, + 'dns_id' => 0, + 'type' => 'SOA', + 'ttl' => 0, + 'name' => '', + 'mx_preference' => '0', + 'txt' => '', + 'srv_pri' => 0, + 'srv_weight' => 0, + 'srv_port' => 0, + 'notes' => '', + 'dns_view_id' => 0 + ) + ); + + } diff --git a/www/modules/ona/interface.inc.php b/www/modules/ona/interface.inc.php index 83b722a8..23566cb5 100644 --- a/www/modules/ona/interface.inc.php +++ b/www/modules/ona/interface.inc.php @@ -196,6 +196,7 @@ interface_add-v{$version} 'host_id' => $host['id'], 'subnet_id' => $subnet['id'], 'ip_addr' => $options['ip'], + 'ip_addr_inet' => inet_format($options['ip']), 'mac_addr' => $options['mac'], 'name' => trim($options['name']), 'description' => trim($options['description']) @@ -477,8 +478,10 @@ interface=ID or IP or MAC interface ID or IP address // Everything looks ok, add it to $SET if($interface['subnet_id'] != $subnet['id']) $SET['subnet_id'] = $subnet['id']; - if($interface['ip_addr'] != $options['set_ip']) - $SET['ip_addr'] = $options['set_ip']; + if($interface['ip_addr'] != $options['set_ip']) { + $SET['ip_addr'] = $options['set_ip']; + $SET['ip_addr_inet'] = inet_format($options['set_ip']); + } } diff --git a/www/winc/list_records.inc.php b/www/winc/list_records.inc.php index 9f4d646d..8ae6b60f 100644 --- a/www/winc/list_records.inc.php +++ b/www/winc/list_records.inc.php @@ -365,6 +365,8 @@ class="domain" } $record['name'] = preg_replace("/${domain_part}$/", '', $record['name']); + printmsg("DEBUG => list_records : " . json_encode ( array ( 'record' => $record, 'pointsto' => $pointsto, 'pdomain' => $pdomain, 'parent' => $parent ) ), 1); + $data = << Date: Fri, 20 Apr 2018 19:24:30 +0000 Subject: [PATCH 2/7] Added named.conf config for BIND-DLZ. --- docs/DPD-DLZ-INET-Chanages.md | 87 +++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/docs/DPD-DLZ-INET-Chanages.md b/docs/DPD-DLZ-INET-Chanages.md index 12e20d95..79e1f65c 100644 --- a/docs/DPD-DLZ-INET-Chanages.md +++ b/docs/DPD-DLZ-INET-Chanages.md @@ -32,3 +32,90 @@ The PHP code is changes, but two install scripts need to be run manually. * modules/ona/dns_record.inc.php - various tweaks for v6, as well as setting dns.name for PTR records. + +--- +**named.conf for BIND-DLZ** +The machine running bind-dlz, if you change /etc/resolv.conf to +point to localhost, you may want to use an IP address for the host. + +And yes, this format and syntax below works with Bind 9.12.0 and FreeBSD 11.1-stable. + +NOTE: Zone Transfers haven't be tested yet. + +``` +dlz "ONA Default" { + database "mysql + {host=a.b.c.d dbname=ona_ixsystems user=ona pass=xxx ssl=true} + {select name as zone from domains where name = '$zone$' limit 1} +{select + case + when dns.ttl = 0 + then domains.default_ttl + end as ttl, + dns.type as type, + CASE + when lower(dns.type)='mx' + then + dns.mx_preference + else '' + end as mx_priority, + case + when lower(dns.type)='a' or lower(dns.type)='aaaa' + then inet6_ntoa(interfaces.ip_addr_inet) + when lower(dns.type) in ( 'ptr', 'cname') + then (select concat(dns2.name, '.', domains.name, '.') from dns as dns2 inner join domains on domains.id = dns2.domain_id where dns.dns_id = dns2.id) + when lower(dns.type)='txt' + then concat('\"', dns.txt, '\"') + when lower(dns.type)='srv' + then concat('\"', + srv_pri ,' ', srv_weight,' ', srv_port, ' ', + concat ( dns.name, '.' , domains.name), + '\"') + when lower(dns.type) in ('mx', 'ns') + then (select concat(dns2.name, '.', domains.name, '.') from dns as dns2 inner join domains on domains.id = dns2.domain_id where dns.dns_id = dns2.id) + else concat(dns.name, '.' , domains.name) + end as data + from interfaces, dns, domains + where + dns.name = if ('$record$' like '@', '', '$record$') + and domains.name = '$zone$' + and dns.interface_id = interfaces.id + and dns.domain_id = domains.id + and upper(dns.type) not in ('SOA', 'NS')} + {select + case + when dns.ttl = 0 + then domains.default_ttl + end as ttl, + dns.type as type, + CASE + when lower(dns.type)='mx' + then + dns.mx_preference + else '' + end as mx_priority, + case + when lower(dns.type) in ('mx', 'ns') + then (select concat(dns2.name, '.', domains.name, '.') from dns as dns2 inner join domains on domains.id = dns2.domain_id where dns.dns_id = dns2.id) + when lower(dns.type) in ('soa') + then concat( + domains.primary_master, '. ', + domains.admin_email, '. ', + domains.serial, ' ', + domains.refresh, ' ', + domains.retry, ' ', + domains.expiry, ' ', + domains.minimum ) + else concat(dns.name, '.' , domains.name) + end as data + from interfaces, dns, domains + where + domains.name = '$zone$' + and dns.interface_id = interfaces.id + and dns.domain_id = domains.id + and upper(dns.type) in ('SOA', 'NS') order by type DESC} + {} + {select name as zone from domains where name = '$zone$' and '$client$' like '10.%'} + {}"; +}; +``` \ No newline at end of file From 88eb40c3c0483028be19738dafea92ecec5a6954 Mon Sep 17 00:00:00 2001 From: "David P. Discher" Date: Fri, 20 Apr 2018 21:29:36 +0000 Subject: [PATCH 3/7] syntax error, semicolon. --- install/inet-functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/inet-functions.php b/install/inet-functions.php index 17fd2f33..d0f89214 100644 --- a/install/inet-functions.php +++ b/install/inet-functions.php @@ -77,7 +77,7 @@ if (count($octets) > 4) { $arpa = 'ip6.arpa'; $octcount = 31; - $a = array_reverse ( $octets ) + $a = array_reverse ( $octets ); $domain = implode (".", $a); $_name = ''; $domain = implode (".", array ($a[0], $arpa) ); From 331b0306def434ecbbeb86c5164985b79203652d Mon Sep 17 00:00:00 2001 From: "David P. Discher" Date: Mon, 23 Apr 2018 19:14:04 +0000 Subject: [PATCH 4/7] Allow for MX,NS, and CNAME records to point to externals domains. Also allow for duplicate A/AAAA duplicate records. Allowing MX, NS and CNAME records to point to external domains is needed for example, for Gmail/GSuite MX Records. Also, if having other 3rd party cloud services, this is sometimes needed. Footer files are a solution, however not for BIND-DLZ server, and for single source of truth. This is an optional config, and when not enabled should have a NOOP effect: "allow_external_pointsto" => 1 HOWEVER - this does slightly break build-bind, and I have not yet provided patches. Allow Duplicate A,AAA records for the poor man's loadbalanceing with Round-Robin DNS. This too could be done with footers, however, in the spirit of a single source of truth - allowing this to be in the database as well as allowing BIND-DLZ to server it. "allow_duplicate_arecords" => 1 --- install/inet-functions.sql | 1 + www/config/config.inc.php | 29 ++++-- www/include/functions_db.inc.php | 21 ++-- www/include/functions_general.inc.php | 20 +++- www/modules/ona/dns_record.inc.php | 135 ++++++++++++++++++++++---- www/winc/display_domain.inc.php | 16 ++- www/winc/list_records.inc.php | 2 - 7 files changed, 183 insertions(+), 41 deletions(-) diff --git a/install/inet-functions.sql b/install/inet-functions.sql index a5a2e13b..b184c41c 100644 --- a/install/inet-functions.sql +++ b/install/inet-functions.sql @@ -2,3 +2,4 @@ alter table interfaces add `ip_addr_inet` varbinary(16) default NULL; CREATE INDEX domains_name_index ON domains (name); CREATE INDEX dns_name_index ON dns (name); CREATE INDEX type_index ON dns (type); +INSERT INTO interfaces (id, subnet_id, host_id, nat_interface_id, ip_addr, mac_addr, name, description, last_response, ip_addr_inet) VALUES (0, 0, 0, 0, 0, '0', '0', '0', '2018-04-20 15:14:24', null); diff --git a/www/config/config.inc.php b/www/config/config.inc.php index 1c558ff1..d990b011 100644 --- a/www/config/config.inc.php +++ b/www/config/config.inc.php @@ -70,12 +70,23 @@ "plugin_dir" => "$base/local/plugins", /* Defaults for some user definable options normally in sys_config table */ - "debug" => "16", + "debug" => "0", "syslog" => "0", "stdout" => "0", "log_to_db" => "0", "logfile" => "/var/log/ona.log", + /* + Allow MX, NS and CNAME records to point to external domains + For example, this is needed for Gmail/GSuite MX Records. + */ + "allow_external_pointsto" => 0, + + /* + Allow Duplicate A,AAA records for Round-Robin DNS + */ + "allow_duplicate_arecords" => 0, + /* The output charset to be used in htmlentities() and htmlspecialchars() filtering */ "charset" => "utf8", "php_charset" => "UTF-8", @@ -214,9 +225,14 @@ // These will override any of the defaults set above list($status, $rows, $records) = db_get_records($onadb, 'sys_config', 'name like "%"', 'name'); foreach ($records as $record) { - printmsg("INFO => Loaded config item from database: {$record['name']}=''{$record['value']}''",5); $conf[$record['name']] = $record['value']; } +// Do this twice, so to reflect the sys_config database debug value; +if ( $conf['debug'] > 4 ) { + foreach ($records as $record) { + printmsg("INFO => Loaded config item from database: {$record['name']}=''{$record['value']}''",5); + } +} // Include functions that replace the default session handler with one that uses MySQL as a backend # require_once($conf['inc_db_sessions']); @@ -227,14 +243,15 @@ // Include the AUTH functions require_once($conf['inc_functions_auth']); -// Start the session handler (this calls a function defined in functions_general) -startSession(); - -// Set session inactivity threshold +// Set session inactivity threshold - before you start the session. if ( isset ($_SERVER['REQUEST_METHOD']) ) { ini_set("session.gc_maxlifetime", $conf['cookie_life']); } +// Start the session handler (this calls a function defined in functions_general) +startSession(); + + // if search_results_per_page is in the session, set the $conf variable to it. this fixes the /rows command if (isset($_SESSION['search_results_per_page'])) $conf['search_results_per_page'] = $_SESSION['search_results_per_page']; diff --git a/www/include/functions_db.inc.php b/www/include/functions_db.inc.php index 0631b4b6..5cb18fe4 100644 --- a/www/include/functions_db.inc.php +++ b/www/include/functions_db.inc.php @@ -1140,15 +1140,20 @@ function ona_get_domain_record($array='', $order='') { // Returns an additional "fqdn" field for some dns records function ona_get_dns_record($array='', $order='') { + global $conf; list($status, $rows, $record) = ona_get_record($array, 'dns', $order); - - if ($record['type'] == 'A' or $record['type'] == 'AAAA' or $record['type'] == 'TXT') { - $record['fqdn'] = $record['name'].'.'.ona_build_domain_name($record['domain_id']); - $record['domain_fqdn'] = ona_build_domain_name($record['domain_id']); - } - if ($record['type'] == 'CNAME') { - $record['fqdn'] = $record['name'].'.'.ona_build_domain_name($record['domain_id']); - $record['domain_fqdn'] = ona_build_domain_name($record['domain_id']); + if ($record['type'] == 'A' or $record['type'] == 'AAAA' or $record['type'] == 'TXT' or $record['type'] == 'CNAME') { + if ( $conf['allow_external_pointsto'] && preg_match ( '/\.$/', $record['name']) ) + { + $record['name'] = preg_replace ( '/\.$/', '', $record['name'] ); + $record['fqdn'] = $record['name']; + $a = array_reverse ( explode(".", $record['name']) ) ; + $record['domain_fqdn_old'] = $a[2] . "." . $a[1]; + $record['domain_fqdn'] = ''; + } else { + $record['fqdn'] = $record['name'].'.'.ona_build_domain_name($record['domain_id']); + $record['domain_fqdn'] = ona_build_domain_name($record['domain_id']); + } } return(array($status, $rows, $record)); } diff --git a/www/include/functions_general.inc.php b/www/include/functions_general.inc.php index 40082be1..eb90b6f7 100644 --- a/www/include/functions_general.inc.php +++ b/www/include/functions_general.inc.php @@ -3,9 +3,18 @@ // Debugging: lets print what's in $_REQUEST -if ( 6 <= $conf['debug'] ) { - printmsg("Get/Post vars:", 6); - foreach (array_keys($_REQUEST) as $key) printmsg("Name: $key Value: $_REQUEST[$key]", 6); +if ( $conf['debug'] > 5 ) { + printmsg("Get/Post vars: . ", 6); + // this was getting "Array to string conversion" notice in PHP error logs. + // So, fix that for nested arrays, Serialize with JSON. + foreach ($_REQUEST as $key => $value) { + if ( is_array ($value) ) { + $v = json_encode ( $value ); + } else { + $v = $value; + } + printmsg("Name: $key Value: $v", 6); + } } // MP: moved this stuff to config.inc.php @@ -646,7 +655,10 @@ function ipv6gz($ip) { // If we get here, then the input must be in numeric format (1) else { - $ip = gmp_init(strval($ip), 10); + // FIXME: "PHP Warning: gmp_init(): Unable to convert variable to GMP" + // This happens when $ip == NULL, but fixing this, created even more warnings + // down the code. I'm going to suppress warnings with @. + $ip = @gmp_init(strval($ip), 10); if ($format == "default") { if(is_ipv4($ip)) $format = "dotted"; diff --git a/www/modules/ona/dns_record.inc.php b/www/modules/ona/dns_record.inc.php index 032f534b..c1058707 100644 --- a/www/modules/ona/dns_record.inc.php +++ b/www/modules/ona/dns_record.inc.php @@ -235,10 +235,12 @@ function dns_record_add($options="") { // Validate that there isn't already any dns record named $hostname in the domain $domain_id. list($d_status, $d_rows, $d_record) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'],'interface_id' => $interface['id'],'type' => $options['type'], 'dns_view_id' => $add_viewid)); - if ($d_status or $d_rows) { + if (($d_status or $d_rows) and !$conf['allow_duplicate_arecords']) { printmsg("ERROR => Another DNS A record named {$hostname}.{$domain['fqdn']} with IP {$interface['ip_addr_text']} already exists!{$viewmsg}",3); $self['error'] = "ERROR => Another DNS A record named {$hostname}.{$domain['fqdn']} with IP {$interface['ip_addr_text']} already exists!{$viewmsg}"; return(array(5, $self['error'] . "\n")); + } else if ($conf['allow_duplicate_arecords']) { + printmsg("DEBUG => Allowing duplicate A/AAA records for {$hostname}.{$domain['fqdn']} with IP {$interface['ip_addr_text']}; Input : IP: " . $options['ip'] . "Hostname: $hostname ; domain:" . $domain['name'] , 3); } // Validate that there are no CNAMES already with this fqdn @@ -329,12 +331,12 @@ function dns_record_add($options="") { // MP: since there could be multiple A records, I'm going to fail out if there is not JUST ONE A record. // this is limiting in a way but allows cleaner data. list($status, $rows, $arecord) = ona_get_dns_record(array('name' => $hostname, 'domain_id' => $domain['id'], 'type' => 'A','dns_view_id' => $add_viewid)); - if (($rows > 1)) { + if (($rows > 1) and !$conf['allow_duplicate_arecords']) { printmsg("ERROR => Unable to find a SINGLE DNS A record to point PTR entry to! In this case, you are only allowed to do this if there is one A record using this name.{$viewmsg}",3); $self['error'] = "ERROR => Unable to find a SINGLE DNS A record to point PTR entry to! In this case, you are only allowed to do this if there is one A record using this name.{$viewmsg}"; } - if ($rows != 1) + if ($rows == 0) return(array(66, $self['error'] . "\n")); } @@ -446,10 +448,44 @@ function dns_record_add($options="") { // Find the dns record that it will point to list($status, $rows, $pointsto_record) = ona_get_dns_record(array('name' => $phostname, 'domain_id' => $pdomain['id'], 'type' => 'A','dns_view_id' => $add_viewid)); + if ($status or !$rows) { - printmsg("ERROR => Unable to find DNS A record to point CNAME entry to!{$viewmsg}",3); - $self['error'] = "ERROR => Unable to find DNS A record to point CNAME entry to!{$viewmsg}"; - return(array(5, $self['error'] . "\n")); + if ( !$conf['allow_external_pointsto']) { + printmsg("ERROR => Unable to find DNS A record to point CNAME entry to!{$viewmsg}",3); + $self['error'] = "ERROR => Unable to find DNS A record to point CNAME entry to!{$viewmsg}"; + return(array(5, $self['error'] . "\n")); + } else { + printmsg("DEBUG => Allowing an external pointer, Using 'pointsto' as given, hostname: {$options['pointsto']}, for domain { " . $domain['id'] . ":" . $domain['name'] . " } Domain ID: {$pdomain['id']}", 3); + if ( !preg_match ( '/\.$/', $options['pointsto']) ) + { + $name = $options['pointsto'] . '.'; + } else { + $name = $options['pointsto']; + } + $dns_id = ona_get_next_id('dns'); + $pointsto_record['interface_id'] = 0; + $pointsto_record['id'] = $dns_id; + list($status, $rows) = db_insert_record( + $onadb, + 'dns', + array( + 'id' => $dns_id, + 'domain_id' => $domain['id'], + 'interface_id' => 0, + 'dns_id' => 0, + 'type' => 'A', + 'ttl' => 0, + 'name' => $name, + 'mx_preference' => '0', + 'txt' => '', + 'srv_pri' => 0, + 'srv_weight' => 0, + 'srv_port' => 0, + 'notes' => '', + 'dns_view_id' => 0 + ) + ); + } } @@ -515,12 +551,43 @@ function dns_record_add($options="") { // Validate that there are no NS already with this domain and host list($status, $rows, $record) = ona_get_dns_record(array('dns_id' => $pointsto_record['id'], 'domain_id' => $domain['id'],'type' => 'NS','dns_view_id' => $add_viewid)); if ($rows or $status) { - printmsg("ERROR => Another DNS NS record for {$domain['fqdn']} pointing to {$options['pointsto']} already exists!{$viewmsg}",3); - $self['error'] = "ERROR => Another DNS NS record for {$domain['fqdn']} pointing to {$options['pointsto']} already exists!{$viewmsg}"; - return(array(5, $self['error'] . "\n")); - } - - + if ( !$conf['allow_external_pointsto']) { + printmsg("ERROR => Another DNS NS record for {$domain['fqdn']} pointing to {$options['pointsto']} already exists!{$viewmsg}",3); + $self['error'] = "ERROR => Another DNS NS record for {$domain['fqdn']} pointing to {$options['pointsto']} already exists!{$viewmsg}"; + return(array(5, $self['error'] . "\n")); + } else { + printmsg("DEBUG => Allowing an external pointer, Using 'pointsto' as given, hostname: {$options['pointsto']}, for domain { " . $domain['id'] . ":" . $domain['name'] . " } Domain ID: {$pdomain['id']}", 3); + if ( !preg_match ( '/\.$/', $options['pointsto']) ) + { + $name = $options['pointsto'] . '.'; + } else { + $name = $options['pointsto']; + } + $dns_id = ona_get_next_id('dns'); + $pointsto_record['interface_id'] = 0; + $pointsto_record['id'] = $dns_id; + list($status, $rows) = db_insert_record( + $onadb, + 'dns', + array( + 'id' => $dns_id, + 'domain_id' => $domain['id'], + 'interface_id' => 0, + 'dns_id' => 0, + 'type' => 'A', + 'ttl' => 0, + 'name' => $name, + 'mx_preference' => '0', + 'txt' => '', + 'srv_pri' => 0, + 'srv_weight' => 0, + 'srv_port' => 0, + 'notes' => '', + 'dns_view_id' => 0 + ) + ); + } + } $add_name = ''; //$options['name']; $add_domainid = $domain['id']; $add_interfaceid = $pointsto_record['interface_id']; @@ -582,12 +649,44 @@ function dns_record_add($options="") { // Find the dns record that it will point to list($status, $rows, $pointsto_record) = ona_get_dns_record(array('name' => $phostname, 'domain_id' => $pdomain['id'], 'type' => 'A','dns_view_id' => $add_viewid)); if ($status or !$rows) { - printmsg("ERROR => Unable to find DNS A record to point NS entry to!{$viewmsg}",3); - $self['error'] = "ERROR => Unable to find DNS A record to point NS entry to!{$viewmsg}"; - return(array(5, $self['error'] . "\n")); + if ( !$conf['allow_external_pointsto'] ) { + printmsg("ERROR => Unable to find DNS A record to point NS entry to!{$viewmsg}",3); + $self['error'] = "ERROR => Unable to find DNS A record to point NS entry to!{$viewmsg}"; + return(array(5, $self['error'] . "\n")); + } else { + printmsg("DEBUG => Allowing an external pointer, Using 'pointsto' as given, hostname: {$options['pointsto']}, for domain { " . $domain['id'] . ":" . $domain['name'] . " } Domain ID: {$pdomain['id']}", 3); + if ( !preg_match ( '/\.$/', $options['pointsto']) ) + { + $name = $options['pointsto'] . '.'; + } else { + $name = $options['pointsto']; + } + $dns_id = ona_get_next_id('dns'); + $pointsto_record['interface_id'] = 0; + $pointsto_record['id'] = $dns_id; + list($status, $rows) = db_insert_record( + $onadb, + 'dns', + array( + 'id' => $dns_id, + 'domain_id' => $domain['id'], + 'interface_id' => 0, + 'dns_id' => 0, + 'type' => 'A', + 'ttl' => 0, + 'name' => $name, + 'mx_preference' => '0', + 'txt' => '', + 'srv_pri' => 0, + 'srv_weight' => 0, + 'srv_port' => 0, + 'notes' => '', + 'dns_view_id' => 0 + ) + ); + } } - $add_name = $hostname; $add_domainid = $domain['id']; $add_interfaceid = $pointsto_record['interface_id']; @@ -1189,8 +1288,8 @@ function dns_record_modify($options="") { // Find the dns record that it will point to list($status, $rows, $pointsto_record) = ona_get_dns_record(array('name' => $phostname, 'domain_id' => $pdomain['id'], 'type' => 'A','dns_view_id' => $check_dns_view_id)); if ($status or !$rows) { - printmsg("ERROR => Unable to find DNS A record to point {$options['set_type']} entry to!{$viewmsg}",3); - $self['error'] = "ERROR => Unable to find DNS A record to point {$options['set_type']} entry to!{$viewmsg}"; + printmsg("ERROR => Unable to find DNS A record to point {$options['set_type']} entry to!{$viewmsg} " ,3); + $self['error'] = "ERROR => Unable to find DNS A record to point {$options['set_type']} entry to!{$viewmsg} "; return(array(5, $self['error'] . "\n")); } diff --git a/www/winc/display_domain.inc.php b/www/winc/display_domain.inc.php index 6ca8e8e7..7f4fea04 100644 --- a/www/winc/display_domain.inc.php +++ b/www/winc/display_domain.inc.php @@ -66,8 +66,18 @@ function ws_display($window_name, $form='') { EOL; // Escape data for display in html - foreach(array_keys($record) as $key) { $record[$key] = htmlentities($record[$key], ENT_QUOTES, $conf['php_charset']); } - foreach(array_keys((array)$parent_domain) as $key) { $parent_domain[$key] = htmlentities($parent_domain[$key], ENT_QUOTES, $conf['php_charset']); } + if (is_array ($record) ) { + foreach($record as $key => $v) { + $record[$key] = htmlentities($v, ENT_QUOTES, $conf['php_charset']); + } + } + if (is_array ($parent_domain) ) { + foreach($parent_domain as $key => $v) { + printmsg("DEBUG => {" . __FILE__ . ":" . __LINE__ . "} parent_domain key/value : " . $key . " : " . $value , 6); + // Cannot assign an empty string to a string offset + $parent_domain[$key] = htmlentities($v, ENT_QUOTES, $conf['php_charset']); + } + } $html .= << EOL; - if ($parent_domain['id']) { + if (isset ($parent_domain['id']) && $parent_domain['id']) { $html .= << Parent Domain  diff --git a/www/winc/list_records.inc.php b/www/winc/list_records.inc.php index 8ae6b60f..9f4d646d 100644 --- a/www/winc/list_records.inc.php +++ b/www/winc/list_records.inc.php @@ -365,8 +365,6 @@ class="domain" } $record['name'] = preg_replace("/${domain_part}$/", '', $record['name']); - printmsg("DEBUG => list_records : " . json_encode ( array ( 'record' => $record, 'pointsto' => $pointsto, 'pdomain' => $pdomain, 'parent' => $parent ) ), 1); - $data = << Date: Mon, 23 Apr 2018 19:24:08 +0000 Subject: [PATCH 5/7] Update query for Allowing MX, NS and CNAME to point to exteneral domains as well as A/AAAA round robin. --- docs/DPD-DLZ-INET-Chanages.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/DPD-DLZ-INET-Chanages.md b/docs/DPD-DLZ-INET-Chanages.md index 79e1f65c..091983db 100644 --- a/docs/DPD-DLZ-INET-Chanages.md +++ b/docs/DPD-DLZ-INET-Chanages.md @@ -62,8 +62,14 @@ dlz "ONA Default" { case when lower(dns.type)='a' or lower(dns.type)='aaaa' then inet6_ntoa(interfaces.ip_addr_inet) - when lower(dns.type) in ( 'ptr', 'cname') - then (select concat(dns2.name, '.', domains.name, '.') from dns as dns2 inner join domains on domains.id = dns2.domain_id where dns.dns_id = dns2.id) + when lower(dns.type) in ( 'ptr', 'cname', 'mx', 'ns') + then (select + CASE + WHEN SUBSTRING(dns2.name, -1) = '.' + THEN dns2.name + ELSE concat(dns2.name, '.', domains.name, '.') + end + from dns as dns2 inner join domains on domains.id = dns2.domain_id where dns.dns_id = dns2.id) when lower(dns.type)='txt' then concat('\"', dns.txt, '\"') when lower(dns.type)='srv' @@ -95,8 +101,14 @@ dlz "ONA Default" { else '' end as mx_priority, case - when lower(dns.type) in ('mx', 'ns') - then (select concat(dns2.name, '.', domains.name, '.') from dns as dns2 inner join domains on domains.id = dns2.domain_id where dns.dns_id = dns2.id) + when lower(dns.type) in ( 'ptr', 'cname', 'mx', 'ns') + then (select + CASE + WHEN SUBSTRING(dns2.name, -1) = '.' + THEN dns2.name + ELSE concat(dns2.name, '.', domains.name, '.') + end + from dns as dns2 inner join domains on domains.id = dns2.domain_id where dns.dns_id = dns2.id) when lower(dns.type) in ('soa') then concat( domains.primary_master, '. ', From c688fcdbf4c2491dee281edbe267b9e3994e87d5 Mon Sep 17 00:00:00 2001 From: "David P. Discher" Date: Wed, 25 Apr 2018 03:35:57 +0000 Subject: [PATCH 6/7] Fix ONA so that a third level dns domain can add a DNS server. --- www/config/config.inc.php | 2 +- www/include/functions_gui.inc.php | 4 ++-- www/modules/ona/dns_record.inc.php | 2 +- www/modules/ona/domain_server.inc.php | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/www/config/config.inc.php b/www/config/config.inc.php index 47be897a..63750f6e 100644 --- a/www/config/config.inc.php +++ b/www/config/config.inc.php @@ -217,7 +217,7 @@ } // Include functions that replace the default session handler with one that uses MySQL as a backend -require_once($conf['inc_db_sessions']); +// require_once($conf['inc_db_sessions']); // Include the GUI functions require_once($conf['inc_functions_gui']); diff --git a/www/include/functions_gui.inc.php b/www/include/functions_gui.inc.php index cd4f4162..dc4995ec 100644 --- a/www/include/functions_gui.inc.php +++ b/www/include/functions_gui.inc.php @@ -141,7 +141,7 @@ function workspace_plugin_loader($modulename, $record=array(), $extravars=array( global $conf, $self, $base, $images, $color, $style, $onadb; $modhtml = ''; $modjs = ''; - $modwsmenu = ''; + $modwsmenu = array(); $modbodyhtml = ''; $ws_plugin_dir = "{$base}/workspace_plugins"; @@ -350,7 +350,7 @@ function get_host_suggestions($q, $max_results=10) { list($status, $rows, $view) = db_get_record($onadb, 'dns_views', array('id' => $record['dns_view_id'])); $viewname = $view['name'].'/'; } - $results[] = $viewname.$record[$field].".".$domain['name']; + $results[] = $viewname.$record[$field].".".ona_build_domain_name ( $record['domain_id'] ); } } diff --git a/www/modules/ona/dns_record.inc.php b/www/modules/ona/dns_record.inc.php index 7812d15b..8d2dd252 100644 --- a/www/modules/ona/dns_record.inc.php +++ b/www/modules/ona/dns_record.inc.php @@ -951,7 +951,7 @@ function dns_record_modify($options="") { $options['set_name'] = preg_replace("/^\./", '', $options['set_name']); // Find the DNS record from $options['name'] - list($status, $rows, $dns) = ona_find_dns_record($options['name']); + list($status, $rows, $dns) = ona_find_dns_record($options['server'] . "." . $domain['fqdn']); printmsg("DEBUG => dns_record_modify() DNS record: {$dns['fqdn']}", 3); if ($rows > 1) { printmsg("DEBUG => Found more than one DNS record for: {$options['name']}",3); diff --git a/www/modules/ona/domain_server.inc.php b/www/modules/ona/domain_server.inc.php index f187d910..b3e6ddda 100644 --- a/www/modules/ona/domain_server.inc.php +++ b/www/modules/ona/domain_server.inc.php @@ -80,7 +80,7 @@ function domain_server_add($options="") { printmsg("DEBUG => domain_server_add(): Found domain, {$domain['name']}", 3); // Determine the server is valid - list($status, $rows, $ns_dns) = ona_find_dns_record($options['server']); + list($status, $rows, $ns_dns) = ona_find_dns_record($options['server'] . "." . $domain['fqdn']); list($status, $rows, $interface) = ona_find_interface($ns_dns['interface_id']); $host['id'] = $interface['host_id']; @@ -169,7 +169,7 @@ function domain_server_add($options="") { if (!$dnsrows) { printmsg("DEBUG => Auto adding a NS record for {$options['server']}.", 0); // Run dns_record_add as a NS type - list($status, $output) = run_module('dns_record_add', array('name' => $domain['fqdn'],'pointsto' => $options['server'], 'type' => 'NS')); + list($status, $output) = run_module('dns_record_add', array('name' => $domain['fqdn'],'pointsto' => $options['server'] . "." . $domain['fqdn'], 'type' => 'NS')); if ($status) return(array($status, $output)); $add_to_error .= $output; From e9e46974c71e19e545cc3355666cbcf38515431f Mon Sep 17 00:00:00 2001 From: "David P. Discher" Date: Thu, 24 May 2018 18:06:49 +0000 Subject: [PATCH 7/7] Remove older files in the wrong place --- inet-functions.php | 142 --------------------------------------------- inet-functions.sql | 4 -- 2 files changed, 146 deletions(-) delete mode 100644 inet-functions.php delete mode 100644 inet-functions.sql diff --git a/inet-functions.php b/inet-functions.php deleted file mode 100644 index aa6240ee..00000000 --- a/inet-functions.php +++ /dev/null @@ -1,142 +0,0 @@ - Couldn't find include folder {$include}!\n"; exit; } -require_once($base . '/config/config.inc.php'); -/* --------------------------------------------------------- */ - -global $conf, $self, $onadb; - -// Uncomment the following to get a ton o' debug -//$conf['debug'] = 6; -echo "Checking for SOA meta records:\n"; - -list($status, $rows, $domains) = db_get_records($onadb, 'domains', 'id > 0'); -#print_r ( $domains ); -foreach ( $domains as $d ) { - list($status, $rows, $soa) = db_get_records($onadb, 'dns', "type = 'SOA' and domain_id = '" . $d['id'] . "' "); - if ( $rows == 0 ) { - printf ("{%36s} - doesn't have an SOA DNS Record. \n", $d['name'] ); - // Add the dns record - $dns_id = ona_get_next_id('dns'); - list($status, $rows) = db_insert_record( - $onadb, - 'dns', - array( - 'id' => $dns_id, - 'domain_id' => $d['id'], - 'interface_id' => 0, - 'dns_id' => 0, - 'type' => 'SOA', - 'ttl' => 0, - 'name' => '', - 'mx_preference' => '0', - 'txt' => '', - 'srv_pri' => 0, - 'srv_weight' => 0, - 'srv_port' => 0, - 'notes' => '', - 'dns_view_id' => 0 - ) - ); - if ($status or !$rows) { - printf ("{%36s} - SOA DNS Record insert FAILED. \n", $d['name'] ); - } else { - printf ("{%36s} - SOA DNS Record created. \n", $d['name'] ); - } - - } else { - printf ("{%36s} - has an SOA DNS Record. \n", $d['name'] ); - } -} - -// Get the PTR records that dont have a domain_id -list($status, $rows, $ptrs) = db_get_records($onadb, 'dns', "type = 'PTR'", ''); -echo "Found {$rows} PTR with ptr records - will update all of them\n"; - -foreach ($ptrs as $ptr) { - list($status, $rows, $interface) = ona_get_interface_record(array('id' => $ptr['interface_id'])); - - // Print an error if it doesnt find an IP - if (!$interface['ip_addr']) { - echo "Possible orphan PTR record in dns table at ID: {$ptr['id']}. You should delete this record manually.\n"; - continue; - } - - $ipflip = ip_mangle($interface['ip_addr'],'flip'); - $octets = explode(".",$ipflip); - if (count($octets) > 4) { - $arpa = 'ip6.arpa'; - $octcount = 31; - #$domain = $arpa; - $a = array (); - for ($i=$octcount; $i>$octcount-11; $i--) { - array_push ($a, $octets[$i]); - } - array_push ($a, $arap ); - $domain = implode (".", $a); - $_name = ''; - $a = array (); - for ($i=$octcount-11; $i>=0; $i--) { - array_push ($a, $octets[$i]); - } - $_name = implode (".", $a); - } else { - $arpa = 'in-addr.arpa'; - $octcount = 3; - $domain = $octets[2] . "." . $octets[3] . "." . $arpa; - $_name = $octets[0] . "." . $octets[1]; - } - // Find a pointer zone for this record to associate with. - echo " Searching for $domain \n"; - list($status, $prows, $ptrdomain) = ona_find_domain($domain); - echo " => Found for $domain => " . $ptrdomain['id'] . " " . $ptrdomain['name'] ."\n" ; - - // print_r ( $ptrdomain ); - // CRAPPY security cludge - $_SESSION['ona']['auth']['user']['username'] = 'PTRFIX'; - $_SESSION['ona']['auth']['perms']['advanced'] = 'Y'; - $_SESSION['ona']['auth']['perms']['host_modify'] = 'Y'; - - if (!$ptrdomain['id'] or ($domain != $ptrdomain['name']) ) { - echo " {$interface['ip_addr_text']}: Unable to find a pointer domain for this IP! Creating the following DNS domain: {$domain} \n"; - list($status, $output) = run_module('domain_add', array('name' => $domain)); - if ($status) { - echo "ERROR => {$output}\n"; - exit($status); - } - list($status, $rows, $ptrdomain) = ona_find_domain($domain); - } - - // Found a domain to put them in. - echo " Updating PTR for IP {$interface['ip_addr_text']} to $ipflip.in-addr.arpa\n"; - - // Change the actual DNS record - list($status, $rows) = db_update_record($onadb, 'dns', array('id' => $ptr['id']), array( 'name' => $_name, 'domain_id' => $ptrdomain['id'] )); - // if ($status or !$rows) { - // echo "ERROR => SQL Query failed updating dns record: " . $self['error'] . " $status \n" ; - // exit(2); - // } - - -} - -list($status, $rows, $interfaces) = db_get_records($onadb, 'interfaces', "ip_addr is not null", ''); -foreach ($interfaces as $interface ) { - echo " Adding inet6_atoi field " . $interface['id'] . "\n"; - list($status, $rows) = db_update_record($onadb, 'interfaces', array('id' => $interface['id']), array ('ip_addr_inet' => inet_format($interface['ip_addr']) )); - -} - -exit(0); - -?> diff --git a/inet-functions.sql b/inet-functions.sql deleted file mode 100644 index a5a2e13b..00000000 --- a/inet-functions.sql +++ /dev/null @@ -1,4 +0,0 @@ -alter table interfaces add `ip_addr_inet` varbinary(16) default NULL; -CREATE INDEX domains_name_index ON domains (name); -CREATE INDEX dns_name_index ON dns (name); -CREATE INDEX type_index ON dns (type);