239 lines
7.9 KiB
PHP
239 lines
7.9 KiB
PHP
<?php
|
|
|
|
/*
|
|
----------------------------------------------------------------------
|
|
LICENSE
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License (GPL)
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
To read the license please visit http://www.gnu.org/copyleft/gpl.html
|
|
----------------------------------------------------------------------
|
|
*/
|
|
|
|
/**
|
|
* Manages BIND 9+ zone management templates in AlternC 3.5+
|
|
*
|
|
* @copyright AlternC-Team 2000-2018 https://alternc.com/
|
|
*/
|
|
class m_bind {
|
|
|
|
var $shouldreload;
|
|
var $shouldreconfig;
|
|
|
|
var $ZONE_TEMPLATE ="/etc/alternc/templates/bind/templates/zone.template";
|
|
var $NAMED_TEMPLATE ="/etc/alternc/templates/bind/templates/named.template";
|
|
var $NAMED_CONF ="/var/lib/alternc/bind/automatic.conf";
|
|
var $RNDC ="/usr/sbin/rndc";
|
|
|
|
var $zone_file_directory = '/var/lib/alternc/bind/zones';
|
|
|
|
// ------------------------------------------------------------
|
|
/** Hook launched before any action by updatedomains
|
|
* initialize the reload/reconfig flags used by POST
|
|
* @NOTE launched as ROOT
|
|
*/
|
|
function hook_updatedomains_dns_pre() {
|
|
$this->shouldreload=false;
|
|
$this->shouldreconfig=false;
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
/**
|
|
* Hook launched for each ZONE for which we want a zone update (or create)
|
|
* update the zone, create it if necessary,
|
|
* and ask for reload or reconfig of bind9 depending on what happened
|
|
* @NOTE launched as ROOT
|
|
*/
|
|
function hook_updatedomains_dns_add($dominfo) {
|
|
global $L_FQDN,$L_NS1_HOSTNAME,$L_NS2_HOSTNAME,$L_DEFAULT_MX,$L_DEFAULT_SECONDARY_MX,$L_PUBLIC_IP,$L_PUBLIC_IPV6;
|
|
|
|
$domain = $dominfo["domaine"];
|
|
$ttl = $dominfo["zonettl"];
|
|
|
|
// does it already exist?
|
|
if (file_exists($this->zone_file_directory."/".$domain)) {
|
|
list($islocked,$serial,$more)=$this->read_zone($domain);
|
|
$serial++; // only increment serial for new zones
|
|
} else {
|
|
$more="";
|
|
$serial=date("Ymd")."00";
|
|
$islocked=false;
|
|
}
|
|
if ($islocked) return;
|
|
|
|
// Prepare a new zonefile from a template
|
|
$zone = file_get_contents($this->ZONE_TEMPLATE);
|
|
|
|
// add the SUBDOMAIN entries
|
|
$zone .= $this->conf_from_db($domain);
|
|
|
|
// substitute ALTERNC & domain variables
|
|
$zone = strtr($zone, array(
|
|
"%%fqdn%%" => "$L_FQDN",
|
|
"%%ns1%%" => "$L_NS1_HOSTNAME",
|
|
"%%ns2%%" => "$L_NS2_HOSTNAME",
|
|
"%%DEFAULT_MX%%" => "$L_DEFAULT_MX",
|
|
"%%DEFAULT_SECONDARY_MX%%" => "$L_DEFAULT_SECONDARY_MX",
|
|
"@@fqdn@@" => "$L_FQDN",
|
|
"@@ns1@@" => "$L_NS1_HOSTNAME",
|
|
"@@ns2@@" => "$L_NS2_HOSTNAME",
|
|
"@@DEFAULT_MX@@" => "$L_DEFAULT_MX",
|
|
"@@DEFAULT_SECONDARY_MX@@" => "$L_DEFAULT_SECONDARY_MX",
|
|
"@@DOMAINE@@" => $domain,
|
|
"@@SERIAL@@" => $serial,
|
|
"@@PUBLIC_IP@@" => "$L_PUBLIC_IP",
|
|
"@@PUBLIC_IPV6@@" => "$L_PUBLIC_IPV6",
|
|
"@@ZONETTL@@" => $ttl,
|
|
));
|
|
|
|
// add the "END ALTERNC CONF line";
|
|
$zone .= ";;; END ALTERNC AUTOGENERATE CONFIGURATION\n";
|
|
|
|
// add the manually entered info:
|
|
$zone .= $more;
|
|
file_put_contents($this->zone_file_directory."/".$domain,$zone);
|
|
|
|
// add the line into bind9 conf:
|
|
if (add_line_to_file(
|
|
$this->NAMED_CONF,
|
|
trim(strtr(
|
|
file_get_contents($this->NAMED_TEMPLATE),
|
|
array(
|
|
"@@DOMAIN@@" => $domain,
|
|
"@@ZONE_FILE@@" => $this->zone_file_directory."/".$domain
|
|
)
|
|
)))
|
|
) {
|
|
$this->shouldreconfig=true;
|
|
} else {
|
|
$this->shouldreload=true;
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
/**
|
|
* Hook launched for each ZONE for which we want a zone DELETE
|
|
* remove the zone and its file,
|
|
* and if any action happened, ask for bind RECONFIG at posttime
|
|
* @NOTE launched as ROOT
|
|
*/
|
|
function hook_updatedomains_dns_del($dominfo) {
|
|
$domain = $dominfo["domaine"];
|
|
if (del_line_from_file(
|
|
$this->NAMED_CONF,
|
|
trim(strtr(
|
|
file_get_contents($this->NAMED_TEMPLATE),
|
|
array(
|
|
"@@DOMAIN@@" => $domain,
|
|
"@@ZONE_FILE@@" => $this->zone_file_directory."/".$domain
|
|
)
|
|
)))
|
|
) {
|
|
$this->shouldreconfig=true;
|
|
} else {
|
|
return;
|
|
}
|
|
@unlink($this->zone_file_directory."/".$domain);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
/**
|
|
* Hook function launched at the very end of updatedomains
|
|
* here, we just reload OR reconfig (or both) bind9 depending
|
|
* on what happened before.
|
|
* @NOTE launched as ROOT
|
|
*/
|
|
function hook_updatedomains_dns_post() {
|
|
global $msg;
|
|
if ($this->shouldreload) {
|
|
$ret=0;
|
|
exec($this->RNDC." reload 2>&1",$out,$ret);
|
|
if ($ret!=0) {
|
|
$msg->raise("ERROR","bind","Error while reloading bind, error code is $ret\n".implode("\n",$out));
|
|
} else {
|
|
$msg->raise("INFO","bind","Bind reloaded");
|
|
}
|
|
}
|
|
if ($this->shouldreconfig) {
|
|
$ret=0;
|
|
exec($this->RNDC." reconfig 2>&1",$out,$ret);
|
|
if ($ret!=0) {
|
|
$msg->raise("ERROR","bind","Error while reconfiguring bind, error code is $ret\n".implode("\n",$out));
|
|
} else {
|
|
$msg->raise("INFO","bind","Bind reconfigured");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
/**
|
|
* read a zone file for $domain,
|
|
* @param $domain string the domain name
|
|
* @return array with 3 informations:
|
|
* is the domain locked? (boolean), what's the current serial (integer), the data after alternc conf (string of lines)
|
|
*/
|
|
function read_zone($domain) {
|
|
$f=fopen($this->zone_file_directory."/".$domain,"rb");
|
|
$islocked=false;
|
|
$more="";
|
|
$serial=date("Ymd")."00";
|
|
while ($s=fgets($f,4096)) {
|
|
if (preg_match("#\;\s*LOCKED:YES#i",$s)) {
|
|
$islocked=true;
|
|
}
|
|
if (preg_match("/\s*(\d{10})\s+\;\sserial\s?/", $s,$mat)) {
|
|
$serial=$mat[1];
|
|
}
|
|
if (preg_match('/\;\s*END\sALTERNC\sAUTOGENERATE\sCONFIGURATION(.*)/s', $s)) {
|
|
break;
|
|
}
|
|
}
|
|
while ($s=fgets($f,4096)) {
|
|
$more.=$s;
|
|
}
|
|
return array($islocked,$serial,$more);
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------
|
|
/**
|
|
* Return the part of the conf we got from the sub_domaines table
|
|
* @global m_mysql $db
|
|
* @param string $domain
|
|
* @return string a zonefile excerpt
|
|
*/
|
|
function conf_from_db($domain) {
|
|
global $db;
|
|
$db->query("
|
|
SELECT
|
|
REPLACE(REPLACE(dt.entry,'%TARGET%',sd.valeur), '%SUB%', if(length(sd.sub)>0,sd.sub,'@')) AS ENTRY
|
|
FROM
|
|
sub_domaines sd,
|
|
domaines_type dt
|
|
WHERE
|
|
sd.type=dt.name
|
|
AND sd.enable IN ('ENABLE', 'ENABLED')
|
|
ORDER BY ENTRY ;");
|
|
$t="";
|
|
while ($db->next_record()) {
|
|
$t.= $db->f('ENTRY')."\n";
|
|
}
|
|
return $t;
|
|
}
|
|
|
|
|
|
} // m_bind
|
|
|