Merge remote-tracking branch 'upstream/master' into dnssec

These two files were deleted in upstream/master and I've left them.

  * bureau/class/class_system_bind.php
  * src/functions_dns.sh
This commit is contained in:
Kienan Stewart 2018-12-23 12:25:08 -05:00
commit 16e74d0175
52 changed files with 1262 additions and 1041 deletions

5
.gitignore vendored
View File

@ -41,3 +41,8 @@ bureau/locales/fr_FR/LC_MESSAGES/messages.po~
bureau/locales/it_IT/LC_MESSAGES/messages.po~
bureau/locales/nl_NL/LC_MESSAGES/messages.po~
bureau/locales/pt_BR/LC_MESSAGES/messages.po~
.tx/alternc.alternc
# Added for running tests; currently not used otherwise
composer.lock
composer.json
vendor/

View File

@ -2,14 +2,16 @@ language: php
services:
- mysql
php:
- 7.1
- 7.0
- 5.6
- 5.5
- 5.4
- 5.3
script: ../vendor/bin/phpunit --coverage-clover=coverage.clover
script:
- grep --exclude-dir=../.git/ --exclude-dir=../vendor/ -l -r -e '#!/bin/[bash|sh]' ../ | uniq | xargs shellcheck
- ../vendor/bin/phpcs --ignore=../vendor/ ../
- ../vendor/bin/phpunit --coverage-clover=coverage.clover
before_script:
- composer require phpunit/dbunit
- composer require 'phpunit/dbunit=<3.0.2' squizlabs/php_codesniffer
- mysql -e 'create database alternc_test DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;'
- cd phpunit
after_script:

View File

@ -48,7 +48,7 @@ install-common:
# Installer and upgrade scripts
test -d $(DESTDIR)/usr/share/alternc/install || mkdir -p $(DESTDIR)/usr/share/alternc/install
cp -r install/* $(DESTDIR)/usr/share/alternc/install
chmod a+x $(DESTDIR)/usr/share/alternc/install/alternc.install $(DESTDIR)/usr/share/alternc/install/dopo.sh $(DESTDIR)/usr/share/alternc/install/mysql.sh $(DESTDIR)/usr/share/alternc/install/newone.php $(DESTDIR)/usr/share/alternc/install/reset_root.php $(DESTDIR)/usr/share/alternc/install/upgrade_check.sh $(DESTDIR)/usr/share/alternc/install/upgrades/*.php $(DESTDIR)/usr/share/alternc/install/upgrades/*.sh
chmod a+x $(DESTDIR)/usr/share/alternc/install/alternc.install $(DESTDIR)/usr/share/alternc/install/dopo.sh $(DESTDIR)/usr/share/alternc/install/mysql.sh $(DESTDIR)/usr/share/alternc/install/newone.php $(DESTDIR)/usr/share/alternc/install/reset_root.php $(DESTDIR)/usr/share/alternc/install/upgrade_check.sh $(DESTDIR)/usr/share/alternc/install/upgrades/*.php $(DESTDIR)/usr/share/alternc/install/upgrades/*.sh $(DESTDIR)/usr/share/alternc/install/variables.php
# install AlternC itself:

View File

@ -76,7 +76,7 @@ if (isset($save) && $save) {
}
$addhead['css'][]='<link rel="stylesheet" href="/javascript/prettify/prettify.css" type="text/css" />';
$addhead['js'][]='<script src="/javascript/prettify/prettify.js" type="text/javascript"></script>'
$addhead['js'][]='<script src="/javascript/prettify/prettify.js" type="text/javascript"></script>';
include_once("head.php");
?>

View File

@ -130,8 +130,8 @@ $dom->unlock();
<select class="inl" name="https_<?php ehe($dt['name']); ?>" id="https_<?php ehe($dt['name']); ?>">
<option value="http"<?php selected((strtoupper($type)==strtoupper($dt['name']) && $sd["https"]=="http") || false); ?>><?php __("HTTP Only (redirect HTTPS to HTTP)"); ?></option>
<option value="https"<?php selected((strtoupper($type)==strtoupper($dt['name']) && $sd["https"]=="http") || true); ?>><?php __("HTTPS Only (redirect HTTP to HTTPS)"); ?></option>
<option value="both"<?php selected((strtoupper($type)==strtoupper($dt['name']) && $sd["https"]=="http") || false); ?>><?php __("Both HTTP and HTTPS hosted at the same place"); ?></option>
<option value="https"<?php selected((strtoupper($type)==strtoupper($dt['name']) && $sd["https"]=="https") || true); ?>><?php __("HTTPS Only (redirect HTTP to HTTPS)"); ?></option>
<option value="both"<?php selected((strtoupper($type)==strtoupper($dt['name']) && $sd["https"]=="both") || false); ?>><?php __("Both HTTP and HTTPS hosted at the same place"); ?></option>
</select>
<?php } ?>
</td>
@ -147,7 +147,7 @@ $dom->unlock();
}
?></button>
<?php if ($isedit) { ?>
<button class="inb cancel" name="cancel" onclick="document.location = 'dom_edit.php?domain=<?php echo $domain; ?>'"><?php __("Cancel"); ?></button>
<button class="inb cancel" type="button" name="cancel" onclick="document.location = 'dom_edit.php?domain=<?php echo $domain; ?>'"><?php __("Cancel"); ?></button>
<?php } ?>
</td>
</tr>

View File

@ -199,7 +199,6 @@ if (!$r["sub"][$i]["only_dns"]) {
__("HTTP and HTTPS");
break;
default:
__("Unknown");
break;
}
}

View File

@ -39,7 +39,7 @@ if (!defined("ALTERNC_PANEL")) exit(); // must be included ;)
if (file_exists("styles/style-custom.css") ) {
echo '<link rel="stylesheet" href="styles/style-custom.css" type="text/css" />';
}
if (count($addhead['css'])) {
if (isset($addhead) && count($addhead['css'])) {
foreach($addhead['css'] as $css) echo $css."\n";
}
$favicon = variable_get('favicon', 'favicon.ico' ,'You can specify a favicon, for example /images/my_logo.ico', array('desc'=>'URL','type'=>'string'));
@ -53,7 +53,7 @@ $favicon = variable_get('favicon', 'favicon.ico' ,'You can specify a favicon, fo
<script src="/javascript/jquery-ui/jquery-ui.min.js" type="text/javascript"></script>
<script src="/javascript/jquery-tablesorter/jquery.tablesorter.min.js" type="text/javascript"></script>
<?php
if (count($addhead['js'])) {
if (isset($addhead) && count($addhead['js'])) {
foreach($addhead['js'] as $js) echo $js."\n";
}
?>

View File

@ -242,6 +242,26 @@ class DB_Sql {
return $data;
}
/* pdo equivalent of fetch() */
function fetch($mode=PDO::FETCH_ASSOC) {
if (!$this->pdo_query) {
$this->halt("next_record called with no query pending.");
return FALSE;
}
$data = $this->pdo_query->fetch($mode);
$this->Errno = $this->pdo_query->errorCode();
$this->Error = $this->pdo_query->errorInfo();
if ($data == FALSE) {
if ($this->Auto_Free)
$this->free();
return FALSE;
}
return $data;
}
/**
* table locking
*/

View File

@ -1277,3 +1277,54 @@ function _dovecot_hash($password) {
$hash = _sha512cr($password);
return '{SHA512-CRYPT}' . $hash;
}
// ------------------------------------------------------------
/**
* Add the line of text $line into file $file.
* do not duplicate (check)
* @param $file string the full path to the file where we should add the line
* @param $line string the line to add (without the termination \n, WILL BE ADDED)
* @return boolean TRUE if the line has been added, or FALSE if the line ALREADY EXISTED
*/
function add_line_to_file($file,$line) {
$f=fopen($file,"rb");
$found=false;
while($s=fgets($f,1024)) {
if (trim($s)==$line) {
$found=true;
return false;
}
}
fclose($f);
$f=fopen($file,"ab");
fputs($f,trim($line)."\n");
fclose($f);
return true;
}
// ------------------------------------------------------------
/**
* Remove the line of text $line from file $file.
* @param $file string the full path to the file where we should remove the line
* @param $line string the line to add (without the termination \n, WILL BE REMOVED)
* @return boolean TRUE if the line has been found and removed, or FALSE if the line DIDN'T EXIST
*/
function del_line_from_file($file,$line) {
$f=fopen($file,"rb");
$g=fopen($file.".new","wb");
$found=false;
while($s=fgets($f,1024)) {
if (trim($s)!=$line) {
fputs($g,$s);
} else {
$found=true;
}
}
fclose($f);
fclose($g);
rename($file.".new",$file); // overwrite atomically
return $found;
}

View File

@ -241,7 +241,7 @@ class m_action {
* @global m_messages $msg
* @global m_mysql $db
* @param type $all
* @return boolean
* @return boolean|int The number of rows purged; False is there was an error
*/
function purge($all = null) {
global $msg, $db;

185
bureau/class/m_apache.php Normal file
View File

@ -0,0 +1,185 @@
<?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 APACHE 2.4+ vhosts templates in AlternC 3.5+
*
* @copyright AlternC-Team 2000-2018 https://alternc.com/
*/
class m_apache {
var $shouldreload;
// only values allowed for https in subdomaines table.
var $httpsmodes=array("http","https","both");
// Slave AlternC instances can know the last reload time thanks to this
var $reloadfile="/run/alternc/apache-reload";
// Where do we find apache template files ?
var $templatedir="/etc/alternc/templates/apache2";
// Where do we store all Apache vhosts ?
var $vhostroot="/var/lib/alternc/apache-vhost/";
// launched before any action by updatedomains
function hook_updatedomains_web_pre() {
$this->shouldreload=false;
}
// launched for each FQDN for which we want a new vhost template
function hook_updatedomains_web_add($subdomid) {
global $msg,$db,$ssl,$L_FQDN;
$db->query("SELECT sd.*, dt.only_dns, dt.has_https_option, m.login FROM domaines_type dt, sub_domaines sd LEFT JOIN membres m ON m.uid=sd.compte WHERE dt.name=sd.type AND sd.web_action!='OK' AND id=?;",array($subdomid));
$db->next_record();
$subdom=$db->Record;
// security : only AlternC account's UIDs
if ($subdom["compte"]<1999) {
$msg->raise("ERROR","apache","Subdom ".$subdom["id"]." for domain ".$subdom["sub"].".".$subdom["domaine"]." has id ".$subdom["compte"].". Skipped");
return 1;
}
// search for the template file:
$template = $this->templatedir."/".strtolower($subdom["type"]);
if ($subdom["has_https_option"] && in_array($subdom["https"],$this->httpsmodes)) {
$template.="-".$subdom["https"];
}
$template.=".conf";
if (!is_file($template)) {
$msg->raise("ERROR","apache","Template $template not found for subdom ".$subdom["id"]." for domain ".$subdom["sub"].".".$subdom["domaine"].". Skipped");
return 1;
}
$subdom["fqdn"]=$subdom["sub"].(($subdom["sub"])?".":"").$subdom["domaine"];
// SSL information $subdom["certificate_id"] may be ZERO => it means "take id 0 which is snakeoil cert"
$cert = $ssl->get_certificate_path($subdom["certificate_id"]);
if ($cert["chain"]) {
$chainline="SSLCertificateChainFile ".$cert["chain"];
} else {
$chainline="";
}
// Replace needed vars in template file
$tpl=file_get_contents($template);
$tpl = strtr($tpl, array(
"%%LOGIN%%" => $subdom['login'],
"%%fqdn%%" => $subdom['fqdn'],
"%%document_root%%" => getuserpath($subdom['login']) . $subdom['valeur'],
"%%account_root%%" => getuserpath($subdom['login']),
"%%redirect%%" => $subdom['valeur'],
"%%UID%%" => $subdom['compte'],
"%%GID%%" => $subdom['compte'],
"%%mail_account%%" => $subdom['login']."@".$L_FQDN,
"%%user%%" => "FIXME",
"%%CRT%%" => $cert["cert"],
"%%KEY%%" => $cert["key"],
"%%CHAINLINE%%" => $chainline,
));
// and write the template
$confdir = $this->vhostroot."/".substr($subdom["compte"],-1)."/".$subdom["compte"];
@mkdir($confdir,0755,true);
file_put_contents($confdir."/".$subdom["fqdn"].".conf",$tpl);
$this->shouldreload=true;
return 0; // shell meaning => OK ;)
} // hook_updatedomains_web_add
// ------------------------------------------------------------
/**
* launched for each FQDN for which we want to delete a vhost template
*/
function hook_updatedomains_web_del($subdomid) {
global $db,$msg;
$db->query("SELECT sd.*, dt.only_dns, dt.has_https_option, m.login FROM domaines_type dt, sub_domaines sd LEFT JOIN membres m ON m.uid=sd.compte WHERE dt.name=sd.type AND sd.web_action!='OK' AND id=?;",array($subdomid));
$db->next_record();
$subdom=$db->Record;
$confdir = $this->vhostroot."/".substr($subdom["compte"],-1)."/".$subdom["compte"];
$deleteme= $subdom["sub"].(($subdom["sub"])?".":"").$subdom["domaine"].".conf";
@unlink($confdir."/".$deleteme);
$this->shouldreload=true;
}
// ------------------------------------------------------------
/**
* launched at the very end of updatedomains
*/
function hook_updatedomains_web_post() {
global $msg;
if ($this->shouldreload) {
// concatenate all files into one
$this->concat();
// reload apache
$ret=0;
exec("apache2ctl graceful 2>&1",$out,$ret);
touch($this->reloadfile);
if ($ret!=0) {
$msg->raise("ERROR","apache","Error while reloading apache, error code is $ret\n".implode("\n",$out));
} else {
$msg->raise("INFO","apache","Apache reloaded");
}
}
}
// ------------------------------------------------------------
/**
* Concatenate all files under $this->vhostroot
* into one (mindepth=2 though),
* this function is faster than any shell stuff :D
*/
private function concat() {
global $msg;
$d=opendir($this->vhostroot);
$f=fopen($this->vhostroot."/vhosts_all.conf.new","wb");
if (!$f) {
$msg->raise("FATAL","apache","Can't write vhosts_all file");
return false;
}
while (($c=readdir($d))!==false) {
if (substr($c,0,1)!="." && is_dir($this->vhostroot."/".$c)) {
$this->subconcat($f,$this->vhostroot."/".$c);
}
}
closedir($d);
fclose($f);
rename($this->vhostroot."/vhosts_all.conf.new", $this->vhostroot."/vhosts_all.conf");
}
private function subconcat($f,$root) {
// recursive cat :)
$d=opendir($root);
while (($c=readdir($d))!==false) {
if (substr($c,0,1)!=".") {
if (is_dir($root."/".$c)) {
$this->subconcat($f,$root."/".$c); // RECURSIVE CALL
}
if (is_file($root."/".$c)) {
fputs($f,file_get_contents($root."/".$c)."\n");
}
}
}
closedir($d);
}
} // m_apache

238
bureau/class/m_bind.php Normal file
View File

@ -0,0 +1,238 @@
<?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

View File

@ -54,15 +54,7 @@ class m_dom {
* du domaine par update_domains.sh
* @access private
*/
var $fic_lock_cron = "/run/alternc/cron.lock";
/**
* Le cron a-t-il été bloqué ?
* Il faut appeler les fonctions privées lock et unlock entre les
* appels aux domaines.
* @access private
*/
var $islocked = false;
const fic_lock_cron = "/run/alternc/cron.lock";
var $type_local = "VHOST";
var $type_url = "URL";
@ -84,9 +76,10 @@ class m_dom {
* Constructeur
*/
function m_dom() {
global $L_FQDN;
global $L_FQDN, $domislocked;
$this->tld_no_check_at_all = variable_get('tld_no_check_at_all', 0, 'Disable ALL check on the TLD (users will be able to add any domain)', array('desc' => 'Disabled', 'type' => 'boolean'));
variable_get('mailname_bounce', $L_FQDN, 'FQDN of the mail server, used to create vhost virtual mail_adress.', array('desc' => 'FQDN', 'type' => 'string'));
$domislocked=false;
}
@ -642,35 +635,35 @@ class m_dom {
* @param string $dom nom de domaine é effacer
* @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
*/
function del_domain($dom) {
function del_domain($domain) {
global $db, $msg, $hooks;
$msg->log("dom", "del_domain", $dom);
$dom = strtolower($dom);
$msg->log("dom", "del_domain", $domain);
$domain = strtolower($domain);
$this->lock();
if (!$r = $this->get_domain_all($dom)) {
if (!$r = $this->get_domain_all($domain)) {
return false;
}
$this->unlock();
// Call Hooks to delete the domain and the MX management:
// TODO : the 2 calls below are using an OLD hook call, FIXME: remove them when unused
$hooks->invoke("alternc_del_domain", array($dom));
$hooks->invoke("alternc_del_mx_domain", array($dom));
$hooks->invoke("alternc_del_domain", array($domain));
$hooks->invoke("alternc_del_mx_domain", array($domain));
// New hook calls:
$hooks->invoke("hook_dom_del_domain", array($r["id"]));
$hooks->invoke("hook_dom_del_mx_domain", array($r["id"]));
// Now mark the domain for deletion:
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ?;", array($dom));
$this->set_dns_action($dom, 'DELETE');
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ?;", array($domain));
$this->set_dns_action($domain, 'DELETE');
return true;
}
function domshort($dom, $sub = "") {
return str_replace("-", "", str_replace(".", "", empty($sub) ? "" : "$sub.") . $dom);
function domshort($domain, $sub = "") {
return str_replace("-", "", str_replace(".", "", empty($sub) ? "" : "$sub.") . $domain);
}
@ -694,11 +687,11 @@ class m_dom {
* @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
*/
function add_domain($domain, $dns, $noerase = false, $force = false, $isslave = false, $slavedom = "") {
global $db, $msg, $quota, $L_FQDN, $tld, $cuid, $hooks;
global $db, $msg, $quota, $L_FQDN, $tld, $cuid, $hooks, $domislocked;
$msg->log("dom", "add_domain", $domain);
// Locked ?
if (!$this->islocked) {
if (!$domislocked) {
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
return false;
}
@ -1037,10 +1030,10 @@ class m_dom {
*
*/
function get_domain_all($dom) {
global $db, $msg, $cuid;
global $db, $msg, $cuid, $domislocked;
$msg->debug("dom", "get_domain_all", $dom);
// Locked ?
if (!$this->islocked) {
if (!$domislocked) {
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
return false;
}
@ -1077,13 +1070,14 @@ class m_dom {
$db->query("SELECT sd.*, dt.description AS type_desc, dt.only_dns, dt.advanced, dt.has_https_option FROM sub_domaines sd LEFT JOIN domaines_type dt on UPPER(dt.name)=UPPER(sd.type) WHERE compte= ? AND domaine= ? ORDER BY dt.advanced,sd.sub,sd.type ;", array($cuid, $dom));
// Pas de webmail, on le cochera si on le trouve.
$r["sub"] = array();
$data = $db->fetchAll();
foreach($data as $i=>$record) {
$i=0;
while ($record=$db->fetch()) {
$r["sub"][$i] = $record;
// FIXME : replace sub by name and dest by valeur in the code that exploits this function :
$r["sub"][$i]["name"] = $record["sub"];
$r["sub"][$i]["dest"] = $record["valeur"];
$r["sub"][$i]["fqdn"] = ((!empty($r["sub"][$i]["name"])) ? $r["sub"][$i]["name"] . "." : "") . $r["name"];
$i++;
}
$db->free();
return $r;
@ -1103,10 +1097,10 @@ class m_dom {
* Retourne FALSE si une erreur s'est produite.
*/
function get_sub_domain_all($sub_domain_id) {
global $db, $msg, $cuid;
global $db, $msg, $cuid, $domislocked;
$msg->debug("dom", "get_sub_domain_all", $sub_domain_id);
// Locked ?
if (!$this->islocked) {
if (!$domislocked) {
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
return false;
}
@ -1268,10 +1262,10 @@ class m_dom {
* @return boolean true if the preference has been set
*/
function set_subdomain_ssl_provider($sub_domain_id,$provider) {
global $db, $msg, $cuid, $ssl;
global $db, $msg, $cuid, $ssl, $domislocked;
$msg->log("dom", "set_sub_domain_ssl_provider", $sub_domain_id." / ".$provider);
// Locked ?
if (!$this->islocked) {
if (!$domislocked) {
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
return false;
}
@ -1313,13 +1307,14 @@ class m_dom {
* de $type (url, ip, dossier...)
* @param string $https the HTTPS behavior : HTTP(redirect https to http),
* HTTPS(redirect http to https) or BOTH (both hosted at the same place)
* or nothing "" when not applicable for this domain type.
* @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
*/
function set_sub_domain($dom, $sub, $type, $dest, $sub_domain_id = 0, $https) {
global $db, $msg, $cuid, $bro;
function set_sub_domain($dom, $sub, $type, $dest, $sub_domain_id = 0, $https="") {
global $db, $msg, $cuid, $bro, $domislocked;
$msg->log("dom", "set_sub_domain", $dom . "/" . $sub . "/" . $type . "/" . $dest);
// Locked ?
if (!$this->islocked) {
if (!$domislocked) {
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
return false;
}
@ -1401,10 +1396,10 @@ class m_dom {
*
*/
function del_sub_domain($sub_domain_id) {
global $db, $msg;
global $db, $msg, $domislocked;
$msg->log("dom", "del_sub_domain", $sub_domain_id);
// Locked ?
if (!$this->islocked) {
if (!$domislocked) {
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
return false;
}
@ -1449,11 +1444,11 @@ class m_dom {
* TRUE sinon.
*
*/
function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 86400, $dnssec = FALSE) {
global $db, $msg, $hooks;
function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 3600, $dnssec = FALSE) {
global $db, $msg, $hooks, $domislocked;
$msg->log("dom", "edit_domain", $dom . "/" . $dns . "/" . $gesmx);
// Locked ?
if (!$this->islocked && !$force) {
if (!$domislocked && !$force) {
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
return false;
}
@ -1857,15 +1852,20 @@ class m_dom {
* @access private
*/
function lock() {
global $msg;
global $msg,$domislocked;
$msg->debug("dom", "lock");
if ($this->islocked) {
if ($domislocked) {
$msg->raise("ERROR", "dom", _("--- Program error --- Lock already obtained!"));
}
while (file_exists($this->fic_lock_cron)) {
// wait for the file to disappear, or at most 15min:
while (file_exists(m_dom::fic_lock_cron) && filemtime(m_dom::fic_lock_cron)>(time()-900)) {
clearstatcache();
sleep(2);
}
$this->islocked = true;
@touch(m_dom::fic_lock_cron);
$domislocked = true;
// extra safe :
register_shutdown_function(array("m_dom","unlock"),1);
return true;
}
@ -1875,13 +1875,15 @@ class m_dom {
* return true
* @access private
*/
function unlock() {
global $msg;
function unlock($isshutdown=0) {
global $msg,$domislocked;
$msg->debug("dom", "unlock");
if (!$this->islocked) {
if (!$isshutdown && !$domislocked) {
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
}
$this->islocked = false;
// don't use $this since we may be called by register_shutdown_function out of an object instance.
@unlink(m_dom::fic_lock_cron);
$domislocked = false;
return true;
}
@ -1984,196 +1986,100 @@ class m_dom {
/**
* Return an array with all the needed parameters to generate conf
* of a vhost.
* If no parameters, return the parameters for ALL the vhost.
* Optionnal parameters: id of the sub_domaines
* */
function generation_parameters($id = null, $only_apache = true) {
global $db, $msg;
$msg->log("dom", "generation_parameters");
$params = "";
/** 2016_05_18 : this comments was here before escaping the request... is there still something to do here ?
* // BUG BUG BUG FIXME
* // Suppression de comptes -> membres existe pas -> domaines a supprimer ne sont pas lister
* complex process to manage domain and subdomain updates
* Launched every minute by a cron as root
* should launch hooks for each domain or subdomain,
* so that apache & bind could do their job
*/
$query = "
select
sd.id as sub_id,
lower(sd.type) as type,
m.login,
m.uid as uid,
if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine) as fqdn,
concat_ws('@',m.login,v.value) as mail,
sd.valeur
from
sub_domaines sd left join membres m on sd.compte=m.uid,
variable v,
domaines_type dt
where
v.name='mailname_bounce'
and lower(dt.name) = lower(sd.type)";
$query_args = array();
if (!is_null($id) && intval($id) == $id) {
$query .= " AND sd.id = ? ";
array_push($query_args, intval($id));
}
if ($only_apache) {
$query .=" and dt.only_dns is false ";
function update_domains() {
global $db, $hooks;
if (posix_getuid()!=0) {
echo "FATAL: please lauch me as root\n";
exit();
}
$query .= "
order by
m.login,
sd.domaine,
sd.sub;";
$this->lock();
// fix in case we forgot to delete SUBDOMAINS before deleting a DOMAIN
$db->query("UPDATE sub_domaines sd, domaines d SET sd.web_action = 'DELETE' WHERE sd.domaine = d.domaine AND sd.compte=d.compte AND d.dns_action = 'DELETE';");
$db->query($query, $query_args);
$r = array();
// Search for things to do on DOMAINS:
$db->query("SELECT * FROM domaines WHERE dns_action!='OK';");
$alldoms=array();
while ($db->next_record()) {
$r[$db->Record['sub_id']] = $db->Record;
$alldoms[$db->Record["id"]]=$db->Record;
}
return $r;
}
/**
* Return an array with all informations of the domains_type
* used to generate Apache conf.
* Die if templates missing.
* Warning: an Apache domains_type must have 'only_dns' == TRUE
*
* */
function generation_domains_type() {
global $dom;
$d = array();
foreach ($dom->domains_type_lst() as $k => $v) {
if ($v['only_dns'] == true) {
continue;
}
if (!$j = file_get_contents(ALTERNC_APACHE2_GEN_TMPL_DIR . '/' . strtolower($k) . '.conf')) {
die("Error: missing file for $k");
}
$d[$k] = $v;
$d[$k]['tpl'] = $j;
}
return $d;
}
/**
* Launch old fashionned hooks as there was in AlternC 1.0
* @TODO: do we still need that?
*/
function generate_conf_oldhook($action, $lst_sub, $sub_obj = null) {
if (is_null($sub_obj)) {
$sub_obj = $this->generation_parameters(null, false);
}
if (!isset($lst_sub[strtoupper($action)]) || empty($lst_sub[strtoupper($action)])) {
return false;
}
$lst_by_type = $lst_sub[strtoupper($action)];
foreach ($lst_by_type as $type => $lid_arr) {
$script = "/etc/alternc/functions_hosting/hosting_" . strtolower($type) . ".sh";
if (!@is_executable($script)) {
continue;
}
foreach ($lid_arr as $lid) {
$o = $sub_obj[$lid];
$cmd = $script . " " . escapeshellcmd(strtolower($action)) . " ";
$cmd .= escapeshellcmd($o['fqdn']) . " " . escapeshellcmd($o['valeur']);
system($cmd);
}
} // foreach $lst_by_type
}
/**
* Generate apache configuration.
* Die if a specific FQDN have 2 vhost conf.
*
* */
function generate_apacheconf($p = null) {
// Get the parameters
$lst = $this->generation_parameters($p);
$gdt = $this->generation_domains_type();
// Initialize duplicate check
$check_dup = array();
$ret = '';
foreach ($lst as $p) {
// Check if duplicate
if (in_array($p['fqdn'], $check_dup)) {
die("Error: duplicate fqdn : " . $p['fqdn']);
// now launch hooks
if (count($alldoms)) {
$hooks->invoke("hook_updatedomains_dns_pre");
foreach($alldoms as $id=>$onedom) {
if ($onedom["gesdns"]==0 || $onedom["dns_action"]=="DELETE") {
$ret = $hooks->invoke("hook_updatedomains_dns_del",array($onedom));
} else {
$check_dup[] = $p['fqdn'];
$ret = $hooks->invoke("hook_updatedomains_dns_add",array($onedom));
}
// Get the needed template
$tpl = $gdt[$p['type']] ['tpl'];
// Replace needed vars
$tpl = strtr($tpl, array(
"%%LOGIN%%" => $p['login'],
"%%fqdn%%" => $p['fqdn'],
"%%document_root%%" => getuserpath($p['login']) . $p['valeur'],
"%%account_root%%" => getuserpath($p['login']),
"%%redirect%%" => $p['valeur'],
"%%UID%%" => $p['uid'],
"%%GID%%" => $p['uid'],
"%%mail_account%%" => $p['mail'],
"%%user%%" => "FIXME",
));
// Security check
if ($p['uid'] < 1999) { // if UID is not an AlternC uid
$ret.= "# ERROR: Sub_id: " . $p['sub_id'] . "- The uid seem to be dangerous\n";
continue;
if ($onedom["dns_action"]=="DELETE") {
$db->query("DELETE FROM domaines WHERE domaine=?;",array($onedom));
} else {
// we keep the highest result returned by hooks...
rsort($ret,SORT_NUMERIC); $returncode=$ret[0];
$db->query("UPDATE domaines SET dns_result=?, dns_action='OK' WHERE domaine=?;",array($returncode,$onedom["domaine"]));
}
// Return the conf
$ret.= "# Sub_id: " . $p['sub_id'] . "\n" . $tpl;
}
return $ret;
$hooks->invoke("hook_updatedomains_dns_post");
}
/**
* Return an array with the list of id of sub_domains waiting for an action
*/
function generation_todo() {
global $db, $msg;
$msg->debug("dom", "generation_todo");
$db->query("select id as sub_id, web_action, type from sub_domaines where web_action !='ok';");
$r = array();
// Search for things to do on SUB-DOMAINS:
$db->query("SELECT sd.*, dt.only_dns FROM domaines_type dt, sub_domaines sd WHERE dt.name=sd.type AND sd.web_action!='OK';");
$alldoms=array();
$ignore=array();
$delete=array();
while ($db->next_record()) {
$r[strtoupper($db->Record['web_action'])][strtoupper($db->Record['type'])][] = $db->f('sub_id');
// only_dns=1 => weird, we should not have web_action SET to something else than OK ... anyway, skip it
if ($db->Record["only_dns"]) {
if ($db->Record["web_action"]=="DELETE") {
$delete[]=$db->Record["id"];
} else {
$ignore[]=$db->Record["id"];
}
return $r;
} else {
$alldoms[$db->Record["id"]]=$db->Record;
}
}
foreach($delete as $id) {
$db->query("DELETE FROM sub_domaines WHERE id=?;",array($id));
}
foreach($ignore as $id) {
// @FIXME (unsure it's useful) maybe we could check that no file exist for this subdomain ?
$db->query("UPDATE sub_domaines SET web_action='OK' WHERE id=?;",array($id));
}
// now launch hooks
if (count($alldoms)) {
$hooks->invoke("hook_updatedomains_web_pre");
foreach($alldoms as $id=>$subdom) {
// is it a delete (DISABLED or DELETE)
if ($subdom["web_action"]=="DELETE" || strtoupper(substr($subdom["enable"],0,7))=="DISABLE") {
$ret = $hooks->invoke("hook_updatedomains_web_del",array($subdom["id"]));
} else {
$hooks->invoke("hook_updatedomains_web_before",array($subdom["id"])); // give a chance to get SSL cert before ;)
$ret = $hooks->invoke("hook_updatedomains_web_add",array($subdom["id"]));
$hooks->invoke("hook_updatedomains_web_after",array($subdom["id"]));
}
function subdomain_modif_are_done($sub_domain_id, $action) {
global $db;
$sub_domain_id = intval($sub_domain_id);
switch (strtolower($action)) {
case "delete":
$sql = "DELETE FROM sub_domaines WHERE id =$sub_domain_id;";
break;
default:
$sql = "UPDATE sub_domaines SET web_action='OK' WHERE id='$sub_domain_id'; ";
if ($subdom["web_action"]=="DELETE") {
$db->query("DELETE FROM sub_domaines WHERE id=?;",array($id));
} else {
// we keep the highest result returned by hooks...
rsort($ret,SORT_NUMERIC); $returncode=$ret[0];
$db->query("UPDATE sub_domaines SET web_result=?, web_action='OK' WHERE id=?;",array($returncode,$id));
}
$db->query($sql);
return true;
}
$hooks->invoke("hook_updatedomains_web_post");
}
$this->unlock();
}
@ -2187,15 +2093,8 @@ class m_dom {
}
function set_dns_result($domain, $dns_result) {
global $db;
$db->query("UPDATE domaines SET dns_result= ? WHERE domaine= ?; ", array($dns_result, $domain));
return true;
}
/**
* List if there is problems in the domains.
* List if there are problems on the domain.
* Problems can appear when editing domains type properties
*/
function get_problems($domain) {
@ -2252,6 +2151,8 @@ class m_dom {
_("Default mail server");
_("Default backup mail server");
_("AlternC panel access");
_("DKIM Key");
_("Email autoconfiguration");
}
} /* Class m_domains */

View File

@ -53,6 +53,11 @@ class m_hooks {
// existe on l'execute et on rajoute ce qu'elle a retourné dans
// un tableau
$val = array();
if (!$classes) {
// Leaving early if classes isn't set prevents PHP warnings.
// Happens frequently when running PHPUnit tests.
return $val;
}
foreach ($classes as $c) {
global $$c;
if (method_exists($$c, $hname)) {

View File

@ -99,8 +99,8 @@ class m_lxc implements vm {
}
}
$msg = serialize($params);
if (fwrite($fp, $msg . "\n") < 0) {
$message = serialize($params);
if (fwrite($fp, $message . "\n") < 0) {
$this->error[] = 'Unable to send data';
return FALSE;
}
@ -135,22 +135,22 @@ class m_lxc implements vm {
$pass = $pass ? $pass : $mem->user['pass'];
$uid = $uid ? $uid : $mem->user['uid'];
$msgg = array('action' => 'start', 'login' => $login, 'pass' => $pass, 'uid' => $uid);
$msgg['mysql_host'] = $mysql->dbus->Host;
$message = array('action' => 'start', 'login' => $login, 'pass' => $pass, 'uid' => $uid);
$message['mysql_host'] = $mysql->dbus->Host;
$res = $this->sendMessage($msgg);
$res = $this->sendMessage($message);
if ($res === FALSE) {
return $this->error;
} else {
$data = unserialize($res);
$error = (int) $data['error'];
$hostname = $data['hostname'];
$msg = $data['msg'];
$message = $data['msg'];
$date_start = 'NOW()';
$uid = $mem->user['uid'];
if ($error != 0) {
$msg->raise("ERROR", 'lxc', _($msg));
$msg->raise("ERROR", 'lxc', _($message));
return FALSE;
}
$db->query("INSERT INTO vm_history (ip,date_start,uid,serialized_object) VALUES (?, ?, ?, ?);", array($hostname, $date_start, $uid, $res));
@ -166,8 +166,8 @@ class m_lxc implements vm {
global $mem;
$login = $login ? $login : $mem->user['login'];
$msgg = array('action' => 'get', 'login' => $login);
$res = $this->sendMessage($msgg);
$message = array('action' => 'get', 'login' => $login);
$res = $this->sendMessage($message);
if (!$res) {
return FALSE;
}

View File

@ -466,12 +466,18 @@ ORDER BY
}
}
$db->query("SELECT domaine FROM domaines WHERE id= ? ;", array($dom_id));
if ($db->next_record()) {
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='txt' AND (sub='' AND valeur LIKE 'v=spf1 %') OR (sub='_dmarc' AND valeur LIKE 'v=dmarc1;%');", array($db->Record["domaine"]));
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND (type='defmx' OR type='defmx2');", array($db->Record["domaine"]));
$db->query("UPDATE domaines SET dns_action='UPDATE' WHERE id= ? ;", array($dom_id));
if (!$db->next_record()) {
return false;
}
$domain=$db->Record["domaine"];
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND (type='defmx' OR type='defmx2');", array($domain));
$this->del_dns_dmarc($domain);
$this->del_dns_spf($domain);
$this->del_dns_autoconf($domain);
$this->dkim_del($domain);
$db->query("UPDATE domaines SET dns_action='UPDATE' WHERE id= ? ;", array($dom_id));
return true;
}
@ -912,6 +918,7 @@ ORDER BY
}
// ------------------------------------------------------------
/**
* hook function called by AlternC when a domain is created for
* the current user account using the SLAVE DOMAIN feature
@ -928,6 +935,7 @@ ORDER BY
}
// ------------------------------------------------------------
/**
* hook function called by AlternC when a domain is created for
* the current user account
@ -937,7 +945,7 @@ ORDER BY
* @access private
*/
function hook_dom_add_mx_domain($domain_id) {
global $msg, $mem, $db;
global $msg, $mem, $db, $L_FQDN;
$msg->log("mail", "hook_dom_add_mx_domain", $domain_id);
$db->query("SELECT value FROM variable where name='mailname_bounce';");
@ -947,19 +955,23 @@ ORDER BY
}
$mailname = $db->f("value");
// set spf & dmarc for this domain
$db->query("SELECT domaine FROM domaines WHERE id= ?;", array($domain_id));
$db->query("SELECT domaine,compte FROM domaines WHERE id= ?;", array($domain_id));
if ($db->next_record()) {
$domaine=$db->Record["domaine"];
$compte=$db->Record["compte"];
$this->set_dns_autoconf($domaine,$compte);
if ($spf = variable_get("default_spf_value")) {
$this->set_dns_spf($db->Record["domaine"], $spf);
$this->set_dns_spf($domaine, $spf);
}
if ($dmarc = variable_get("default_dmarc_value")) {
$this->set_dns_dmarc($db->Record["domaine"], $dmarc);
$this->set_dns_dmarc($domaine, $dmarc);
}
}
return $this->create_alias($domain_id, 'postmaster', $mem->user['login'] . '@' . $mailname);
}
// ------------------------------------------------------------
/**
* hook function called by variables when a variable is changed
* @access private
@ -992,6 +1004,43 @@ ORDER BY
}
// ------------------------------------------------------------
/**
* Add dns entries for autodiscover / autoconf on the domain
*/
function set_dns_autoconf($domain,$uid=-1) {
global $db, $L_FQDN, $cuid;
$changed=false;
if ($uid==-1) $uid=$cuid;
$db->query("SELECT domaine,sub,type,valeur FROM sub_domaines WHERE domaine=? AND sub='autodiscover' AND type='autodiscover';",array($domain));
if (!$db->next_record()) {
$db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='autodiscover', type='autodiscover', valeur='';",array($domain,$uid));
$changed=true;
}
$db->query("SELECT domaine,sub,type,valeur FROM sub_domaines WHERE domaine=? AND sub='autoconfig' AND type='autodiscover';",array($domain));
if (!$db->next_record()) {
$db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='autoconfig', type='autodiscover', valeur='';",array($domain,$uid));
$changed=true;
}
if ($changed) {
$db->query("UPDATE domaines SET dns_action='UPDATE' WHERE domaine= ?;", array($domain));
}
return $changed;
}
// ------------------------------------------------------------
/**
* delete the autoconf / autodiscover vhosts when removing a domain as MX
*/
function del_dns_autoconf($domain) {
global $db, $L_FQDN, $cuid;
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='autodiscover' AND sub='autoconfig';", array($domain));
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='autodiscover' AND sub='autodiscover';", array($domain));
}
// ------------------------------------------------------------
/**
* Set or UPDATE the DNS record for the domain $dom(str) to be $spf
* account's login is current and if not it's $login.
@ -999,7 +1048,8 @@ ORDER BY
* @access private
*/
function set_dns_spf($domain, $spf, $previous = -1, $uid = -1, $login = -1) {
global $db, $cuid, $mem;
global $db, $cuid, $mem, $msg;
$msg->debug("mail","set_dns_spf($domain, $spf, $previous, $uid, $login)");
// defaults
if ($uid === -1) {
$uid = intval($cuid);
@ -1021,7 +1071,18 @@ ORDER BY
$db->query("UPDATE domaines SET dns_action='UPDATE' WHERE domaine= ?;", array($domain));
}
// ------------------------------------------------------------
/**
* delete the SPF entries in the sub_domaine table for a domain
* called by del_domain or del_mx_domain by hooks :
*/
function del_dns_spf($domain) {
global $db;
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='txt' AND sub='' AND valeur LIKE 'v=spf1 %';", array($domain));
}
// ------------------------------------------------------------
/**
* Set or UPDATE the DNS record for the domain $dom(str) to be $dmarc
* account's login is current and if not it's $login.
@ -1029,7 +1090,8 @@ ORDER BY
* @access private
*/
function set_dns_dmarc($domain, $dmarc, $previous = -1, $uid = -1, $login = -1) {
global $db, $cuid, $mem, $L_FQDN;
global $db, $cuid, $mem, $L_FQDN, $msg;
$msg->debug("mail","set_dns_dmarc($domain, $dmarc, $previous, $uid, $login)");
// defaults
if ($uid === -1) {
$uid = intval($cuid);
@ -1055,5 +1117,151 @@ ORDER BY
}
// ------------------------------------------------------------
/**
* delete the DMARC entries in the sub_domaine table for a domain
* called by del_domain or del_mx_domain by hooks :
*/
function del_dns_dmarc($domain) {
global $db;
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='txt' AND sub='' AND valeur LIKE 'v=dmarc1 %';", array($domain));
}
/** Manage DKIM when adding / removing a domain MX management */
var $shouldreloaddkim;
// ------------------------------------------------------------
/**
* Hook launched before doing anything dns-related
*/
function hook_updatedomains_dns_pre() {
global $db;
// for each domain where we don't have the MX or the DNS, remove the DKIM setup
$this->shouldreloaddkim=false;
$db->query("SELECT domaine,compte,gesdns,gesmx FROM domaines WHERE dns_action!='OK';");
$add=array();
$del=array();
while ($db->next_record()) {
if ($db->Record["gesdns"]==0 || $db->Record["gesmx"]==0) {
$del[]=$db->Record;
} else {
$add[]=$db->Record;
}
}
foreach($add as $domain) {
$this->dkim_add($domain["domaine"],$domain["compte"]);
}
foreach($del as $domain) {
$this->dkim_del($domain["domaine"]);
}
}
// ------------------------------------------------------------
/**
* Hook launched after doing anything dns-related
*/
function hook_updatedomains_dns_post() {
if ($this->shouldreloaddkim) {
exec("service opendkim reload");
$this->shouldreloaddkim=false;
}
}
// ------------------------------------------------------------
/**
* Add a domain into OpenDKIM configuration
*/
function dkim_add($domain,$uid) {
global $db;
$target_dir = "/etc/opendkim/keys/$domain";
// Create a dkim key when it's not already there :
if (!file_exists($target_dir.'/alternc.txt')) {
$this->shouldreloaddkim=true;
if (! is_dir($target_dir)) mkdir($target_dir); // create dir
// Generate the key, 1200 bits (better than 1024)
$old_dir=getcwd();
chdir($target_dir);
exec('opendkim-genkey -b 1200 -r -d '.escapeshellarg($domain).' -s "alternc" ');
chdir($old_dir);
// opendkim must be owner of the key
chown("$target_dir/alternc.private", 'opendkim');
chgrp("$target_dir/alternc.private", 'opendkim');
add_line_to_file("/etc/opendkim/KeyTable","alternc._domainkey.".$domain." ".$domain.":alternc:/etc/opendkim/keys/".$domain."/alternc.private");
add_line_to_file("/etc/opendkim/SigningTable",$domain." alternc._domainkey.".$domain);
}
// Search for the subdomain entry, if it's not already there, create it:
$db->query("SELECT id FROM sub_domaines WHERE domaine=? AND sub='alternc._domainkey';",array($domain));
if (!$db->next_record()) {
// Add subdomaine entry
$dkim_key=$this->dkim_get_entry($domain);
$db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='alternc._domainkey', type='dkim', valeur=?;",array($domain,$uid,$dkim_key));
// no need to do DNS_ACTION="UPDATE" => we are in the middle of a HOOK, so dns WILL BE reloaded for this domain
}
}
// ------------------------------------------------------------
/**
* Delete a domain from OpenDKIM configuration
*/
function dkim_del($domain) {
global $db;
$target_dir = "/etc/opendkim/keys/$domain";
if (file_exists($target_dir)) {
$this->shouldreloaddkim=true;
@unlink("$target_dir/alternc_private");
@unlink("$target_dir/alternc.txt");
@rmdir($target_dir);
del_line_from_file("/etc/opendkim/KeyTable","alternc._domainkey.".$domain." ".$domain.":alternc:/etc/opendkim/keys/".$domain."/alternc.private");
del_line_from_file("/etc/opendkim/SigningTable",$domain." alternc._domainkey.".$domain);
}
$db->query("DELETE FROM sub_domaines WHERE domaine=? AND sub='alternc._domainkey';",array($domain));
// No need to do DNS_ACTION="UPDATE" => we are in the middle of a HOOK
}
// ------------------------------------------------------------
/**
* return the content of the TXT information to be added into the DB for DKIM subdomains
* @param $domain string the name of the domain name
* @return string the TXT entry (without quotes)
* or false if an error occurred
**/
function dkim_get_entry($domain) {
global $msg;
$key=file_get_contents("/etc/opendkim/keys/".$domain."/alternc.txt");
// easy: monoline key
if (preg_match('#alternc._domainkey IN TXT "(.*)"#',$key,$mat)) {
return $mat[1];
} else {
// Need to parse a multiligne key:
$inkey=false; $result="";
$lines=explode("\n",$key);
foreach($lines as $line) {
if (preg_match('#alternc._domainkey\s+IN\s+TXT\s+\( "(.*)"#',$line,$mat)) {
$result.=$mat[1]; $inkey=true; continue;
}
if ($inkey && preg_match('#^\s*"(.*)"\s*\)#',$line,$mat)) {
$result.=$mat[1]; $inkey=false; break;
}
if ($inkey && preg_match('#^\s*"(.*)"\s*$#',$line,$mat)) {
$result.=$mat[1]; $inkey=true; continue;
}
}
if ($result)
return $result;
}
$msg->debug("mail","dkim_get_entry($domain) failed");
return false;
}
// @TODO hook after reloading DNS zones => if necessary, restart opendkim
} /* Class m_mail */

View File

@ -373,6 +373,33 @@ INSTR(CONCAT(sd.sub,IF(sd.sub!='','.',''),sd.domaine),'.')+1))=?
}
// -----------------------------------------------------------------
/** Return paths to certificate, key, and chain for a certificate
* given it's ID.
* @param $id integer the certificate by id
* @return array cert, key, chain (not mandatory) with full path.
*/
function get_certificate_path($id) {
global $db, $msg, $cuid;
$msg->log("ssl", "get_certificate_path",$id);
$id = intval($id);
$db->query("SELECT id FROM certificates WHERE id=?;",array($id));
if (!$db->next_record()) {
$msg->raise("ERROR","ssl", _("Can't find this Certificate"));
// Return cert 0 info :)
$id=0;
}
$chain=self::KEY_REPOSITORY."/".floor($id/1000)."/".$id.".chain";
if (!file_exists($chain))
$chain=false;
return array(
"cert" => self::KEY_REPOSITORY."/".floor($id/1000)."/".$id.".pem",
"key" => self::KEY_REPOSITORY."/".floor($id/1000)."/".$id.".key",
"chain" => $chain
);
}
// -----------------------------------------------------------------
/** Return all the valid certificates that can be used for a specific FQDN
* return the list of certificates by order of preference
@ -600,7 +627,7 @@ SELECT ?,?,?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?, ?, sslcsr FROM certificate
$s = file_get_contents($TARGET_FILE);
$s = str_replace("%%CRT%%", $cert["crt"], $s);
$s = str_replace("%%KEY%%", $cert["key"], $s);
if (isset($cert["sslchain"]) && $cert["sslchain"]) {
if (isset($cert["chain"]) && $cert["chain"]) {
$s = str_replace("%%CHAINLINE%%", "SSLCertificateChainFile " . $cert["chain"], $s);
} else {
$s = str_replace("%%CHAINLINE%%", "", $s);
@ -613,6 +640,34 @@ SELECT ?,?,?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?, ?, sslcsr FROM certificate
}
// -----------------------------------------------------------------
/** Launched by hosting_functions.sh launched by update_domaines.sh
* Action may be create/postinst/delete/enable/disable
* Change the template for this domain name to have the proper CERTIFICATE
* An algorithm determine the best possible certificate, which may be a BAD one
* (like a generic self-signed for localhost as a last chance)
*/
public function hook_updatedomains_web_before($subdomid) {
global $db, $msg, $dom;
$msg->log("ssl", "hook_updatedomains_web_before($subdomid)");
$db->query("SELECT sd.*, dt.only_dns, dt.has_https_option, m.login FROM domaines_type dt, sub_domaines sd LEFT JOIN membres m ON m.uid=sd.compte WHERE dt.name=sd.type AND sd.web_action!='OK' AND id=?;",array($subdomid));
$db->next_record();
$subdom=$db->Record;
$domtype=$dom->domains_type_get($subdom["type"]);
// the domain type must be a "dns_only=false" one:
if ($domtype["only_dns"]==true) {
return; // nothing to do : this domain type does not involve Vhosts
}
$subdom["fqdn"]=$subdom["sub"].(($subdom["sub"])?".":"").$subdom["domaine"];
list($cert) = $this->get_valid_certs($subdom["fqdn"], $subdom["provider"]);
$this->write_cert_file($cert);
// Edit certif_hosts:
$db->query("UPDATE sub_domaines SET certificate_id=? WHERE id=?;",array($cert["id"], $subdom["id"]));
}
// ----------------------------------------------------------------
/** Search for the best certificate for a user and a fqdn
* Return a hash with crt, key and maybe chain.
@ -627,7 +682,25 @@ SELECT ?,?,?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?, ?, sslcsr FROM certificate
// get the first good certificate:
list($cert) = $this->get_valid_certs($fqdn, $subdom["provider"]);
$this->write_cert_file($cert);
// we have the files, let's fill the output array :
$output=array(
"id" => $cert["id"],
"crt" => $CRTDIR . "/" . $cert["id"].".pem",
"key" => $CRTDIR . "/" . $cert["id"].".key",
);
if (file_exists($CRTDIR . "/" . $cert["id"].".chain")) {
$output["chain"] = $CRTDIR . "/" . $cert["id"].".chain";
}
return $output;
}
// -----------------------------------------------------------------
/** Write certificate file into KEY_REPOSITORY
* @param $cert array an array with ID sslcrt sslkey sslchain
*/
function write_cert_file($cert) {
// we split the certificates by 1000
$CRTDIR = self::KEY_REPOSITORY . "/" . floor($cert["id"]/1000);
@mkdir($CRTDIR,0750,true);
@ -659,16 +732,6 @@ SELECT ?,?,?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?, ?, sslcsr FROM certificate
chmod($CRTDIR . "/" . $cert["id"].".chain",0640);
}
}
// we have the files, let's fill the output array :
$output=array(
"id" => $cert["id"],
"crt" => $CRTDIR . "/" . $cert["id"].".pem",
"key" => $CRTDIR . "/" . $cert["id"].".key",
);
if (file_exists($CRTDIR . "/" . $cert["id"].".chain")) {
$output["chain"] = $CRTDIR . "/" . $cert["id"].".chain";
}
return $output;
}

View File

@ -1601,24 +1601,20 @@ msgid "Quit"
msgstr "Fermer"
#: ../admin/bro_main.php:73
#, fuzzy, php-format
msgid "The folder '%s' was successfully created"
msgstr "L'utilisateur %s a été effacée avec succès"
msgstr "Le dossier %s a été effacé avec succès"
#: ../admin/bro_main.php:79
#, fuzzy, php-format
msgid "The file '%s' was successfully created"
msgstr "L'Email a été modifié avec succès"
msgstr "Le fihier été créé avec succès"
#: ../admin/bro_main.php:94
#, fuzzy, php-format
msgid "The folder '%s' was successfully deleted"
msgstr "L'utilisateur %s a été effacée avec succès"
msgstr "Le dossier %s a été effacé avec succès"
#: ../admin/bro_main.php:96
#, fuzzy, php-format
msgid "The file '%s' was successfully deleted"
msgstr "L'adresse email %s a été effacée avec succès"
msgstr "Le fichier %s a été effacé avec succès"
#: ../admin/bro_main.php:102
#, php-format
@ -1663,39 +1659,32 @@ msgid "The file '%s' was successfully moved to '%s'"
msgstr "L'Email a été modifié avec succès"
#: ../admin/bro_main.php:145
#, fuzzy
msgid "The files / folders were successfully moved"
msgstr "Le répertoire protégé %s a été déprotégé avec succès"
msgstr "Les fichiers / répertoires %s ont été déplacé avec succès"
#: ../admin/bro_main.php:153
#, fuzzy, php-format
msgid "The folder '%s' was successfully renamed to '%s'"
msgstr "L'Email a été modifié avec succès"
msgstr "Le dossier '%s' a été renommé '%s' avec succès"
#: ../admin/bro_main.php:155
#, fuzzy, php-format
msgid "The file '%s' was successfully renamed to '%s'"
msgstr "L'Email a été modifié avec succès"
msgstr "Le fichier '%s' a été renommé '%s' avec succès"
#: ../admin/bro_main.php:157
#, fuzzy
msgid "The files / folders were successfully renamed"
msgstr "Le compte AlternC a été renouvelé avec succès"
msgstr "Les fichiers / répertoires ont été renommés avec succès"
#: ../admin/bro_main.php:162
#, fuzzy, php-format
msgid "The file '%s' was successfully uploaded"
msgstr "L'adresse email %s a été effacée avec succès"
msgstr "Le fichier '%s' a été téléversé avec succès"
#: ../admin/bro_main.php:167
#, fuzzy
msgid "The permissions were successfully set"
msgstr "L'Email a été modifié avec succès"
msgstr "Les permissions ont été appliquées avec succès"
#: ../admin/bro_main.php:175
#, fuzzy, php-format
msgid "The extraction of the file '%s' succeeded"
msgstr "Le mot de passe de l'utilisateur %s à été modifié avec succés"
msgstr "L'extraction du fichier '%s' a été effectuée avec succés"
#: ../admin/bro_main.php:180 ../class/m_bro.php:74
msgid "File browser"
@ -2713,12 +2702,10 @@ msgid "Folder %s is protected"
msgstr ""
#: ../admin/hta_doadduser.php:45
#, fuzzy, php-format
msgid "The user %s was added to the protected folder %s"
msgstr "Modification de l'utilisateur %s dans le répertoire protégé %s"
msgstr "L'utilisateur %s a été ajouté au répertoire protégé %s"
#: ../admin/hta_dodeluser.php:39
#, fuzzy, php-format
msgid "The user '%s' was successfully deleted"
msgstr "L'utilisateur %s a été effacée avec succès"
@ -4273,9 +4260,8 @@ msgid "Create this new MySQL user"
msgstr "Créer ce nouvel utilisateur MySQL"
#: ../admin/sql_users_del.php:38 ../class/m_mysql.php:770
#, fuzzy, php-format
msgid "The user '%s' has been successfully deleted"
msgstr "L'utilisateur %s a été effacée avec succès"
msgstr "L'utilisateur MySQL %s a été effacé avec succès"
#: ../admin/sql_users_del.php:49
msgid "MySQL users"
@ -4294,14 +4280,12 @@ msgid "Yes, delete the MySQL user"
msgstr "Oui, effacer cet utilisateur MySQL"
#: ../admin/sql_users_doadd.php:41 ../admin/sql_users_doadd.php:50
#, fuzzy, php-format
msgid "The user '%s' has been successfully created."
msgstr "L'utilisateur %s a été effacée avec succès"
msgstr "L'utilisateur %s a été ajouté avec succès"
#: ../admin/sql_users_dopassword.php:35
#, fuzzy, php-format
msgid "Password changed for user '%s'."
msgstr "Permettre le changement de mot de passe ?"
msgstr "Mot de passe changé pour l'utilisateur '%s'."
#: ../admin/sql_users_dorights.php:49
msgid "The rights has been successfully applied to the user"

View File

@ -11,11 +11,6 @@ LOGROTATE="/etc/logrotate.d/roundcube-core"
case "$1" in
configure)
# add alternc-roundcube user for php-itk special rights
if ! getent passwd alternc-roundcube; then
useradd -g nogroup -u 1996 alternc-roundcube -d /usr/share/roundcube
fi
# removed from 3.1 & 3.2 :
dpkg-statoverride --list /var/lib/roundcube/temp >/dev/null &&
dpkg-statoverride --remove /var/lib/roundcube/temp

View File

@ -14,8 +14,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 5 * * * alterncpanel /usr/lib/alternc/sqlbackup.sh -t daily
0 4 * * 0 alterncpanel /usr/lib/alternc/sqlbackup.sh -t weekly
# Every 5 minutes, spool waiting domain changes
*/5 * * * * root /usr/lib/alternc/update_domains.sh
# Every minute, spool waiting domain changes
* * * * * root /usr/lib/alternc/update_domains.php
# Every 5 minutes, do mails actions
*/5 * * * * root /usr/lib/alternc/update_mails.sh

View File

@ -42,8 +42,9 @@ case "$1" in
# corriger les permissions du chroot
mkdir -p /var/spool/postfix/var/run/saslauthd || true
if ! dpkg-statoverride --list /var/spool/postfix/var/run/saslauthd >/dev/null ; then
dpkg-statoverride --quiet --update --add root sasl 710 /var/spool/postfix/var/run/saslauthd || true
fi
db_get "alternc/alternc_mail"
VMAIL_HOME="$RET"

10
debian/control vendored
View File

@ -59,12 +59,13 @@ Depends: debianutils (>= 1.13.1)
, opendkim-tools
, dovecot-sieve
, dovecot-managesieved
, default-mysql-client
, default-mysql-client | mysql-client | mariadb-client
, php5-curl | php7.0-curl
, quota
, pwgen
, lsb-release
, ${misc:Depends}
Recommends: default-mysql-server
Recommends: default-mysql-server | mysql-server | mariadb-server
, ntp
, unzip
, bzip2
@ -148,8 +149,9 @@ Depends: debianutils (>= 1.13.1)
, opendkim-tools
, dovecot-sieve
, dovecot-managesieved
, default-mysql-client
, php5-curl
, default-mysql-client | mysql-client | mariadb-client
, php5-curl | php7.0-curl
, lsb-release
, ${misc:Depends}
Recommends:
quota

View File

@ -14,6 +14,7 @@ AssignUserId www-data www-data
Options +FollowSymLinks
AllowOverride None
Require all denied
Satisfy Any
</Directory>
#### End security parameters

View File

@ -5,10 +5,6 @@
DocumentRoot /usr/share/alternc/panel/admin
ServerName %%fqdn%%
# Mail autoconfig
ServerAlias autoconfig.*
ServerAlias autodiscover.*
RewriteEngine on
RewriteRule ^/admin/(.*) /$1 [R=301,L]
@ -17,20 +13,6 @@
RewriteEngine On
RewriteRule ^webmail /webmail-redirect.php [L]
# Mail autoconfig
RewriteRule ^/mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^/mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^/autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^/Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^/Autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule ^/autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule ^autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^Autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule ^autodiscover.xml$ mailautoconfig_outlook.php [L]
# will be used to define aliases such as /javascript /webmail /squirrelmail ...
IncludeOptional /etc/alternc/apache-panel.d/*.conf

View File

@ -0,0 +1,57 @@
<VirtualHost *:80>
DocumentRoot /usr/share/alternc/panel/admin
AssignUserId alterncpanel alterncpanel
SetEnv LOGIN "0000-panel"
ServerName %%fqdn%%
RewriteEngine On
# Mail autoconfig
RewriteRule ^/mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^/mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^/autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^/Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^/Autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule ^/autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule ^autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^Autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule ^autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule (.*) - [F]
</VirtualHost>
<VirtualHost *:443>
DocumentRoot /usr/share/alternc/panel/admin
AssignUserId alterncpanel alterncpanel
SetEnv LOGIN "0000-panel"
ServerName %%fqdn%%
RewriteEngine On
# Mail autoconfig
RewriteRule ^/mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^/mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
RewriteRule ^/autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^/Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^/Autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule ^/autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule ^autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
RewriteRule ^Autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule ^autodiscover.xml$ mailautoconfig_outlook.php [L]
RewriteRule (.*) - [F]
SSLEngine On
SSLCertificateFile %%CRT%%
SSLCertificateKeyFile %%KEY%%
%%CHAINLINE%%
</VirtualHost>

View File

@ -7,6 +7,7 @@
<Directory "%%document_root%%">
php_admin_value open_basedir "%%account_root%%:/usr/share/php/"
php_admin_value upload_tmp_dir %%account_root%%/tmp
php_admin_value sys_temp_dir %%account_root%%/tmp
php_admin_value sendmail_path '/usr/lib/alternc/sendmail "%%mail_account%%" '
php_admin_flag mail.add_x_header on
Options +MultiViews -FollowSymLinks +SymLinksIfOwnerMatch
@ -24,6 +25,7 @@
<Directory "%%document_root%%">
php_admin_value open_basedir "%%account_root%%:/usr/share/php/"
php_admin_value upload_tmp_dir %%account_root%%/tmp
php_admin_value sys_temp_dir %%account_root%%/tmp
php_admin_value sendmail_path '/usr/lib/alternc/sendmail "%%mail_account%%" '
php_admin_flag mail.add_x_header on
Options +MultiViews -FollowSymLinks +SymLinksIfOwnerMatch

View File

@ -10,6 +10,11 @@
RewriteCond %{REQUEST_FILENAME} !/.well-known/acme-challenge/
RewriteRule ^/(.*)$ http://%%fqdn%%/$1 [R=301,L]
SSLEngine On
SSLCertificateFile %%CRT%%
SSLCertificateKeyFile %%KEY%%
%%CHAINLINE%%
</Virtualhost>
<VirtualHost *:80>
@ -21,6 +26,7 @@
<Directory "%%document_root%%">
php_admin_value open_basedir "%%account_root%%:/usr/share/php/"
php_admin_value upload_tmp_dir %%account_root%%/tmp
php_admin_value sys_temp_dir %%account_root%%/tmp
php_admin_value sendmail_path '/usr/lib/alternc/sendmail "%%mail_account%%" '
php_admin_flag mail.add_x_header on
Options -MultiViews -FollowSymLinks +SymLinksIfOwnerMatch

View File

@ -20,6 +20,7 @@
<Directory "%%document_root%%">
php_admin_value open_basedir "%%account_root%%:/usr/share/php/"
php_admin_value upload_tmp_dir %%account_root%%/tmp
php_admin_value sys_temp_dir %%account_root%%/tmp
php_admin_value sendmail_path '/usr/lib/alternc/sendmail "%%mail_account%%" '
php_admin_flag mail.add_x_header on
Options +MultiViews -FollowSymLinks +SymLinksIfOwnerMatch

View File

@ -18,7 +18,7 @@ options {
auth-nxdomain no; # conform to RFC1035
allow-query { "internal"; };
allow-transfer { "allslaves"; };
allow-transfer { "allslaves"; "internal"; };
recursion no;
# DnsSec configuration. This is close to defaults for bind9.
@ -33,7 +33,7 @@ options {
acl "internal" {
{
127.0.0.1;
127.0.0.1; ::1;
};
};

View File

@ -5,6 +5,7 @@
acl "allslaves" {
{
127.0.0.1;
::1;
//AUTO-SLAVES//
};
};

View File

@ -1 +1 @@
zone "@@DOMAINE@@" { type master; file "@@ZONE_FILE@@"; allow-query { any; }; };
zone "@@DOMAIN@@" { type master; file "@@ZONE_FILE@@"; allow-query { any; }; };

View File

@ -14,3 +14,7 @@ KeyTable /etc/opendkim/KeyTable
SigningTable /etc/opendkim/SigningTable
ExternalIgnoreList /etc/opendkim/TrustedHosts
InternalHosts /etc/opendkim/TrustedHosts
# The value from /etc/default/opendkim doesn't seem to be taken into account
# @see https://bugs.debian.org/cgi-bin/bugreport.cgi?archive=no&bug=861169
Socket local:/var/run/opendkim/opendkim.sock

View File

@ -76,6 +76,14 @@ fi
. /usr/lib/alternc/functions.sh
# get the information on running Sysv or Systemd init & boot system
if [ -e /run/systemd/system ]
then
SYSTEMD=1
else
SYSTEMD=0
fi
# Lock the jobs !
lock_jobs
@ -91,7 +99,7 @@ TEMPLATE_DIR="/etc/alternc/templates"
# Find needed configuration files (without the initial '/')
# replace this one unconditionnally
CONFIG_FILES="etc/alternc/bureau.conf etc/apache2/envvars etc/alternc/apache2.conf etc/alternc/apache_logformat.conf etc/alternc/phpmyadmin.inc.php"
CONFIG_FILES="etc/alternc/bureau.conf etc/apache2/envvars etc/alternc/apache2.conf etc/alternc/phpmyadmin.inc.php"
if [ -e /etc/bind/named.conf ]; then
CONFIG_FILES="$CONFIG_FILES etc/bind/named.conf.options"
@ -112,7 +120,7 @@ if [ -e /etc/default/saslauthd ]; then
fi
if [ -e /etc/dovecot/dovecot.conf ]; then
CONFIG_FILES="$CONFIG_FILES etc/dovecot/alternc-sql.conf etc/dovecot/alternc-dict-quota.conf etc/dovecot/conf.d/95_alternc.conf"
CONFIG_FILES="$CONFIG_FILES etc/dovecot/alternc-sql.conf etc/dovecot/alternc-dict-quota.conf etc/dovecot/conf.d/95_alternc.conf etc/dovecot/conf.d/96_ssl.conf"
fi
INSTALLED_CONFIG_TAR="/var/lib/alternc/backups/etc-installed.tar.gz"
@ -354,9 +362,8 @@ do
fi
done
# ensure dovecot, postfix, apache, can access ssl certificates:
# ensure dovecot, postfix, can access ssl certificates:
adduser dovecot ssl-cert
adduser www-data ssl-cert
adduser postfix ssl-cert
run-parts --arg=certificates /usr/lib/alternc/install.d
@ -366,7 +373,6 @@ if [ -x /usr/sbin/apache2 ]; then
run-parts --arg=apache2 /usr/lib/alternc/install.d
a2enmod mpm_itk
s="apache2"
# unused from AlternC 1.0, FIXME: remove it later
if [ -L /etc/apache2/mods-enabled/vhost_alias.load ]
then
@ -394,7 +400,12 @@ if [ -x /usr/sbin/apache2 ]; then
a2enconf alternc-ssl
fi
SERVICES="$SERVICES $s"
if [ ! -h /etc/apache2/conf-available/alternc.conf ] && [ -e /etc/apache2/conf-available/ ]; then
ln -sf /etc/alternc/apache2.conf /etc/apache2/conf-available/alternc.conf
a2enconf alternc
fi
SERVICES="$SERVICES apache2"
fi
# Manage sudoers.d include appearing in Squeeze:
@ -592,6 +603,9 @@ fi
chmod 640 /var/log/alternc/bureau.log /var/log/alternc/update_domains.log
chown alterncpanel:adm /var/log/alternc/bureau.log /var/log/alternc/update_domains.log
# Launch a script that will populate AlternC variables as needed
su - alterncpanel -s /bin/bash -c /usr/share/alternc/install/variables.php
# Creating admin user if needed
HAS_ROOT=`mysql --defaults-file=/etc/alternc/my.cnf -e "SELECT COUNT(*) FROM membres WHERE login = 'admin' OR login = 'root' and su = 1" | tail -1`
@ -643,6 +657,16 @@ grep -q "^127.0.0.1\$" /etc/opendkim/TrustedHosts || echo "127.0.0.1" >>/etc/ope
grep -q "^localhost\$" /etc/opendkim/TrustedHosts || echo "localhost" >>/etc/opendkim/TrustedHosts
grep -q "^$PUBLIC_IP\$" /etc/opendkim/TrustedHosts || echo "$PUBLIC_IP" >>/etc/opendkim/TrustedHosts
if [ "$SYSTEMD" = "1" -a "$(lsb_release -s -c)" = "stretch" ] ; then
/lib/opendkim/opendkim.service.generate
# Without adding '-u opendkim' after the service file is generated, opendkim
# will run as root, which we do not want.
if [ "$(grep -c 'u opendkim' /etc/systemd/system/opendkim.service.d/override.conf)" == 0 ] ; then
sed -i -e 's/inet:8891@127.0.0.1/& -u opendkim/' /etc/systemd/system/opendkim.service.d/override.conf
fi
systemctl daemon-reload
fi
# Add opendkim to service to restart
SERVICES="$SERVICES opendkim bind9"

View File

@ -115,7 +115,7 @@ CREATE TABLE IF NOT EXISTS domaines (
noerase tinyint(4) NOT NULL default '0',
dns_action enum ('OK','UPDATE','DELETE') NOT NULL default 'UPDATE',
dns_result varchar(255) not null default '',
zonettl int(10) unsigned NOT NULL default '86400',
zonettl int(10) unsigned NOT NULL default '3600',
dnssec BOOLEAN NOT NULL DEFAULT FALSE,
dnssec_action ENUM ('OK', 'CREATE') NOT NULL DEFAULT 'OK',
ksk_algorithm ENUM ('NSEC3RSASHA1', 'NSEC3DSA', 'RSASHA256', 'RSASHA512', 'ECDSAP256SHA256', 'ECDSAP384SHA384') DEFAULT NULL,
@ -485,18 +485,20 @@ CREATE TABLE IF NOT EXISTS `domaines_type` (
PRIMARY KEY ( `name` )
) ENGINE=InnoDB COMMENT = 'Type of domains allowed';
INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable) values
('vhost', 'Locally hosted', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, false, false, 'ALL'),
('url', 'URL redirection', 'URL', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2', false, false, false, 'ALL'),
('ip', 'IPv4 redirect', 'IP', '%SUB% IN A %TARGET%', 'url,ip,ipv6,txt,mx,mx2,defmx,defmx2', true, true, false, 'ALL'),
('ipv6', 'IPv6 redirect', 'IPV6', '%SUB% IN AAAA %TARGET%', 'ip,ipv6,txt,mx,mx2,defmx,defmx2', true, true, true, 'ALL'),
('cname', 'CNAME DNS entry', 'DOMAIN', '%SUB% CNAME %TARGET%', '', true, true, true, 'ALL'),
('txt', 'TXT DNS entry', 'TXT', '%SUB% IN TXT "%TARGET%"', 'vhost,url,ip,ipv6,txt,mx,mx2,defmx,defmx2', true, true, true, 'ALL'),
('mx', 'MX DNS entry', 'DOMAIN', '%SUB% IN MX 5 %TARGET%', 'vhost,url,ip,ipv6,txt,mx,mx2', true, true, true, 'ALL'),
('mx2', 'secondary MX DNS entry', 'DOMAIN', '%SUB% IN MX 10 %TARGET%', 'vhost,url,ip,ipv6,txt,mx,mx2', true, true, true, 'ALL'),
('defmx', 'Default mail server', 'NONE', '%SUB% IN MX 5 @@DEFAULT_MX@@.', 'vhost,url,ip,ipv6,txt,defmx2', true, true, true, 'ADMIN'),
('defmx2', 'Default backup mail server', 'NONE', '%SUB% IN MX 10 @@DEFAULT_SECONDARY_MX@@.', 'vhost,url,ip,ipv6,txt,defmx', true, true, true, 'ADMIN'),
('panel', 'AlternC panel access', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'vhost,url,ip,ipv6,txt,mx,mx2,defmx,defmx2', false, false, true, 'ALL')
INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable,has_https_option) VALUES
('dkim', 'DKIM Key', 'TXT', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN', false),
('autodiscover', 'Email autoconfiguration', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, true, true, 'ADMIN', false),
('vhost', 'Locally hosted', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, false, false, 'ALL', true),
('url', 'URL redirection', 'URL', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2', false, false, false, 'ALL', false),
('ip', 'IPv4 redirect', 'IP', '%SUB% IN A %TARGET%', 'url,ip,ipv6,txt,mx,mx2,defmx,defmx2', true, true, false, 'ALL', false),
('ipv6', 'IPv6 redirect', 'IPV6', '%SUB% IN AAAA %TARGET%', 'ip,ipv6,txt,mx,mx2,defmx,defmx2', true, true, true, 'ALL', false),
('cname', 'CNAME DNS entry', 'DOMAIN', '%SUB% CNAME %TARGET%', '', true, true, true, 'ALL', false),
('txt', 'TXT DNS entry', 'TXT', '%SUB% IN TXT "%TARGET%"', 'vhost,url,ip,ipv6,txt,mx,mx2,defmx,defmx2', true, true, true, 'ALL', false),
('mx', 'MX DNS entry', 'DOMAIN', '%SUB% IN MX 5 %TARGET%', 'vhost,url,ip,ipv6,txt,mx,mx2', true, true, true, 'ALL', false),
('mx2', 'secondary MX DNS entry', 'DOMAIN', '%SUB% IN MX 10 %TARGET%', 'vhost,url,ip,ipv6,txt,mx,mx2', true, true, true, 'ALL', false),
('defmx', 'Default mail server', 'NONE', '%SUB% IN MX 5 @@DEFAULT_MX@@.', 'vhost,url,ip,ipv6,txt,defmx2', true, true, true, 'ADMIN', false),
('defmx2', 'Default backup mail server', 'NONE', '%SUB% IN MX 10 @@DEFAULT_SECONDARY_MX@@.', 'vhost,url,ip,ipv6,txt,defmx', true, true, true, 'ADMIN', false),
('panel', 'AlternC panel access', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'vhost,url,ip,ipv6,txt,mx,mx2,defmx,defmx2', false, false, true, 'ALL', false)
;
UPDATE domaines_type SET create_tmpdir=true, create_targetdir=true WHERE target='DIRECTORY';
@ -799,7 +801,6 @@ CREATE TABLE IF NOT EXISTS `certificates` (
-- make it re-exec-proof
DELETE FROM alternc_status WHERE name='alternc_version';
INSERT INTO alternc_status SET name='alternc_version',value='3.5.0.1.sql';
-- make it re-exec-proof -- BUT don't overwrite existing value !
INSERT IGNORE INTO alternc_status SET name='alternc_version',value='3.5.0.2.php';

View File

@ -1,13 +1,22 @@
-- upgrade from 3.4.10 and 3.4.11 (a bug prevented them to be inserted :/ )
-- migrating DKIM to be inside sub_domaines table
INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable) VALUES
('dkim', 'DKIM Key', 'TXT', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN');
-- migrating AUTODISCOVER / AUTOCONF to be inside sub_domaines table
INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable) VALUES
('autodiscover', 'Email autoconfiguration', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, true, true, 'ADMIN');
-- upgrade from 3.4.10 and 3.4.11 (a bug prevented them to be inserted :/ )
ALTER TABLE mailbox MODIFY `lastlogin` DATETIME NOT NULL DEFAULT 0;
ALTER TABLE mailbox ADD `lastloginsasl` DATETIME NOT NULL DEFAULT 0 AFTER `lastlogin`;
ALTER TABLE `domaines` MODIFY `zonettl` INT(10) UNSIGNED NOT NULL default '3600';
ALTER TABLE `membres` MODIFY `pass` varchar(255);
ALTER TABLE `ftpusers` MODIFY `encrypted_password` varchar(255);
-- upgrade to better hashes ($6$, 20000 loops) in membres and ftpusers
ALTER TABLE `membres` MODIFY `pass` VARCHAR(255);
ALTER TABLE `ftpusers` MODIFY `encrypted_password` VARCHAR(255);
-- upgrade to merge alternc-ssl into alternc + change the way we work on SSL
DROP TABLE IF EXISTS `certif_alias`;
ALTER TABLE `certificates`
@ -28,7 +37,8 @@ ALTER TABLE `domaines_type`
UPDATE `domaines_type` SET `has_https_option`=1 WHERE name='vhost';
-- Backport old certif_hosts data to sub_domaines
UPDATE `sub_domaines` LEFT JOIN `certif_hosts` ON `sub_domaines`.`id` = `certif_hosts`.`sub` SET `sub_domaines`.`certificate_id` = `certif_hosts`.`certif` WHERE 1;
UPDATE `sub_domaines` LEFT JOIN `certif_hosts` ON `sub_domaines`.`id` = `certif_hosts`.`sub`
SET `sub_domaines`.`certificate_id` = `certif_hosts`.`certif`;
DROP TABLE IF EXISTS `certif_hosts`;
-- Set https status (http,https,both)
@ -37,21 +47,22 @@ UPDATE `sub_domaines` SET `https` = "both" WHERE `type` LIKE '%-mixssl' AND http
UPDATE `sub_domaines` SET `https` = "http" WHERE https = '';
UPDATE `sub_domaines` SET `type` = REPLACE(`type`,'-ssl','');
UPDATE `sub_domaines` SET `type` = REPLACE(`type`,'-mixssl','');
-- Disable https status when domains_type don't provide this
UPDATE `sub_domaines` SET `https` = '' WHERE type IN (select name FROM domaines_type WHERE has_https_option = 0);
-- Disable https status when domains_type don't use it
UPDATE `sub_domaines` SET `https` = '' WHERE type IN (SELECT name FROM domaines_type WHERE has_https_option = 0);
-- When two sudomain exists, we consider sub_domains with http and https feature
-- When two subdomain exists, we consider sub_domains with http and https feature
UPDATE sub_domaines AS sd INNER JOIN
(SELECT MIN(id) id FROM `sub_domaines` GROUP BY domaine,sub,type HAVING count(id) > 1) sd1
ON sd.id = sd1.id
SET `https` = "both";
-- Delete duplicate lines
DELETE sd1 FROM sub_domaines sd1, sub_domaines sd2 WHERE sd1.id > sd2.id AND sd1.domaine = sd2.domaine AND sd1.sub = sd2.sub AND sd1.type = sd2.type AND sd1.https <> '' AND sd2.https <> '';
DELETE sd1 FROM sub_domaines sd1, sub_domaines sd2
WHERE sd1.id > sd2.id AND sd1.domaine = sd2.domaine AND sd1.sub = sd2.sub AND sd1.type = sd2.type
AND sd1.https <> '' AND sd2.https <> '';
-- we need to regenerate all vhost, they will be by AlternC.install
-- UPDATE `sub_domaines` SET `web_action` = 'UPDATE';
-- change some variable names :
UPDATE variable
@ -72,6 +83,6 @@ DELETE FROM variable WHERE name IN (
'ftp_human_name'
);
-- we'd like to prepare IPv6 ;)
-- we'd like to prepare for IPv6 ;)
ALTER TABLE `domaines_type` CHANGE `entry` `entry` TEXT DEFAULT '';

View File

@ -0,0 +1,33 @@
#!/usr/bin/php -q
<?php
// we don't check our AlternC session
if(!chdir("/usr/share/alternc/panel"))
exit(1);
require("/usr/share/alternc/panel/class/config_nochk.php");
$db->query("SELECT * FROM domaines WHERE gesdns=1 AND gesmx=1;");
$add=array();
while ($db->next_record()) {
$add[$db->Record["domaine"]]=$db->Record["compte"];
}
foreach($add as $domain => $id) {
// Convert DKIM keys into SUB_DOMAINES table
if (file_exists("/etc/opendkim/keys/".$domain."/alternc.txt")) {
$dkim_key = $mail->dkim_get_entry($domain);
if ($dkim_key) {
// Add subdomain dkim entry
$db->query("INSERT INTO sub_domaines
SET compte=?, domaine=?, sub='@', valeur=?, type='dkim', web_action='OK', web_result=0, enable='ENABLED';",
array($id, $domain, $dkim_key)
);
// Alternc.INSTALL WILL reload DNS zones anyway, so fear not we don't set dns_action="RELOAD" here.
}
}
// Convert autodiscover into SUB_DOMAINES table
$db->query("INSERT INTO sub_domaines
SET compte=?, domaine=?, sub='@', valeur='', type='autodiscover', web_action='UPDATE', web_result=0, enable='ENABLED';",
array($id, $domain)
);
}

17
install/variables.php Normal file
View File

@ -0,0 +1,17 @@
#!/usr/bin/php
<?php
/**
* This script set the required variables for AlternC at install time.
* only create missing variable, don't overwrite them
*/
// bootstrap
if(!chdir("/usr/share/alternc/panel"))
exit(1);
require("/usr/share/alternc/panel/class/config_nochk.php");
variable_set('default_spf_value','a mx ?all', 'This variable (if set) tells the SPF/TXT DNS field that will be published as a SPF entry, telling which server(s) are allowed to send email for this one. You can still change it later in the advanced DNS entries for ONE domain, this entry is only set once for new domains (or when you change it here).');
variable_set('default_dmarc_value', 'p=none;pct=100;rua=%%ADMINMAIL%%;aspf=r;adkim=r', 'This variable (if set) tells the DMARC/TXT DNS field that will be published as a DMARC entry, telling which policy you apply to this domain name. You can still change it later in the advanced DNS entries for ONE domain, this entry is only set once for new domains (or when you change it here). You can use %%ADMINMAIL%% or %%USERMAIL%% to substitute to admin-account or alternc user-account email address.');
// strict dmarc would be 'p=reject;pct=100;rua=%%ADMINMAIL%%;aspf=s;adkim=s'

View File

@ -5,6 +5,8 @@
*/
use PHPUnit\Framework\TestCase;
use PHPUnit\DbUnit\TestCaseTrait;
use PHPUnit\DbUnit\DataSet\YamlDataSet;
use PHPUnit\DbUnit\DataSet\CompositeDataSet;
abstract class AlterncTest extends TestCase
{
@ -40,10 +42,10 @@ abstract class AlterncTest extends TestCase
if( !is_file($file) ){
throw new \Exception("missing $file");
}
$dataSet = new PHPUnit_Extensions_Database_DataSet_YamlDataSet($file);
$dataSet = new YamlDataSet($file);
$datasetList[] = $dataSet;
}
$compositeDataSet = new PHPUnit_Extensions_Database_DataSet_CompositeDataSet($datasetList);
$compositeDataSet = new CompositeDataSet($datasetList);
return $dataSet;
}

View File

@ -174,7 +174,7 @@ class m_actionTest extends AlterncTest {
*/
public function testPurge() {
$result = $this->object->purge();
$this->assertEquals(0, $result);
$this->assertEquals(1, $result);
$expectedTable = $this->loadDataSet("actions-empty.yml")->getTable("actions");
$currentTable = $this->getConnection()->createQueryTable('actions', 'SELECT * FROM actions');
$this->assertTablesEqual($expectedTable, $currentTable);

View File

@ -690,101 +690,6 @@ class m_domTest extends TestCase
);
}
/**
* @covers m_dom::generation_parameters
* @todo Implement testGeneration_parameters().
*/
public function testGeneration_parameters()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers m_dom::generation_domains_type
* @todo Implement testGeneration_domains_type().
*/
public function testGeneration_domains_type()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers m_dom::generate_conf_oldhook
* @todo Implement testGenerate_conf_oldhook().
*/
public function testGenerate_conf_oldhook()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers m_dom::generate_apacheconf
* @todo Implement testGenerate_apacheconf().
*/
public function testGenerate_apacheconf()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers m_dom::generation_todo
* @todo Implement testGeneration_todo().
*/
public function testGeneration_todo()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers m_dom::subdomain_modif_are_done
* @todo Implement testSubdomain_modif_are_done().
*/
public function testSubdomain_modif_are_done()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers m_dom::set_dns_action
* @todo Implement testSet_dns_action().
*/
public function testSet_dns_action()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers m_dom::set_dns_result
* @todo Implement testSet_dns_result().
*/
public function testSet_dns_result()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @covers m_dom::get_problems

View File

@ -320,6 +320,9 @@ class m_mailTest extends AlterncTest
public function testCreate_alias()
{
// Test #1580
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**

View File

@ -81,9 +81,8 @@ EOF
fi
if [ "$1" = "end" ]; then
# This is necessary because upgrading roundcube from 7.1 to 7.2 changes this setting
chown alternc-roundcube:root /etc/roundcube/config.inc.php
# In case owner is reset to www-data
chown alternc-roundcube:nogroup /var/lib/roundcube/temp
# Roundcube vhosts run as www-data instead of alternc-roundcube now.
# Ensure the configuration is owned by the appropriate user.
chown www-data:root /etc/roundcube/config.inc.php
chown www-data:nogroup /var/lib/roundcube/temp
fi

View File

@ -37,20 +37,19 @@
<Directory /var/lib/roundcube/config>
Options -FollowSymLinks
AllowOverride None
Require all denied
</Directory>
<Directory /var/lib/roundcube/temp>
Options -FollowSymLinks
AllowOverride None
Order allow,deny
Deny from all
Require all denied
</Directory>
<Directory /var/lib/roundcube/logs>
Options -FollowSymLinks
AllowOverride None
Order allow,deny
Deny from all
Require all denied
</Directory>
Alias /javascript /usr/share/javascript/

View File

@ -22,50 +22,58 @@
# Purpose of file: Fix permission, ACL and ownership of AlternC's files
# ----------------------------------------------------------------------
#
red () { echo -e "\e[31m$@ \e[0m" ; }
usage () {
[[ -n "$@" ]] && red "$@\n"
cat<<End-of-message
Four optionals argument to chose from
-l string : a specific login to fix
-u integer : a specific uid to fix
-f string : a specific file to fix according to a given uid
-d string : a specific subdirectory to fix according to a given uid
# four optionals argument to chose from
# -l string : a specific login to fix
# -u integer : a specific uid to fix
# -f string : a specific file to fix according to a given uid
# -d string : a specific subdirectory to fix according to a given uid
# The u and l switch are used to fix a given user whole directory including his base directory ($ALTERNC_HTML/<letter>/<login>/
# The f and d switch are used to fix a given file or directory under the user's base directory. They use the base directory to get the permissions they should use.
# Be sure to have correct base directory permissions before attemplting to fix use those two switch
The u and l switch are used to fix a given user whole directory including his base directory ($ALTERNC_HTML/<letter>/<login>/
The f and d switch are used to fix a given file or directory under the user's base directory. They use the base directory to get the permissions they should use.
Be sure to have correct base directory permissions before attemplting to fix use those two switch
End-of-message
exit 1
}
query="SELECT uid,login FROM membres ORDER BY login"
sub_dir=""
file=""
LOCK_FIXPERMS="/etc/alternc/disable_all_fixperms"
if [ -f "$LOCK_FIXPERMS" ] ; then
(
echo " ------------- "
echo '/!\ WARNING /!\ '
echo "The fixperms script is disabled"
echo "To enable it, delete $LOCK_FIXPERMS "
echo " ------------- "
) 1>&2
exit 0
usage "
------------------------------------
/!\ WARNING /!\
The fixperms script is disabled
To enable it, delete $LOCK_FIXPERMS
------------------------------------
"
fi
while getopts "l:u:f:d:" optname
while getopts "hl:u:f:d:" optname
do
case "$optname" in
"h") usage
;;
"l")
if [[ "$OPTARG" =~ ^[a-zA-Z0-9_]+$ ]] ; then
query="SELECT uid,login FROM membres WHERE login LIKE '$OPTARG' ORDER BY login"
else
echo "Bad login provided"
exit
usage "Bad login provided"
fi
;;
"u")
if [[ "$OPTARG" =~ ^[0-9]+$ ]] ; then
query="SELECT uid,login FROM membres WHERE uid LIKE '$OPTARG' ORDER BY login"
else
echo "Bad uid provided"
exit
usage "Bad uid provided"
fi
;;
"f")
@ -79,17 +87,14 @@ do
echo $sub_dir
;;
"?")
echo "Unknown option $OPTARG - stop processing"
exit
usage "Unknown option $OPTARG - stop processing"
;;
":")
echo "No argument value for option $OPTARG - stop processing"
exit
usage "No argument value for option $OPTARG - stop processing"
;;
*)
# Should not occur
echo "Unknown error while processing options"
exit
usage "Unknown error while processing options"
;;
esac
done

View File

@ -1,225 +0,0 @@
#!/bin/bash
. /usr/lib/alternc/functions.sh
TEMPLATE_DIR="/etc/alternc/templates/apache2"
HOSTING_DIR="/etc/alternc/functions_hosting"
HTML_HOME="$ALTERNC_HTML"
VHOST_DIR="/var/lib/alternc/apache-vhost"
launch_hooks() {
local ACTION=$1
if [ ! $2 ] ; then
# If no VTYPE specified
return 0
fi
local VTYPE=$2
EXITCODE=0
if [ -x "$HOSTING_DIR/hosting_$VTYPE.sh" ] ; then
# If a specific script exist for this VTYPE,
# we launch it, and return his return code
"$HOSTING_DIR/hosting_$VTYPE.sh" "$1" "$2" "$3" "$4"
EXITCODE=$?
fi
# also launch ssl update domains hook
/usr/lib/alternc/update_certs.sh "$1" "$2" "$3" "$4"
# No specific script, return 0
return "$EXITCODE"
}
host_conffile() {
# Return the absolute path of a conf file for a FQDN
local FQDN="$1"
local U_ID=$(get_uid_by_domain "$FQDN")
local CONFFILE="$VHOST_DIR/${U_ID:(-1)}/$U_ID/$FQDN.conf"
echo $CONFFILE
return 0
}
host_create() {
# Function to create a vhost for a website
# First, it look if there is a special file for
# this type of vhost
# If there isn't, it use the default function
# and the template file provided
local VTYPE="$1"
launch_hooks "create" "$1" "$2" "$3" "$4"
if [ $? -gt 10 ] ; then
# If the hooks return a value > 10
# it's mean we do not continue the
# "default" actions
return $?
fi
# There is no special script, I use the standart template
# If I do not found template manualy define, I look
# If there is an existing template with the good name
# First, usefull vars. Some may be empty or false, it's
# OK, it will be solve in the "case" below
local FQDN=$2
local MAIL_ACCOUNT=$3
local REDIRECT=$4 # Yes, TARGET_DIR and REDIRECT are the same
local TARGET_DIR=$4 # It's used by different template
local U_ID=$(get_uid_by_domain "$FQDN")
local G_ID="$U_ID"
local USER=$(get_account_by_domain $FQDN)
local user_letter=`print_user_letter "$USER"`
local DOCUMENT_ROOT="${HTML_HOME}/${user_letter}/${USER}$TARGET_DIR"
local ACCOUNT_ROOT="${HTML_HOME}/${user_letter}/${USER}/"
local FILE_TARGET=$(host_conffile "$FQDN")
# In case VTYPE don't have the same name as the template file,
# here we can define it
local TEMPLATE=''
case $VTYPE in
# "example")
# TEMPLATE="$TEMPLATE_DIR/an-example.conf"
# ;;
*)
# No template found, look if there is some in the
# template dir
[ -r "$TEMPLATE_DIR/$VTYPE" ] && TEMPLATE="$TEMPLATE_DIR/$VTYPE"
[ ! "$TEMPLATE" ] && [ -r "$TEMPLATE_DIR/$VTYPE.conf" ] && TEMPLATE="$TEMPLATE_DIR/$VTYPE.conf"
;;
esac
# If TEMPLATE is empty, stop right here
[ ! "$TEMPLATE" ] && return 6
# Forbid generation for website with UID/GID == 0
if [[ $U_ID == 0 || $G_ID == 0 ]] ; then
log_error "Fatal error: update_domains/function_dns/host_create : FQDN = $FQDN - TYPE = $VTYPE - UID = $U_ID - GID = $G_ID . Stopping generation"
return 7
fi
# Create a new conf file
local TMP_FILE=$(mktemp "/tmp/alternc_host.XXXXXX")
cp "$TEMPLATE" "$TMP_FILE"
# Substitute special characters :
FQDN2="`echo $FQDN | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
DOCUMENT_ROOT2="`echo $DOCUMENT_ROOT | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
ACCOUNT_ROOT2="`echo $ACCOUNT_ROOT | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
REDIRECT2="`echo $REDIRECT | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
USER2="`echo $USER | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
# Put the good value in the conf file
sed -i \
-e "s#%%LOGIN%%#$USER#g" \
-e "s#%%fqdn%%#$FQDN2#g" \
-e "s#%%document_root%%#$DOCUMENT_ROOT2#g" \
-e "s#%%account_root%%#$ACCOUNT_ROOT2#g" \
-e "s#%%redirect%%#$REDIRECT2#g" \
-e "s#%%UID%%#$U_ID#g" \
-e "s#%%GID%%#$G_ID#g" \
-e "s#%%mail_account%%#$MAIL_ACCOUNT#g" \
-e "s#%%user%%#$USER2#g" \
$TMP_FILE
## Fix for wildcard
if [[ "$FQDN2" == "*."* ]]; then
sed -i "s/ServerName/ServerAlias/" $TMP_FILE
fi
# Check if all is right in the conf file
# If not, put a debug message
# NO : redirect and document_root COULD contains legitimate %% expressions (...)
# local ISNOTGOOD=$(grep "%%" "$TMP_FILE")
# [ "$ISNOTGOOD" ] && (echo "# There was a probleme in the generation : $ISNOTGOOD" > "$TMP_FILE" ; return 44 )
# Put the conf file in prod
mkdir -p "$(dirname "$FILE_TARGET")"
mv -f "$TMP_FILE" "$FILE_TARGET"
# Execute post-install hooks
launch_hooks "postinst" "$1" "$2" "$3" "$4"
if [ $? -gt 10 ] ; then
# If the hooks return a value > 10
# it's mean we do not continue the
# "default" actions
return $?
fi
# All is quit, we return 0
return 0
}
host_disable() {
host_change_enable "disable" "$1" "$2" "$3" "$4"
}
host_enable() {
host_change_enable "enable" "$1" "$2" "$3" "$4"
}
host_change_enable() {
# Function to enable or disable a host
local STATE=$1
# Execute hooks
launch_hooks "$1" "$2" "$3" "$4"
if [ $? -gt 10 ] ; then
# If the hooks return a value > 10
# it's mean we do not continue the
# "default" actions
return $?
fi
local TYPE=$2 # no use here, but one day, maybe... So here he is
local FQDN=$3
local FENABLED=$(host_conffile "$FQDN")
local FDISABLED="$FENABLED-disabled"
case $STATE in
"enable")
local SOURCE="$FDISABLED"
local TARGET="$FENABLED"
;;
"disable")
local TARGET="$FDISABLED"
local SOURCE="$FENABLED"
;;
*)
return 1
;;
esac
if [ ! -e "$TARGET" ] && [ -e "$SOURCE" ] ; then
# If the "target" file do not exist and the "source" file exist
mv -f "$SOURCE" "$TARGET"
else
return 2
fi
}
host_delete() {
local VTYPE=$1
local FQDN=$2
# Execute post-install hooks
launch_hooks "delete" "$1" "$2" "$3" "$4"
if [ $? -gt 10 ] ; then
# If the hooks return a value > 10
# it's mean we do not continue the
# "default" actions
return $?
fi
# Fix of a longstanding BUG: we only DELETE the vhost file if the type is a vhost one !
if [ -f "${TEMPLATE_DIR}/${VTYPE}.conf" ]
then
local FENABLED=$(host_conffile "$FQDN")
local FDISABLED="$FENABLED-disabled"
[ -w "$FENABLED" ] && rm -f "$FENABLED"
[ -w "$FDISABLED" ] && rm -f "$FDISABLED"
fi
}

View File

@ -1,85 +0,0 @@
#!/usr/bin/php -q
<?php
/**
*
* Generate Apache configuration for AlternC
*
* To force generation, /launch/generate_apache_conf.php force
*
* Return the number of vhost modified, return 0 if no action
*
**/
require_once("/usr/share/alternc/panel/class/config_nochk.php");
ini_set("display_errors", 1);
/*
FIXME :
- add security check
*/
// Check if we can modify Apache conf
@touch(ALTERNC_VHOST_FILE);
if ( ! is_writable( ALTERNC_VHOST_FILE )) {
die("Error: ".ALTERNC_VHOST_FILE." is not writable\n");
}
// Do we need to regenerate apache conf ?
$db->query("select count(*) as c from sub_domaines where web_action != 'OK';");
if (! $db->next_record()) $nb_todo = 0;
$nb_todo = $db->f('c');
// But, we may have forced it
if ( ! in_array('force', $argv) && $nb_todo < 1) {
die('0');
}
$todo = $dom->generation_todo();
$parameters = $dom->generation_parameters();
// Generate apache conf
$conf = $dom->generate_apacheconf();
if (! $conf) {
die("Error: generate empty configuration\n");
}
// Add some headers
$conf2 = "###BEGIN OF ALTERNC AUTO-GENERATED FILE - DO NOT EDIT MANUALLY###
# Generation: ".date('Y-m-d H:i:s');
// Do we need to include manual configuration ?
if ( is_dir( ALTERNC_VHOST_MANUALCONF ) ) {
$conf2.="\n## Manual VHOST\nInclude ".ALTERNC_VHOST_MANUALCONF."\n" ;
} else {
$conf2.="\n## Manual VHOST directory missing (".ALTERNC_VHOST_MANUALCONF.")\n" ;
}
$conf2.="\n$conf\n\n###END OF ALTERNC AUTO-GENERATED FILE - DO NOT EDIT MANUALLY###\n";
// Write the conf !
if (! file_put_contents(ALTERNC_VHOST_FILE, $conf2) ) {
die("Error: writing content\n");
}
// Update the database to inform that we did the job
foreach ( $todo as $taction=>$tlist){
foreach ($tlist as $ttype) {
foreach($ttype as $tid) {
$dom->subdomain_modif_are_done($tid, $taction);
}
}
}
// Hooks !
foreach (array('DELETE', 'CREATE', 'UPDATE', 'ENABLE', 'DISABLE') as $y) {
if (!isset($todo[$y]) || empty($todo[$y])) continue;
$dom->generate_conf_oldhook($y, $todo); // old hooks for compatibility
$hooks->invoke("hook_genconf", array($y, $todo[$y], $parameters)); // modern hooks
}
echo $nb_todo;

View File

@ -1,24 +0,0 @@
#!/usr/bin/php -q
<?php
/**
*
* Generate Bind configuration for AlternC
*
* To force generation, /launch/generate_bind_conf.php --force
*
*
**/
require_once("/usr/share/alternc/panel/class/config_nochk.php");
ini_set("display_errors", 1);
$bind = new system_bind();
$force = false;
if (in_array('--force', $argv)) { // Want to force
$force=true;
}
$bind->regenerate_conf($force);

View File

@ -4,7 +4,6 @@
. /usr/lib/alternc/functions.sh
echo "This script will rebuild all web configuration and regenerate DNS."
echo "Only files in $VHOST_MANUALCONF will be preserved."
echo "Use --force to skip confirmation"
if [ ! "$1" == "--force" ] ; then
@ -20,7 +19,6 @@ mysql_query "update domaines set dns_action = 'UPDATE' WHERE dns_action != '
echo "Now launching update_domains to rebuild."
/usr/lib/alternc/update_domains.sh
/usr/lib/alternc/generate_bind_conf.php --force
echo "Finish."

View File

@ -30,7 +30,7 @@ $ssl->cron_new_certs();
$services=array("postfix","dovecot","proftpd","apache2");
foreach($services as $service) {
passthru("service $service status",&$ret);
passthru("service $service status",$ret);
if ($ret!=0) {
echo "$service not running, restarting\n";
passthru("service $service restart");

View File

@ -1,35 +1,33 @@
#!/bin/bash
#!/usr/bin/php
<?php
# Rebuild the bind configuration's file
# with the IP of the slave dns
// Rebuild the bind configuration's file
// with the IP of the slave dns
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
FLAGFILE="/run/alternc/refresh_slave";
TPL="/etc/alternc/templates/bind/slaveip.conf"
TARGET="/var/lib/alternc/bind/slaveip.conf"
$FLAGFILE="/run/alternc/refresh_slave";
$TPL="/etc/alternc/templates/bind/slaveip.conf";
$TARGET="/var/lib/alternc/bind/slaveip.conf";
if [ ! -e "$FLAGFILE" ] ; then
# Nothing to do
exit 0
fi
if (!file_exists($FLAGFILE)) exit(0);
# Source some functions
. /usr/lib/alternc/functions.sh
// Bootstrap
require_once("/usr/share/alternc/panel/class/config_nochk.php");
TMP=$(mktemp /tmp/slaveip.conf.XXXX)
$db->query("SELECT ip,class FROM slaveip;");
$str="";
while ($db->next_record()) {
$str.=" ".$db->Record["ip"]."/".$db->Record["class"].";\n";
}
# Get the slave IP. Remove the "newline" caracters
val=$(mysql_query "SELECT concat(ip,'::',class,'; ') FROM slaveip;"|tr '\n' ' ')
file_put_contents($TARGET, str_replace("//AUTO-SLAVES//",$str, file_get_contents($TPL) ) );
# Add the slaves to the templates, re-add the missing "/" separator of subnet
cat "$TPL" | sed -e "s/\/\/AUTO-SLAVES\/\//$val/g" -e "s/::/\//g" > "$TMP"
chown($TARGET,"root");
chgrp($TARGET,"bind");
chmod($TARGET,0640);
# Activate the new configuration
mv "$TMP" "$TARGET"
chown root:bind "$TARGET"
chmod 640 "$TARGET"
putenv("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
passthru("rndc reconfig");
unlink($FLAGFILE);
invoke-rc.d bind9 reload
# Remove FLAGSLAVE file
rm -f "$FLAGFILE"

10
src/update_domains.php Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/php -q
<?php
// bootstrap
require_once("/usr/share/alternc/panel/class/config_nochk.php");
putenv("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
$dom->update_domains();

View File

@ -1,168 +1,5 @@
#!/bin/bash
# Update domain next-gen by fufroma
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# This is now done using PHP-only scripting
for CONFIG_FILE in \
/etc/alternc/local.sh \
/usr/lib/alternc/functions.sh \
/usr/lib/alternc/functions_hosting.sh \
/usr/lib/alternc/functions_dns.sh
do
if [ ! -r "$CONFIG_FILE" ]; then
echo "Can't access $CONFIG_FILE."
exit 1
fi
. "$CONFIG_FILE"
done
stop_if_jobs_locked
# Some vars
umask 022
LOCK_FILE="/usr/share/alternc/panel/cron.lock" # FIXME doesn't seem clean to be here
OLDIFS="$IFS"
NEWIFS=" "
RELOAD_WEB="$(mktemp /tmp/alternc_reload_web.XXXX)"
RELOAD_DNS="$(mktemp /tmp/alternc_reload_dns.XXXX)"
B="µµ§§" # Strange letters to make split in query
# Somes check before start operations
if [ `id -u` -ne 0 ]; then
log_error "must be launched as root"
elif [ -z "$DEFAULT_MX" -o -z "$PUBLIC_IP" ]; then
log_error "Bad configuration. Please use: dpkg-reconfigure alternc"
elif [ -f "$LOCK_FILE" ]; then
process=$(ps f -p `cat "$LOCK_FILE"|tail -1`|tail -1|awk '{print $NF;}')
if [ "$(basename $process)" = "$(basename "$0")" ] ; then
log_error "last cron unfinished or stale lock file ($LOCK_FILE)."
else
rm "$LOCK_FILE"
fi
fi
# backward compatibility: single-server setup
if [ -z "$ALTERNC_SLAVES" ] ; then
ALTERNC_SLAVES="localhost"
fi
# We lock the application
echo $$ > "$LOCK_FILE"
echo "" > "$RELOAD_WEB"
echo "" > "$RELOAD_DNS"
# For domains we want to delete completely, make sure all the tags are all right
# set sub_domaines.web_action = delete where domaines.dns_action = DELETE
mysql_query "update sub_domaines sd, domaines d set sd.web_action = 'DELETE' where sd.domaine = d.domaine and sd.compte=d.compte and d.dns_action = 'DELETE';"
# Sub_domaines we want to delete
# sub_domaines.web_action = delete
for sub in $( mysql_query "select concat_ws('$B',lower(sd.type), if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine)) from sub_domaines sd where web_action ='DELETE';") ; do
host_delete ${sub/$B/ }
mysql_query "delete from sub_domaines where concat_ws('$B',lower(type), if(length(sub)>0,concat_ws('.',sub,domaine),domaine)) = '$sub' and web_action ='DELETE';"
echo 1 > "$RELOAD_WEB"
done
# Sub domaines we want to update
# sub_domaines.web_action = update and sub_domains.only_dns = false
IFS="$NEWIFS"
mysql_query "
select concat_ws('$IFS',sd.id, lower(sd.type), if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine), concat_ws('@',m.login,v.value), sd.valeur )
from sub_domaines sd,membres m,variable v
where sd.compte=m.uid and sd.web_action ='UPDATE' and v.name='mailname_bounce'
;" | while read sdid type domain mail valeur ; do
host_create "$type" "$domain" "$mail" "$valeur"
mysql_query "update sub_domaines sd set web_action='OK',web_result='$?' where sd.id = '$sdid' ; "
echo 1 > "$RELOAD_WEB"
done
# Domaine to enable
mysql_query "select concat_ws('$IFS',sd.id, lower(sd.type),if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine),sd.valeur) from sub_domaines sd where sd.enable ='ENABLE' ;"|while read sdid type domain valeur ; do
host_enable "$type" "$domain" "$valeur"
mysql_query "update sub_domaines sd set enable='ENABLED' where sd.id = '$sdid' ;"
echo 1 > "$RELOAD_WEB"
done
# Domains to disable
mysql_query "select concat_ws('$IFS', sd.id, lower(sd.type),if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine),sd.valeur) from sub_domaines sd where sd.enable ='DISABLE' ;"|while read sdid type domain valeur ; do
host_disable "$type" "$domain" "$valeur"
mysql_query "update sub_domaines sd set enable='DISABLED' where sd.id = '$sdid' ;"
echo 1 > "$RELOAD_WEB"
done
# Domains we do not want to be the DNS serveur anymore :
# domaines.dns_action = UPDATE and domaines.gesdns = 0
for dom in `mysql_query "select domaine from domaines where dns_action = 'UPDATE' and gesdns = 0;"| tr '\n' ' '`
do
dns_delete $dom
mysql_query "update domaines set dns_action = 'OK', dns_result = '$?' where domaine = '$dom'"
echo 1 >"$RELOAD_DNS"
done
# Domains we have to update the dns :
# domaines.dns_action = UPDATE
for dom in `mysql_query "select domaine from domaines where dns_action = 'UPDATE';" | tr '\n' ' '`
do
echo "dns_regenerate : domain=/$dom/"
dns_regenerate $dom
mysql_query "update domaines set dns_action = 'OK', dns_result = '$?' where domaine = '$dom'"
echo 1 >"$RELOAD_DNS"
done
# Domains we want to delete completely, now we do it
# domaines.dns_action = DELETE
for dom in `mysql_query "select domaine from domaines where dns_action = 'DELETE';" | tr '\n' ' '`
do
dns_delete $dom
# Web configurations have already bean cleaned previously
mysql_query "delete from sub_domaines where domaine='$dom'; delete from domaines where domaine='$dom';"
echo 1 >"$RELOAD_DNS"
done
if [ ! -z "$(cat "$RELOAD_WEB")" ] ; then
# Just to encourage user to use THIS directory and not another one
test -d "$VHOST_MANUALCONF" || mkdir -p "$VHOST_MANUALCONF"
# Concat the apaches files
tempo=$(mktemp "$VHOST_FILE.XXXXX")
(
echo "###BEGIN OF ALTERNC AUTO-GENERATED FILE - DO NOT EDIT MANUALLY###"
find "$VHOST_DIR"/ -mindepth 2 -type f -iname "*.conf" -print0 | xargs -0 cat
echo "###END OF ALTERNC AUTO-GENERATED FILE - DO NOT EDIT MANUALLY###"
) > "$tempo"
if [ $? -ne 0 ] ; then
log_error " web file concatenation failed"
fi
touch "$VHOST_FILE"
if [ ! -w "$VHOST_FILE" ] ; then
log_error "cannot write on $VHOST_FILE"
fi
mv "$tempo" "$VHOST_FILE"
# We must reload apache
# we assume we run apache on the master
/usr/lib/alternc/alternc_reload apache || true
# Launch hooks for apache reload
run-parts --arg=web_reload /usr/lib/alternc/reload.d
fi
# If we added / edited / deleted at least one dns zone file, we go here in the end:
if [ ! -z "$(cat "$RELOAD_DNS")" ] ; then
service opendkim restart
run-parts --arg=dns_reload /usr/lib/alternc/reload.d
fi
## FIXME : move the slave part into the /usr/lib/alternc/reload.d directory to be an hook
#for slave in $ALTERNC_SLAVES; do
# if [ "$slave" != "localhost" ]; then
# ssh alternc@$slave alternc_reload 'apache' || true
# fi
#done
rm -f "$LOCK_FILE" "$RELOAD_ZONES" "$RELOAD_WEB" "$INOTIFY_UPDATE_DOMAIN" "$RELOAD_DNS"
exit 0
/usr/lib/alternc/update_domains.php