From a194cd80d0a1985c125151ec9fcd42ed730f3054 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Sat, 7 Jul 2018 13:13:28 +0200 Subject: [PATCH 01/68] [fix] vhost http template missing SSLENGINE and CERT instructions in 443 Vhost --- etc/alternc/templates/apache2/vhost-http.conf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/etc/alternc/templates/apache2/vhost-http.conf b/etc/alternc/templates/apache2/vhost-http.conf index c163bc86..5754a8e9 100644 --- a/etc/alternc/templates/apache2/vhost-http.conf +++ b/etc/alternc/templates/apache2/vhost-http.conf @@ -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%% + From ed7aaa3151ae946f61ebfa67f57c1d7d9dee654f Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Sun, 8 Jul 2018 13:01:35 +0200 Subject: [PATCH 02/68] [enh] first version of class-and-hooks-based update_domains.php, includes ssl certficate mechanism --- bureau/class/m_apache.php | 179 ++++++++++++++++++ .../{class_system_bind.php => m_bind.php} | 55 +++++- bureau/class/m_dom.php | 101 +++++++++- bureau/class/m_ssl.php | 90 +++++++-- src/update_domains.sh | 9 +- 5 files changed, 415 insertions(+), 19 deletions(-) create mode 100644 bureau/class/m_apache.php rename bureau/class/{class_system_bind.php => m_bind.php} (92%) diff --git a/bureau/class/m_apache.php b/bureau/class/m_apache.php new file mode 100644 index 00000000..e497e8e1 --- /dev/null +++ b/bureau/class/m_apache.php @@ -0,0 +1,179 @@ +shouldreload=false; + } + + // launched for each FQDN for which we want a new vhost template + function hook_updatedomains_web_add($subdomid) { + global $msg,$db; + + $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['mail'], + "%%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"); + $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($subdom) { + $confdir = $this->vhostroot."/".substr($subdom["compte"],-1)."/".$subdom["compte"]; + @unlink($confdir."/".$subdom["fqdn"].".conf"); + $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); + } + + 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 + diff --git a/bureau/class/class_system_bind.php b/bureau/class/m_bind.php similarity index 92% rename from bureau/class/class_system_bind.php rename to bureau/class/m_bind.php index 34d045b4..c5080629 100644 --- a/bureau/class/class_system_bind.php +++ b/bureau/class/m_bind.php @@ -19,11 +19,16 @@ */ /** - * bind9 file management class + * Manages BIND 9+ zone management templates in AlternC 3.5+ * - * @copyright AlternC-Team 2000-2017 https://alternc.com/ + * @copyright AlternC-Team 2000-2018 https://alternc.com/ */ -class system_bind { +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"; @@ -39,6 +44,47 @@ class system_bind { var $cache_domain_summary = array(); var $zone_file_directory = '/var/lib/alternc/bind/zones/'; + + // launched before any action by updatedomains + function hook_updatedomains_dns_pre() { + $this->shouldreload=false; + $this->shouldreconfig=false; + } + + // launched for each ZONE for which we want a zone update (or create) + function hook_updatedomains_dns_add($domain) { + + } + + // launched for each ZONE for which we want a zone DELETE + function hook_updatedomains_dns_del($domain) { + + } + + // launched at the very end of updatedomains + 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." reload 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"); + } + } + } + + /** * Return the part of the conf we got from the database @@ -521,5 +567,6 @@ class system_bind { } -} /* Class system_bind */ + +} // m_bind diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index 64d50a7f..bafab4de 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -1770,10 +1770,15 @@ class m_dom { if ($this->islocked) { $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($this->fic_lock_cron) && filemtime($this->fic_lock_cron)>(time()-900)) { + clearstatcache(); sleep(2); } + @touch($this->fic_lock_cron); $this->islocked = true; + // extra safe : + register_shutdown_function(array("m_dom","unlock"),1); return true; } @@ -1783,12 +1788,13 @@ class m_dom { * return true * @access private */ - function unlock() { + function unlock($isshutdown=0) { global $msg; $msg->debug("dom", "unlock"); - if (!$this->islocked) { + if (!$isshutdown && !$this->islocked) { $msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!")); } + @unlink($this->fic_lock_cron); $this->islocked = false; return true; } @@ -1891,6 +1897,95 @@ class m_dom { } + /** + * 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 + */ + function update_domains() { + if (posix_getuid()!=0) { + echo "FATAL: please lauch me as root\n"; + exit(); + } + + $dom->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';"); + + // Search for things to do on DOMAINS: + $db->query("SELECT * FROM domaines WHERE dns_action!='OK';"); + $alldoms=array(); + while ($db->next_record()) { + $alldoms[$db->Record["id"]]=$db->Record; + } + // 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(array($onedom))); + } else { + $ret = $hooks->invoke("hook_updatedomains_dns_add",array(array($onedom))); + } + + 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)); + } + } + $hooks->invoke("hook_updatedomains_dns_post"); + } + + + // 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(); + while ($db->next_record()) { + // only_dns=1 => weird, we should not have web_action SET to something else than OK ... anyway, skip it + if ($db->Record["only_dns"]) { + $ignore[]=$db->Record["id"]; + } else { + $alldoms[$db->Record["id"]]=$db->Record; + } + } + 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"])); + } + + 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)); + } + } + $hooks->invoke("hook_updatedomains_web_post"); + } + + $dom->unlock(); + } + + /** * Return an array with all the needed parameters to generate conf * of a vhost. diff --git a/bureau/class/m_ssl.php b/bureau/class/m_ssl.php index 109241c4..69b0a6f0 100644 --- a/bureau/class/m_ssl.php +++ b/bureau/class/m_ssl.php @@ -372,7 +372,34 @@ INSTR(CONCAT(sd.sub,IF(sd.sub!='','.',''),sd.domaine),'.')+1))=? return $db->Record; } - + + // ----------------------------------------------------------------- + /** 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.".cert", + "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 @@ -492,6 +519,12 @@ INSTR(CONCAT(sd.sub,IF(sd.sub!='','.',''),sd.domaine),'.')+1))=? $msg->raise("ERROR","ssl", _("Can't save the Key/Crt/Chain now. Please try later.")); return false; } + $this->write_cert_file(array( + "id"=>$id, + "sslcrt"=>$crt, + "sslkey"=>$key, + "sslchain"=>$chain + )); return $id; } @@ -612,6 +645,33 @@ 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($fqdn, $subdom["provider"]); + // 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 @@ -627,7 +687,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 +737,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; } diff --git a/src/update_domains.sh b/src/update_domains.sh index feb2f923..3869ac72 100755 --- a/src/update_domains.sh +++ b/src/update_domains.sh @@ -1,5 +1,12 @@ #!/bin/bash -# Update domain next-gen by fufroma +# This is now done using PHP-only scripting + +/usr/lib/alternc/update_domains.php + +exit + +# legacy code here + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin for CONFIG_FILE in \ From 9b7332f35405574868093ad526b6618879487aca Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Sun, 8 Jul 2018 22:03:27 +0200 Subject: [PATCH 03/68] [enh] adding DKIM and AUTODISCOVER management in SUB_DOMAINES, finishing BIND update_domains.php --- bureau/class/functions.php | 51 +++ bureau/class/m_bind.php | 643 +++++++++-------------------------- bureau/class/m_dom.php | 2 +- bureau/class/m_mail.php | 147 +++++++- install/mysql.sql | 8 +- install/upgrades/3.5.0.1.sql | 33 +- install/upgrades/3.5.0.2.php | 32 ++ 7 files changed, 407 insertions(+), 509 deletions(-) create mode 100644 install/upgrades/3.5.0.2.php diff --git a/bureau/class/functions.php b/bureau/class/functions.php index b9c94817..cd9e782c 100755 --- a/bureau/class/functions.php +++ b/bureau/class/functions.php @@ -1245,3 +1245,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; +} + diff --git a/bureau/class/m_bind.php b/bureau/class/m_bind.php index c5080629..e85b42ad 100644 --- a/bureau/class/m_bind.php +++ b/bureau/class/m_bind.php @@ -27,41 +27,132 @@ 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 $dkim_trusted_host_file = "/etc/opendkim/TrustedHosts"; - var $dkim_keytable_file = "/etc/opendkim/KeyTable"; - var $dkim_signingtable_file = "/etc/opendkim/SigningTable"; + var $zone_file_directory = '/var/lib/alternc/bind/zones'; - var $cache_conf_db = array(); - var $cache_get_persistent = array(); - var $cache_zone_file = array(); - var $cache_domain_summary = array(); - var $zone_file_directory = '/var/lib/alternc/bind/zones/'; - - - // launched before any action by updatedomains + // ------------------------------------------------------------ + /** 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; } - // launched for each ZONE for which we want a zone update (or create) - function hook_updatedomains_dns_add($domain) { - + + // ------------------------------------------------------------ + /** + * 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); + // 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 SUBDOMAIN entries + $zone .= $this->conf_from_db($domain); + + // 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; + } } - // launched for each ZONE for which we want a zone DELETE - function hook_updatedomains_dns_del($domain) { - + + // ------------------------------------------------------------ + /** + * 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 (remove_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); } - // launched at the very end of updatedomains + + // ------------------------------------------------------------ + /** + * 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) { @@ -84,489 +175,63 @@ class m_bind { } } + + // ------------------------------------------------------------ + /** + * 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 database - * + * Return the part of the conf we got from the sub_domaines table * @global m_mysql $db * @param string $domain - * @return array $this->cache_conf_db + * @return string a zonefile excerpt */ - function conf_from_db($domain=false) { + function conf_from_db($domain) { global $db; - // Use cache, fill cache if empty - if (empty($this->cache_conf_db)) { - $db->query(" - select - sd.domaine, - replace(replace(dt.entry,'%TARGET%',sd.valeur), '%SUB%', if(length(sd.sub)>0,sd.sub,'@')) as entry - from + $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 + WHERE sd.type=dt.name - and sd.enable in ('ENABLE', 'ENABLED') - order by entry ;"); - $t=array(); - while ($db->next_record()) { - $t[$db->f('domaine')][] = $db->f('entry'); - } - $this->cache_conf_db = $t; + AND sd.enable IN ('ENABLE', 'ENABLED') + ORDER BY ENTRY ;"); + $t=array(); + while ($db->next_record()) { + $t.= $db->f('entry')."\n"; } - if ($domain) { - if (isset($this->cache_conf_db[$domain])) { - return $this->cache_conf_db[$domain]; - } else { - return array(); - } - } // if domain - return $this->cache_conf_db; + return $t; } - - /** - * Return full path of the zone configuration file - * - * @param string $domain - * @return string - */ - function get_zone_file_uri($domain) { - return $this->zone_file_directory.$domain; - } - - - /** - * - * @param string $domain - * @return string zone file path - */ - function get_zone_file($domain) { - // Use cache, fill cache if empty - if (!isset($this->cache_zone_file[$domain]) ) { - if (file_exists($this->get_zone_file_uri($domain))) { - $this->cache_zone_file[$domain] = @file_get_contents($this->get_zone_file_uri($domain)); - } else { - $this->cache_zone_file[$domain] = false; - } - } - return $this->cache_zone_file[$domain] ; - } - - - /** - * - * @param string $domain - * @return string - */ - function get_serial($domain) { - // Return the next serial the domain must have. - // Choose between a generated and an incremented. - - // Calculated : - $calc = date('Ymd').'00'."\n"; - - // Old one : - $old=$calc; // default value - $file = $this->get_zone_file($domain); - preg_match_all("/\s*(\d{10})\s+\;\sserial\s?/", $file, $output_array); - if (isset($output_array[1][0]) && !empty($output_array[1][0])) { - $old = $output_array[1][0]; - } - - // Return max between newly calculated, and old one incremented - return max(array($calc,$old)) + 1 ; - } - - - /** - * Return lines that are after ;;; END ALTERNC AUTOGENERATE CONFIGURATION - * - * @param string $domain - * @return string - */ - function get_persistent($domain) { - if ( ! isset($this->cache_get_persistent[$domain] )) { - preg_match_all('/\;\s*END\sALTERNC\sAUTOGENERATE\sCONFIGURATION(.*)/s', $this->get_zone_file($domain), $output_array); - if (isset($output_array[1][0]) && !empty($output_array[1][0])) { - $this->cache_get_persistent[$domain] = $output_array[1][0]; - } else { - $this->cache_get_persistent[$domain] = false; - } - } // isset - return $this->cache_get_persistent[$domain]; - } - - - /** - * - * @return string - */ - function get_zone_header() { - return file_get_contents($this->ZONE_TEMPLATE); - } - - - /** - * - * @global m_dom $dom - * @param string $domain - * @return array Retourne un tableau - */ - function get_domain_summary($domain=false) { - global $dom; - - // Use cache if is filled, if not, fill it - if (empty($this->cache_domain_summary)) { - $this->cache_domain_summary = $dom->get_domain_all_summary(); - } - - if ($domain) return $this->cache_domain_summary[$domain]; - else return $this->cache_domain_summary; - } - - - /** - * - * @param string $domain - * @return boolean - */ - function dkim_delete($domain) { - $target_dir = "/etc/opendkim/keys/$domain"; - if (file_exists($target_dir)) { - @unlink("$target_dir/alternc_private"); - @unlink("$target_dir/alternc.txt"); - @rmdir($target_dir); - } - return true; - } - - - /** - * Generate the domain DKIM key - * - * @param string $domain - * @return null|boolean - */ - function dkim_generate_key($domain) { - // Stop here if we do not manage the mail - $domainInfo = $this->get_domain_summary($domain); - if ( ! $domainInfo['gesmx'] ) return; - - $target_dir = "/etc/opendkim/keys/$domain"; - - if (file_exists($target_dir.'/alternc.txt')) return; // Do not generate if exist - - if (! is_dir($target_dir)) mkdir($target_dir); // create dir - - // Generate the key - $old_dir=getcwd(); - chdir($target_dir); - exec('opendkim-genkey -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'); - - return true; // FIXME handle error - } - - - /** - * Refresh DKIM configuration: be sure to list the domain having a private key (and only them) - */ - function dkim_refresh_list() { - // so ugly... but there is only 1 pass, not 3. Still ugly. - $trusted_host_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n"; - $keytable_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n"; - $signingtable_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n"; - - # Generate automatic entry - foreach ($this->get_domain_summary() as $domain => $ds ) { - // Skip if delete in progress, or if we do not manage dns or mail - if ( ! $ds['gesdns'] || ! $ds['gesmx'] || strtoupper($ds['dns_action']) == 'DELETE' ) continue; - - // Skip if there is no key generated - if (! file_exists("/etc/opendkim/keys/$domain/alternc.txt")) continue; - - // Modif the files. - $trusted_host_new.="$domain\n"; - $keytable_new .="alternc._domainkey.$domain $domain:alternc:/etc/opendkim/keys/$domain/alternc.private\n"; - $signingtable_new.="$domain alternc._domainkey.$domain\n"; - } - $trusted_host_new.="# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n"; - $keytable_new .="# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n"; - $signingtable_new.="# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n"; - - # Get old files - $trusted_host_old=@file_get_contents($this->dkim_trusted_host_file); - $keytable_old =@file_get_contents($this->dkim_keytable_file); - $signingtable_old=@file_get_contents($this->dkim_signingtable_file); - - # Keep manuel entry - preg_match_all('/\#\s*END\ AUTOMATIC\ FILE\.\ ADD\ YOUR\ CHANGES\ AFTER\ THIS\ LINE(.*)/s', $trusted_host_old, $output_array); - if (isset($output_array[1][0]) && !empty($output_array[1][0])) { - $trusted_host_new.=$output_array[1][0]; - } - preg_match_all('/\#\s*END\ AUTOMATIC\ FILE\.\ ADD\ YOUR\ CHANGES\ AFTER\ THIS\ LINE(.*)/s', $keytable_old, $output_array); - if (isset($output_array[1][0]) && !empty($output_array[1][0])) { - $keytable_new.=$output_array[1][0]; - } - preg_match_all('/\#\s*END\ AUTOMATIC\ FILE\.\ ADD\ YOUR\ CHANGES\ AFTER\ THIS\ LINE(.*)/s', $signingtable_old, $output_array); - if (isset($output_array[1][0]) && !empty($output_array[1][0])) { - $signingtable_new.=$output_array[1][0]; - } - - // Save if there are some diff - if ( $trusted_host_new != $trusted_host_old ) { - file_put_contents($this->dkim_trusted_host_file, $trusted_host_new); - } - if ( $keytable_new != $keytable_old ) { - file_put_contents($this->dkim_keytable_file, $keytable_new); - } - if ( $signingtable_new != $signingtable_old ) { - file_put_contents($this->dkim_signingtable_file, $signingtable_new); - } - - } - - - /** - * - * @param string $domain - * @return string - */ - function dkim_entry($domain) { - $keyfile="/etc/opendkim/keys/$domain/alternc.txt"; - $domainInfo = $this->get_domain_summary($domain); - if (! file_exists($keyfile) && $domainInfo['gesmx'] ) { - $this->dkim_generate_key($domain); - } - return @file_get_contents($keyfile); - } - - - /** - * Conditionnal generation autoconfig entry for outlook / thunderbird - * If entry with the same name allready exist, skip it. - * - * @param string $domain - * @return string - */ - function mail_autoconfig_entry($domain) { - $zone= implode("\n",$this->conf_from_db($domain))."\n".$this->get_persistent($domain); - - $entry=''; - $domainInfo = $this->get_domain_summary($domain); - if ( $domainInfo['gesmx'] ) { - // If we manage the mail - - // Check if there is no the same entry (defined or manual) - // can be toto IN A or toto.fqdn.tld. IN A - if (! preg_match("/autoconfig(\s|\.".str_replace('.','\.',$domain)."\.)/", $zone )) { - $entry.="autoconfig IN CNAME %%fqdn%%.\n"; - } - if (! preg_match("/autodiscover(\s|\.".str_replace('.','\.',$domain)."\.)/", $zone )) { - $entry.="autodiscover IN CNAME %%fqdn%%.\n"; - } - } // if gesmx - return $entry; - } - - - /** - * - * Return a fully generated zone - * - * @global string $L_FQDN - * @global string $L_NS1_HOSTNAME - * @global string $L_NS2_HOSTNAME - * @global string $L_DEFAULT_MX - * @global string $L_DEFAULT_SECONDARY_MX - * @global string $L_PUBLIC_IP - * @param string $domain - * @return string - */ - function get_zone($domain) { - global $L_FQDN, $L_NS1_HOSTNAME, $L_NS2_HOSTNAME, $L_DEFAULT_MX, $L_DEFAULT_SECONDARY_MX, $L_PUBLIC_IP; - - $zone =$this->get_zone_header(); - $zone.=implode("\n",$this->conf_from_db($domain)); - $zone.="\n;;;HOOKED ENTRY\n"; - - $zone.= $this->dkim_entry($domain); - $zone.= $this->mail_autoconfig_entry($domain); - - $zone.="\n;;; END ALTERNC AUTOGENERATE CONFIGURATION\n"; - $zone.=$this->get_persistent($domain); - $domainInfo = $this->get_domain_summary($domain); - - // FIXME check those vars - $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@@"=>$this->get_serial($domain), - "@@PUBLIC_IP@@"=>"$L_PUBLIC_IP", - "@@ZONETTL@@"=> $domainInfo['zonettl'], - )); - - return $zone; - } - - - /** - * - * @param string $domain - */ - function reload_zone($domain) { - exec($this->RNDC." reload ".escapeshellarg($domain), $output, $return_value); - if ($return_value != 0 ) { - echo "ERROR: Reload zone failed for zone $domain\n"; - } - } - - - /** - * return true if zone is locked - * - * @param string $domain - * @return boolean - */ - function is_locked($domain) { - preg_match_all("/(\;\s*LOCKED:YES)/i", $this->get_zone_file($domain), $output_array); - if (isset($output_array[1][0]) && !empty($output_array[1][0])) { - return true; - } - return false; - } - - - /** - * - * @global m_mysql $db - * @global m_dom $dom - * @param string $domain - * @return boolean - */ - function save_zone($domain) { - global $db, $dom; - - // Do not save if the zone is LOCKED - if ( $this->is_locked($domain)) { - $dom->set_dns_result($domain, "The zone file of this domain is locked. Contact your administrator."); // If edit, change dummy_for_translation - $dom->set_dns_action($domain, 'OK'); - return false; - } - - // Save file, and apply chmod/chown - $file=$this->get_zone_file_uri($domain); - file_put_contents($file, $this->get_zone($domain)); - chown($file, 'bind'); - chmod($file, 0640); - - $dom->set_dns_action($domain, 'OK'); - return true; // fixme add tests - } - - - /** - * Delete the zone configuration file - * - * @param string $domain - * @return boolean - */ - function delete_zone($domain) { - $file=$this->get_zone_file_uri($domain); - if (file_exists($file)) { - unlink($file); - } - $this->dkim_delete($domain); - return true; - } - - - /** - * - * @global m_hooks $hooks - * @return boolean - */ - function reload_named() { - global $hooks; - // Generate the new conf file - $new_named_conf="// DO NOT EDIT\n// This file is generated by Alternc.\n// Every changes you'll make will be overwrited.\n"; - $tpl=file_get_contents($this->NAMED_TEMPLATE); - foreach ($this->get_domain_summary() as $domain => $ds ) { - if ( ! $ds['gesdns'] || strtoupper($ds['dns_action']) == 'DELETE' ) continue; - $new_named_conf.=strtr($tpl, array("@@DOMAINE@@"=>$domain, "@@ZONE_FILE@@"=>$this->get_zone_file_uri($domain))); - } - - // Get the actual conf file - $old_named_conf = @file_get_contents($this->NAMED_CONF); - - // Apply new configuration only if there are some differences - if ($old_named_conf != $new_named_conf ) { - file_put_contents($this->NAMED_CONF,$new_named_conf); - chown($this->NAMED_CONF, 'bind'); - chmod($this->NAMED_CONF, 0640); - exec($this->RNDC." reconfig"); - $hooks->invoke_scripts("/usr/lib/alternc/reload.d", array('dns_reconfig') ); - } - - return true; - } - - - /** - * Regenerate bind configuration and load it - * - * @global m_hooks $hooks - * @param boolean $all - * @return boolean - */ - function regenerate_conf($all=false) { - global $hooks; - - foreach ($this->get_domain_summary() as $domain => $ds ) { - if ( ! $ds['gesdns'] && strtoupper($ds['dns_action']) == 'OK' ) continue; // Skip if we do not manage DNS and is up-to-date for this domain - - if ( (strtoupper($ds['dns_action']) == 'DELETE' ) || - (strtoupper($ds['dns_action']) == 'UPDATE' && $ds['gesdns']==false ) // in case we update the zone to disable DNS management - ) { - $this->delete_zone($domain); - continue; - } - - if ( ( $all || strtoupper($ds['dns_action']) == 'UPDATE' ) && $ds['gesdns'] ) { - $this->save_zone($domain); - $this->reload_zone($domain); - $hooks->invoke_scripts("/usr/lib/alternc/reload.d", array('dns_reload_zone', $domain) ); - } - } // end foreach domain - - $this->dkim_refresh_list(); - $this->reload_named(); - return true; - } - - - /** - * - */ - private function dummy_for_translation() { - _("The zone file of this domain is locked. Contact your administrator."); - } - - } // m_bind diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index bafab4de..8cabd458 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -1442,7 +1442,7 @@ class m_dom { * TRUE sinon. * */ - function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 86400) { + function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 3600) { global $db, $msg, $hooks; $msg->log("dom", "edit_domain", $dom . "/" . $dns . "/" . $gesmx); // Locked ? diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index b7f02735..9a370fe7 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -469,9 +469,9 @@ ORDER BY 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)); + $db->query("UPDATE domaines SET dns_action='UPDATE' WHERE id= ? ;", array($dom_id)); } - + return true; } @@ -912,6 +912,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 +929,7 @@ ORDER BY } + // ------------------------------------------------------------ /** * hook function called by AlternC when a domain is created for * the current user account @@ -937,7 +939,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,8 +949,9 @@ 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()) { + $this->set_dns_autoconf($db->Record["domaine"],$db->Record["compte"]); if ($spf = variable_get("default_spf_value")) { $this->set_dns_spf($db->Record["domaine"], $spf); } @@ -960,13 +963,14 @@ ORDER BY } + // ------------------------------------------------------------ /** * hook function called by variables when a variable is changed * @access private */ function hook_variable_set($name, $old, $new) { global $msg, $db; - $msg->log("mail", "hook_variable_set($name,$old,$new)"); + $msg->log("mail", "hook_variable_set($name,$old,$new)"); if ($name == "default_spf_value") { $new = trim($new); @@ -991,7 +995,34 @@ 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';",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';",array($domain,$uid)); + $changed=true; + } + if ($changed) { + $db->query("UPDATE domaines SET dns_action='UPDATE' WHERE domaine= ?;", array($domain)); + } + return $changed; + } + + + // ------------------------------------------------------------ /** * 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. @@ -1022,6 +1053,7 @@ ORDER BY } + // ------------------------------------------------------------ /** * 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. @@ -1055,5 +1087,110 @@ ORDER BY } + /** 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,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["domaine"]; + } else { + $add[]=$db->Record["domaine"]; + } + } + foreach($add as $domain) { + $this->dkim_add($domain); + } + foreach($del as $domain) { + $this->dkim_del($domain); + } + } + + + // ------------------------------------------------------------ + /** + * 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) { + global $db; + $target_dir = "/etc/opendkim/keys/$domain"; + if (file_exists($target_dir.'/alternc.txt')) return; // Do not generate if exist + $this->shouldreloaddkim=true; + if (! is_dir($target_dir)) mkdir($target_dir); // create dir + // Generate the key + $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 into files: + 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); + // Add subdomaine entry + $dkim_key=$this->dkim_get_entry($domain); + $db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='', type='dkim', valeur=?;",array($uid,$domain,$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) { + $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); + } + } + + + // ------------------------------------------------------------ + /** + * 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) { + $key=file_get_contents("/etc/opendkim/keys/".$domain."/alternc.txt"); + if (preg_match('#alternc._domainkey IN TXT "(.*)"#',$key,$mat)) { + return $mat[1]; + } + return false; + } + + // @TODO hook after reloading DNS zones => if necessary, restart opendkim } /* Class m_mail */ diff --git a/install/mysql.sql b/install/mysql.sql index 2e43504c..4fd129f0 100644 --- a/install/mysql.sql +++ b/install/mysql.sql @@ -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', PRIMARY KEY (id), UNIQUE KEY (domaine) ) ENGINE=InnoDB; @@ -479,8 +479,10 @@ 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'), +INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable) VALUES +('dkim', 'DKIM Key', 'NONE', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN'), +('autodiscover', 'Autodiscover and autoconf for email', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, true, true, 'ADMIN'), + ('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'), diff --git a/install/upgrades/3.5.0.1.sql b/install/upgrades/3.5.0.1.sql index 49fc7f44..0cb4a949 100644 --- a/install/upgrades/3.5.0.1.sql +++ b/install/upgrades/3.5.0.1.sql @@ -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', 'NONE', '%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', 'Autodiscover and autoconf for email', '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 ''; diff --git a/install/upgrades/3.5.0.2.php b/install/upgrades/3.5.0.2.php new file mode 100644 index 00000000..4395db26 --- /dev/null +++ b/install/upgrades/3.5.0.2.php @@ -0,0 +1,32 @@ +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) + ); +} + From f898407d3de2b352906a19e73523029d0241a1d0 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Sun, 8 Jul 2018 22:19:58 +0200 Subject: [PATCH 04/68] [enh] adding update_domains.php in cron, fixing panel to NOT include autodiscover from now --- .gitignore | 1 + debian/alternc.cron.d | 4 +- etc/alternc/templates/alternc/bureau.conf | 18 ------- .../templates/apache2/autodiscover-both.conf | 53 +++++++++++++++++++ src/update_domains.php | 10 ++++ 5 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 etc/alternc/templates/apache2/autodiscover-both.conf create mode 100644 src/update_domains.php diff --git a/.gitignore b/.gitignore index c871c2c5..3c668233 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ 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 diff --git a/debian/alternc.cron.d b/debian/alternc.cron.d index f324f260..0929f5fc 100644 --- a/debian/alternc.cron.d +++ b/debian/alternc.cron.d @@ -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 diff --git a/etc/alternc/templates/alternc/bureau.conf b/etc/alternc/templates/alternc/bureau.conf index 6d677e87..d834648b 100644 --- a/etc/alternc/templates/alternc/bureau.conf +++ b/etc/alternc/templates/alternc/bureau.conf @@ -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 diff --git a/etc/alternc/templates/apache2/autodiscover-both.conf b/etc/alternc/templates/apache2/autodiscover-both.conf new file mode 100644 index 00000000..123a09f3 --- /dev/null +++ b/etc/alternc/templates/apache2/autodiscover-both.conf @@ -0,0 +1,53 @@ + + + DocumentRoot /usr/share/alternc/panel/admin + + AssignUserId alterncpanel alterncpanel + SetEnv LOGIN "0000-panel" + + ServerName %%fqdn%% + + # 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] + + + + + DocumentRoot /usr/share/alternc/panel/admin + + AssignUserId alterncpanel alterncpanel + SetEnv LOGIN "0000-panel" + + ServerName %%fqdn%% + + # 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] + + SSLEngine On + SSLCertificateFile %%CRT%% + SSLCertificateKeyFile %%KEY%% + %%CHAINLINE%% + + diff --git a/src/update_domains.php b/src/update_domains.php new file mode 100644 index 00000000..8589e55e --- /dev/null +++ b/src/update_domains.php @@ -0,0 +1,10 @@ +#!/usr/bin/php -q +update_domains(); + From b6a2f743267ca1556baee0a6620da60c4a8419fc Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 15:02:32 +0200 Subject: [PATCH 05/68] [fix] fix misc bugs at alternc.install time --- bureau/class/m_dom.php | 4 +- src/generate_apache_conf.php | 85 ------------------------------------ src/generate_bind_conf.php | 24 ---------- src/rebuild_all_webconf.sh | 2 - 4 files changed, 2 insertions(+), 113 deletions(-) delete mode 100755 src/generate_apache_conf.php delete mode 100755 src/generate_bind_conf.php diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index 8cabd458..58755dcc 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -1909,7 +1909,7 @@ class m_dom { exit(); } - $dom->lock(); + $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';"); @@ -1982,7 +1982,7 @@ class m_dom { $hooks->invoke("hook_updatedomains_web_post"); } - $dom->unlock(); + $this->unlock(); } diff --git a/src/generate_apache_conf.php b/src/generate_apache_conf.php deleted file mode 100755 index 579d814e..00000000 --- a/src/generate_apache_conf.php +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/php -q -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; - diff --git a/src/generate_bind_conf.php b/src/generate_bind_conf.php deleted file mode 100755 index 4907007d..00000000 --- a/src/generate_bind_conf.php +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/php -q -regenerate_conf($force); - diff --git a/src/rebuild_all_webconf.sh b/src/rebuild_all_webconf.sh index cf7fcefa..176b2587 100755 --- a/src/rebuild_all_webconf.sh +++ b/src/rebuild_all_webconf.sh @@ -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." From f50f45370770bfaa6b9cf765161cedd78a96f2c7 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 15:10:08 +0200 Subject: [PATCH 06/68] [fix] missing global + proper shebang on upgrade script --- bureau/class/m_dom.php | 1 + install/upgrades/3.5.0.2.php | 1 + 2 files changed, 2 insertions(+) diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index 58755dcc..12346c17 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -1904,6 +1904,7 @@ class m_dom { * so that apache & bind could do their job */ function update_domains() { + global $db, $hooks; if (posix_getuid()!=0) { echo "FATAL: please lauch me as root\n"; exit(); diff --git a/install/upgrades/3.5.0.2.php b/install/upgrades/3.5.0.2.php index 4395db26..22c83c15 100644 --- a/install/upgrades/3.5.0.2.php +++ b/install/upgrades/3.5.0.2.php @@ -1,3 +1,4 @@ +#!/usr/bin/php -q Date: Tue, 17 Jul 2018 15:11:31 +0200 Subject: [PATCH 07/68] [fix] no need for www-data to be in ssl-cert group --- install/alternc.install | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/install/alternc.install b/install/alternc.install index acec6919..099ec093 100755 --- a/install/alternc.install +++ b/install/alternc.install @@ -354,9 +354,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 From 7f94d1f03f7525cb246a4f3763ccea6ba948bf27 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 15:21:55 +0200 Subject: [PATCH 08/68] =?UTF-8?q?[fix]=20dpkg-statoverride:=20erreur:=20un?= =?UTF-8?q?e=20d=C3=A9rogation=20pour=20=C2=AB=C2=A0/var/spool/postfix/var?= =?UTF-8?q?/run/saslauthd=C2=A0=C2=BB=20existe=20d=C3=A9j=C3=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/alternc.postinst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/alternc.postinst b/debian/alternc.postinst index 74c973c0..73e436d0 100644 --- a/debian/alternc.postinst +++ b/debian/alternc.postinst @@ -42,8 +42,9 @@ case "$1" in # corriger les permissions du chroot mkdir -p /var/spool/postfix/var/run/saslauthd || true - dpkg-statoverride --quiet --update --add root sasl 710 /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" From 36976cbf24a1c2d9aa0f23c37492759b4eee6335 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 15:22:19 +0200 Subject: [PATCH 09/68] [fix] domislocked should be a global variable (...) since we may need it at php shutdown time :/ --- bureau/class/m_dom.php | 58 +++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index 12346c17..5354218b 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -56,14 +56,6 @@ class m_dom { */ 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; - var $type_local = "VHOST"; var $type_url = "URL"; var $type_ip = "IP"; @@ -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; } @@ -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; } @@ -1098,10 +1091,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; } @@ -1263,10 +1256,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; } @@ -1311,10 +1304,10 @@ class m_dom { * @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; + 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; } @@ -1396,10 +1389,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; } @@ -1443,10 +1436,10 @@ class m_dom { * */ function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 3600) { - global $db, $msg, $hooks; + global $db, $msg, $hooksthis; $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; } @@ -1765,18 +1758,18 @@ 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!")); } // wait for the file to disappear, or at most 15min: - while (file_exists($this->fic_lock_cron) && filemtime($this->fic_lock_cron)>(time()-900)) { + while (file_exists(m_dom::fic_lock_cron) && filemtime(m_dom::fic_lock_cron)>(time()-900)) { clearstatcache(); sleep(2); } - @touch($this->fic_lock_cron); - $this->islocked = true; + @touch(m_dom::fic_lock_cron); + $domislocked = true; // extra safe : register_shutdown_function(array("m_dom","unlock"),1); return true; @@ -1789,13 +1782,14 @@ class m_dom { * @access private */ function unlock($isshutdown=0) { - global $msg; + global $msg,$domislocked; $msg->debug("dom", "unlock"); - if (!$isshutdown && !$this->islocked) { + if (!$isshutdown && !m_dom::islocked) { $msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!")); } - @unlink($this->fic_lock_cron); - $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; } From 74454396542879f50f749e64f0ee6deb6f3ddecb Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 15:50:29 +0200 Subject: [PATCH 10/68] [enh] proper name for autodiscover + fix global in m_dom --- bureau/class/m_dom.php | 4 ++-- install/mysql.sql | 2 +- install/upgrades/3.5.0.1.sql | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index 5354218b..77b8bf64 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -54,7 +54,7 @@ class m_dom { * du domaine par update_domains.sh * @access private */ - var $fic_lock_cron = "/run/alternc/cron.lock"; + const fic_lock_cron = "/run/alternc/cron.lock"; var $type_local = "VHOST"; var $type_url = "URL"; @@ -1784,7 +1784,7 @@ class m_dom { function unlock($isshutdown=0) { global $msg,$domislocked; $msg->debug("dom", "unlock"); - if (!$isshutdown && !m_dom::islocked) { + if (!$isshutdown && !$domislocked) { $msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!")); } // don't use $this since we may be called by register_shutdown_function out of an object instance. diff --git a/install/mysql.sql b/install/mysql.sql index 4fd129f0..26373fd3 100644 --- a/install/mysql.sql +++ b/install/mysql.sql @@ -481,7 +481,7 @@ CREATE TABLE IF NOT EXISTS `domaines_type` ( INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable) VALUES ('dkim', 'DKIM Key', 'NONE', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN'), -('autodiscover', 'Autodiscover and autoconf for email', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, true, true, 'ADMIN'), +('autodiscover', 'Email autoconfiguration', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, true, true, 'ADMIN'), ('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'), diff --git a/install/upgrades/3.5.0.1.sql b/install/upgrades/3.5.0.1.sql index 0cb4a949..2c31a493 100644 --- a/install/upgrades/3.5.0.1.sql +++ b/install/upgrades/3.5.0.1.sql @@ -4,7 +4,7 @@ INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibil ('dkim', 'DKIM Key', 'NONE', '%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', 'Autodiscover and autoconf for email', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, true, true, 'ADMIN'); +('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 :/ ) From dbfc59097b67141ade490d938d8ee1ed8bb96c1a Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 16:07:48 +0200 Subject: [PATCH 11/68] [fix] misc bugs in update_domaines.php, --- bureau/admin/dom_edit.php | 1 - bureau/class/db_mysql.php | 20 ++++++++++++++++++++ bureau/class/m_apache.php | 5 ++++- bureau/class/m_bind.php | 6 +++--- bureau/class/m_dom.php | 9 +++++---- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/bureau/admin/dom_edit.php b/bureau/admin/dom_edit.php index 88d4c629..6986eb6b 100755 --- a/bureau/admin/dom_edit.php +++ b/bureau/admin/dom_edit.php @@ -197,7 +197,6 @@ if (!$r["sub"][$i]["only_dns"]) { __("HTTP and HTTPS"); break; default: - __("Unknown"); break; } } diff --git a/bureau/class/db_mysql.php b/bureau/class/db_mysql.php index 8e5a3c36..9ec79968 100644 --- a/bureau/class/db_mysql.php +++ b/bureau/class/db_mysql.php @@ -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 */ diff --git a/bureau/class/m_apache.php b/bureau/class/m_apache.php index e497e8e1..1c26bd4d 100644 --- a/bureau/class/m_apache.php +++ b/bureau/class/m_apache.php @@ -105,7 +105,10 @@ class m_apache { /** * launched for each FQDN for which we want to delete a vhost template */ - function hook_updatedomains_web_del($subdom) { + function hook_updatedomains_web_del($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; $confdir = $this->vhostroot."/".substr($subdom["compte"],-1)."/".$subdom["compte"]; @unlink($confdir."/".$subdom["fqdn"].".conf"); $this->shouldreload=true; diff --git a/bureau/class/m_bind.php b/bureau/class/m_bind.php index e85b42ad..5610e236 100644 --- a/bureau/class/m_bind.php +++ b/bureau/class/m_bind.php @@ -128,7 +128,7 @@ class m_bind { */ function hook_updatedomains_dns_del($dominfo) { $domain = $dominfo["domaine"]; - if (remove_line_from_file( + if (del_line_from_file( $this->NAMED_CONF, trim(strtr( file_get_contents($this->NAMED_TEMPLATE), @@ -157,7 +157,7 @@ class m_bind { global $msg; if ($this->shouldreload) { $ret=0; - exec($this->rndc." reload 2>&1",$out,$ret); + 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 { @@ -166,7 +166,7 @@ class m_bind { } if ($this->shouldreconfig) { $ret=0; - exec($this->rndc." reload 2>&1",$out,$ret); + exec($this->RNDC." reload 2>&1",$out,$ret); if ($ret!=0) { $msg->raise("ERROR","bind","Error while reconfiguring bind, error code is $ret\n".implode("\n",$out)); } else { diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index 77b8bf64..029fe1c7 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -1065,13 +1065,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; @@ -1920,9 +1921,9 @@ class m_dom { $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(array($onedom))); + $ret = $hooks->invoke("hook_updatedomains_dns_del",array($onedom)); } else { - $ret = $hooks->invoke("hook_updatedomains_dns_add",array(array($onedom))); + $ret = $hooks->invoke("hook_updatedomains_dns_add",array($onedom)); } if ($onedom["dns_action"]=="DELETE") { From cdf07913da5da799f05c017f690b9eaebe796da7 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 16:59:54 +0200 Subject: [PATCH 12/68] [fix] misc bugs in update_domaines.php, --- bureau/admin/html-head.php | 4 ++-- bureau/class/m_apache.php | 6 +++--- bureau/class/m_bind.php | 4 ++-- bureau/class/m_dom.php | 25 +++++++++++++------------ bureau/class/m_mail.php | 16 ++++++++-------- bureau/class/m_ssl.php | 2 +- 6 files changed, 29 insertions(+), 28 deletions(-) diff --git a/bureau/admin/html-head.php b/bureau/admin/html-head.php index 18e9b00f..635ef878 100644 --- a/bureau/admin/html-head.php +++ b/bureau/admin/html-head.php @@ -39,7 +39,7 @@ if (!defined("ALTERNC_PANEL")) exit(); // must be included ;) if (file_exists("styles/style-custom.css") ) { echo ''; } -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 diff --git a/bureau/class/m_apache.php b/bureau/class/m_apache.php index 1c26bd4d..bf69ab54 100644 --- a/bureau/class/m_apache.php +++ b/bureau/class/m_apache.php @@ -44,7 +44,7 @@ class m_apache { // launched for each FQDN for which we want a new vhost template function hook_updatedomains_web_add($subdomid) { - global $msg,$db; + 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(); @@ -85,7 +85,7 @@ class m_apache { "%%redirect%%" => $subdom['valeur'], "%%UID%%" => $subdom['compte'], "%%GID%%" => $subdom['compte'], - "%%mail_account%%" => $subdom['mail'], + "%%mail_account%%" => $subdom['login']."@".$L_FQDN, "%%user%%" => "FIXME", "%%CRT%%" => $cert["cert"], "%%KEY%%" => $cert["key"], @@ -94,7 +94,7 @@ class m_apache { // and write the template $confdir = $this->vhostroot."/".substr($subdom["compte"],-1)."/".$subdom["compte"]; @mkdir($confdir,0755,true); - file_put_contents($confdir."/".$subdom["fqdn"].".conf"); + file_put_contents($confdir."/".$subdom["fqdn"].".conf",$tpl); $this->shouldreload=true; return 0; // shell meaning => OK ;) diff --git a/bureau/class/m_bind.php b/bureau/class/m_bind.php index 5610e236..5b328703 100644 --- a/bureau/class/m_bind.php +++ b/bureau/class/m_bind.php @@ -107,7 +107,7 @@ class m_bind { trim(strtr( file_get_contents($this->NAMED_TEMPLATE), array( - "@@DOMAIN@@" => $DOMAIN, + "@@DOMAIN@@" => $domain, "@@ZONE_FILE@@" => $this->zone_file_directory."/".$domain ) ))) @@ -225,7 +225,7 @@ class m_bind { sd.type=dt.name AND sd.enable IN ('ENABLE', 'ENABLED') ORDER BY ENTRY ;"); - $t=array(); + $t=""; while ($db->next_record()) { $t.= $db->f('entry')."\n"; } diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index 029fe1c7..2261bf6e 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -635,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); } @@ -1302,9 +1302,10 @@ 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) { + 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 ? @@ -1931,7 +1932,7 @@ class m_dom { } 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)); + $db->query("UPDATE domaines SET dns_result=?, dns_action='OK' WHERE domaine=?;",array($returncode,$onedom["domaine"])); } } $hooks->invoke("hook_updatedomains_dns_post"); diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index 9a370fe7..06b158db 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -1099,21 +1099,21 @@ ORDER BY 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,gesdns,gesmx FROM domaines WHERE dns_action!='OK';"); + $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["domaine"]; + $del[]=$db->Record; } else { - $add[]=$db->Record["domaine"]; + $add[]=$db->Record; } } foreach($add as $domain) { - $this->dkim_add($domain); + $this->dkim_add($domain["domaine"],$domain["compte"]); } foreach($del as $domain) { - $this->dkim_del($domain); + $this->dkim_del($domain["domaine"],$domain["compte"]); } } @@ -1134,7 +1134,7 @@ ORDER BY /** * Add a domain into OpenDKIM configuration */ - function dkim_add($domain) { + function dkim_add($domain,$uid) { global $db; $target_dir = "/etc/opendkim/keys/$domain"; if (file_exists($target_dir.'/alternc.txt')) return; // Do not generate if exist @@ -1154,7 +1154,7 @@ ORDER BY add_line_to_file("/etc/opendkim/SigningTable",$domain." alternc._domainkey.".$domain); // Add subdomaine entry $dkim_key=$this->dkim_get_entry($domain); - $db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='', type='dkim', valeur=?;",array($uid,$domain,$dkim_key)); + $db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='', 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 } @@ -1163,7 +1163,7 @@ ORDER BY /** * Delete a domain from OpenDKIM configuration */ - function dkim_del($domain) { + function dkim_del($domain,$uid) { $target_dir = "/etc/opendkim/keys/$domain"; if (file_exists($target_dir)) { $this->shouldreloaddkim=true; diff --git a/bureau/class/m_ssl.php b/bureau/class/m_ssl.php index 69b0a6f0..de486b5b 100644 --- a/bureau/class/m_ssl.php +++ b/bureau/class/m_ssl.php @@ -667,7 +667,7 @@ SELECT ?,?,?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?, ?, sslcsr FROM certificate } $subdom["fqdn"]=$subdom["sub"].(($subdom["sub"])?".":"").$subdom["domaine"]; - list($cert) = $this->get_valid_certs($fqdn, $subdom["provider"]); + list($cert) = $this->get_valid_certs($subdom["fqdn"], $subdom["provider"]); // Edit certif_hosts: $db->query("UPDATE sub_domaines SET certificate_id=? WHERE id=?;",array($cert["id"], $subdom["id"])); } From 1e4f2783d8c8181c687ba8832c02205597f19f0b Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 17:03:28 +0200 Subject: [PATCH 13/68] [fix] bug that make it impossible to launch upgrades properly : alternc_status is overwriten at postinst :/ --- install/mysql.sql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/install/mysql.sql b/install/mysql.sql index 26373fd3..556bd341 100644 --- a/install/mysql.sql +++ b/install/mysql.sql @@ -795,7 +795,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.1.sql'; From e705f377b937774d76fe6d564461d0f61b8e171c Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 17:11:15 +0200 Subject: [PATCH 14/68] [fix] more bugs in update_domaines.php => not renaming vhosts_all.conf.new to vhosts_all.conf.new + ignoring deletion of DNS_ONLY sub_domaines entries --- bureau/class/m_apache.php | 1 + bureau/class/m_dom.php | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/bureau/class/m_apache.php b/bureau/class/m_apache.php index bf69ab54..87767e65 100644 --- a/bureau/class/m_apache.php +++ b/bureau/class/m_apache.php @@ -160,6 +160,7 @@ class m_apache { } closedir($d); fclose($f); + rename($this->vhostroot."/vhosts_all.conf.new", $this->vhostroot."/vhosts_all.conf"); } private function subconcat($f,$root) { diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index 2261bf6e..484a16e4 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -1943,14 +1943,22 @@ class m_dom { $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()) { // only_dns=1 => weird, we should not have web_action SET to something else than OK ... anyway, skip it if ($db->Record["only_dns"]) { - $ignore[]=$db->Record["id"]; + if ($db->Record["web_action"]=="DELETE") { + $delete[]=$db->Record["id"]; + } else { + $ignore[]=$db->Record["id"]; + } } 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)); From 5c32a54edb2b682d81a28ffb8ded8b3a61d7d685 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 17:20:39 +0200 Subject: [PATCH 15/68] [fix] French vs. English in template name :/ + fixing case issue making zone empty --- bureau/class/m_bind.php | 2 +- etc/alternc/templates/bind/templates/named.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bureau/class/m_bind.php b/bureau/class/m_bind.php index 5b328703..12369ef9 100644 --- a/bureau/class/m_bind.php +++ b/bureau/class/m_bind.php @@ -227,7 +227,7 @@ class m_bind { ORDER BY ENTRY ;"); $t=""; while ($db->next_record()) { - $t.= $db->f('entry')."\n"; + $t.= $db->f('ENTRY')."\n"; } return $t; } diff --git a/etc/alternc/templates/bind/templates/named.template b/etc/alternc/templates/bind/templates/named.template index 9c7f7cff..13ed7fb7 100644 --- a/etc/alternc/templates/bind/templates/named.template +++ b/etc/alternc/templates/bind/templates/named.template @@ -1 +1 @@ -zone "@@DOMAINE@@" { type master; file "@@ZONE_FILE@@"; allow-query { any; }; }; +zone "@@DOMAIN@@" { type master; file "@@ZONE_FILE@@"; allow-query { any; }; }; From 3bc65aed3f62985b68b92975b1114d76cccc42f3 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 17:28:14 +0200 Subject: [PATCH 16/68] [fix] substitute variables AFTER mysql queries in bind zone file --- bureau/class/m_bind.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bureau/class/m_bind.php b/bureau/class/m_bind.php index 12369ef9..b8b88d9a 100644 --- a/bureau/class/m_bind.php +++ b/bureau/class/m_bind.php @@ -72,6 +72,10 @@ class m_bind { // 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", @@ -91,9 +95,6 @@ class m_bind { "@@ZONETTL@@" => $ttl, )); - // add the SUBDOMAIN entries - $zone .= $this->conf_from_db($domain); - // add the "END ALTERNC CONF line"; $zone .= ";;; END ALTERNC AUTOGENERATE CONFIGURATION\n"; From e3d2b844189b95da695a5d759d4827d1b7de2879 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 17:39:14 +0200 Subject: [PATCH 17/68] [fix] reading multiline dkim key + fixing autodiscover zone having NULL name --- bureau/class/m_bind.php | 2 +- bureau/class/m_mail.php | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/bureau/class/m_bind.php b/bureau/class/m_bind.php index b8b88d9a..7cb493b8 100644 --- a/bureau/class/m_bind.php +++ b/bureau/class/m_bind.php @@ -223,7 +223,7 @@ class m_bind { sub_domaines sd, domaines_type dt WHERE - sd.type=dt.name + sd.type=dt.name AND sd.enable IN ('ENABLE', 'ENABLED') ORDER BY ENTRY ;"); $t=""; diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index 06b158db..e8496866 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -1007,12 +1007,12 @@ ORDER BY $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';",array($domain,$uid)); + $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';",array($domain,$uid)); + $db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='autoconfig', type='autodiscover', valeur='';",array($domain,$uid)); $changed=true; } if ($changed) { @@ -1184,10 +1184,30 @@ ORDER BY * 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 IN TXT \( "(.*)"#',$key,$mat)) { + $result.=$mat[1]; $inkey=true; continue; + } + if ($inkey && preg_match('# "(.*)" \)#',$key,$mat)) { + $result.=$mat[1]; $inkey=false; break; + } + if ($inkey && preg_match('# "(.*)" #',$key,$mat)) { + $result.=$mat[1]; $inkey=true; continue; + } + } + if ($result) + return $result; } + $msg->debug("mail","dkim_get_entry($domain) failed"); return false; } From 291812ceade845817d379ad3ae32724ab0faddb6 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 17:48:15 +0200 Subject: [PATCH 18/68] fixing dkim get entry function --- bureau/class/m_mail.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index e8496866..15ed9fbb 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -1154,7 +1154,7 @@ ORDER BY add_line_to_file("/etc/opendkim/SigningTable",$domain." alternc._domainkey.".$domain); // Add subdomaine entry $dkim_key=$this->dkim_get_entry($domain); - $db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='', type='dkim', valeur=?;",array($domain,$uid,$dkim_key)); + $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 } @@ -1194,13 +1194,13 @@ ORDER BY $inkey=false; $result=""; $lines=explode("\n",$key); foreach($lines as $line) { - if (preg_match('#alternc._domainkey IN TXT \( "(.*)"#',$key,$mat)) { + if (preg_match('#alternc._domainkey\s+IN\s+TXT\s+\( "(.*)"#',$line,$mat)) { $result.=$mat[1]; $inkey=true; continue; } - if ($inkey && preg_match('# "(.*)" \)#',$key,$mat)) { + if ($inkey && preg_match('#^\s*"(.*)"\s*\)#',$line,$mat)) { $result.=$mat[1]; $inkey=false; break; } - if ($inkey && preg_match('# "(.*)" #',$key,$mat)) { + if ($inkey && preg_match('#^\s*"(.*)"\s*$#',$line,$mat)) { $result.=$mat[1]; $inkey=true; continue; } } From 49e81b55bf20e9e956c3dd776bb09f69e22905d5 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 18:10:39 +0200 Subject: [PATCH 19/68] [fix] add ::1 to slaveip.conf template ... it's 2018 people ! --- etc/alternc/templates/bind/slaveip.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/etc/alternc/templates/bind/slaveip.conf b/etc/alternc/templates/bind/slaveip.conf index 7212d291..2b8aa971 100644 --- a/etc/alternc/templates/bind/slaveip.conf +++ b/etc/alternc/templates/bind/slaveip.conf @@ -5,6 +5,7 @@ acl "allslaves" { { 127.0.0.1; + ::1; //AUTO-SLAVES// }; }; From 1182cada25513ddd54e266a5ee3742b75a111f77 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 18:16:56 +0200 Subject: [PATCH 20/68] [fix] now write ssl cert as ROOT, not as alterncpanel --- bureau/class/m_ssl.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/bureau/class/m_ssl.php b/bureau/class/m_ssl.php index de486b5b..d51de2c3 100644 --- a/bureau/class/m_ssl.php +++ b/bureau/class/m_ssl.php @@ -519,12 +519,6 @@ INSTR(CONCAT(sd.sub,IF(sd.sub!='','.',''),sd.domaine),'.')+1))=? $msg->raise("ERROR","ssl", _("Can't save the Key/Crt/Chain now. Please try later.")); return false; } - $this->write_cert_file(array( - "id"=>$id, - "sslcrt"=>$crt, - "sslkey"=>$key, - "sslchain"=>$chain - )); return $id; } @@ -668,6 +662,7 @@ SELECT ?,?,?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?, ?, sslcsr FROM certificate $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"])); } From 5aeeac1c3100595ea72415ca9a70b669b7a3a29e Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 18:20:06 +0200 Subject: [PATCH 21/68] [fix] cancel button not canceling :/ --- bureau/admin/dom_edit.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bureau/admin/dom_edit.inc.php b/bureau/admin/dom_edit.inc.php index a4a63617..ca64bbdb 100755 --- a/bureau/admin/dom_edit.inc.php +++ b/bureau/admin/dom_edit.inc.php @@ -147,7 +147,7 @@ $dom->unlock(); } ?> - + From e06e2b3abd0efa25dfc2d5d41efad5914711491f Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 18:21:25 +0200 Subject: [PATCH 22/68] dkim domaine type is taking TXT as paramter --- install/mysql.sql | 2 +- install/upgrades/3.5.0.1.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/install/mysql.sql b/install/mysql.sql index 556bd341..89faba08 100644 --- a/install/mysql.sql +++ b/install/mysql.sql @@ -480,7 +480,7 @@ CREATE TABLE IF NOT EXISTS `domaines_type` ( ) ENGINE=InnoDB COMMENT = 'Type of domains allowed'; INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable) VALUES -('dkim', 'DKIM Key', 'NONE', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN'), +('dkim', 'DKIM Key', 'TXT', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN'), ('autodiscover', 'Email autoconfiguration', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, true, true, 'ADMIN'), ('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'), diff --git a/install/upgrades/3.5.0.1.sql b/install/upgrades/3.5.0.1.sql index 2c31a493..f46a1ed4 100644 --- a/install/upgrades/3.5.0.1.sql +++ b/install/upgrades/3.5.0.1.sql @@ -1,7 +1,7 @@ -- 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', 'NONE', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN'); +('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'); From 230d3ffdd87a4b2d2ce48db64277d83c52fd220d Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 18:25:14 +0200 Subject: [PATCH 23/68] [fix] missing global in apache conf --- bureau/class/m_apache.php | 1 + bureau/class/m_ssl.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bureau/class/m_apache.php b/bureau/class/m_apache.php index 87767e65..98f4f17f 100644 --- a/bureau/class/m_apache.php +++ b/bureau/class/m_apache.php @@ -106,6 +106,7 @@ class m_apache { * launched for each FQDN for which we want to delete a vhost template */ function hook_updatedomains_web_del($subdomid) { + global $db; $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; diff --git a/bureau/class/m_ssl.php b/bureau/class/m_ssl.php index d51de2c3..73229021 100644 --- a/bureau/class/m_ssl.php +++ b/bureau/class/m_ssl.php @@ -394,7 +394,7 @@ INSTR(CONCAT(sd.sub,IF(sd.sub!='','.',''),sd.domaine),'.')+1))=? $chain=false; return array( - "cert" => self::KEY_REPOSITORY."/".floor($id/1000)."/".$id.".cert", + "cert" => self::KEY_REPOSITORY."/".floor($id/1000)."/".$id.".pem", "key" => self::KEY_REPOSITORY."/".floor($id/1000)."/".$id.".key", "chain" => $chain ); From e09006b69e1f86b09d00bc947dfd57e774a48a99 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 18:29:57 +0200 Subject: [PATCH 24/68] [fix] fix bad http/https/both switcher --- bureau/admin/dom_edit.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bureau/admin/dom_edit.inc.php b/bureau/admin/dom_edit.inc.php index ca64bbdb..9396c38b 100755 --- a/bureau/admin/dom_edit.inc.php +++ b/bureau/admin/dom_edit.inc.php @@ -130,8 +130,8 @@ $dom->unlock(); From 0b0f08c739e0dffd6b82dbdfab823d3dbe989dd6 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 18:47:49 +0200 Subject: [PATCH 25/68] removing unused code from m_dom, adding translation request for new domaines types --- bureau/class/m_dom.php | 205 +---------------------- phpunit/tests/bureau/class/m_domTest.php | 95 ----------- 2 files changed, 3 insertions(+), 297 deletions(-) diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index 484a16e4..ead61a90 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -1991,200 +1991,6 @@ 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 - */ - $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 "; - } - - $query .= " - order by - m.login, - sd.domaine, - sd.sub;"; - - - $db->query($query, $query_args); - - $r = array(); - while ($db->next_record()) { - $r[$db->Record['sub_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']); - } else { - $check_dup[] = $p['fqdn']; - } - - // 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; - } - - // Return the conf - $ret.= "# Sub_id: " . $p['sub_id'] . "\n" . $tpl; - } - - return $ret; - } - - - /** - * 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(); - while ($db->next_record()) { - $r[strtoupper($db->Record['web_action'])][strtoupper($db->Record['type'])][] = $db->f('sub_id'); - } - return $r; - } - - - 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'; "; - } - $db->query($sql); - return true; - } - - /** * @param string $dns_action */ @@ -2195,15 +2001,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) { @@ -2260,6 +2059,8 @@ class m_dom { _("Default mail server"); _("Default backup mail server"); _("AlternC panel access"); + _("DKIM Key"); + _("Email autoconfiguration"); } } /* Class m_domains */ diff --git a/phpunit/tests/bureau/class/m_domTest.php b/phpunit/tests/bureau/class/m_domTest.php index 12892330..343cceea 100644 --- a/phpunit/tests/bureau/class/m_domTest.php +++ b/phpunit/tests/bureau/class/m_domTest.php @@ -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 From 1716d14b235624871213d6620deb7c07621c1cea Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 17 Jul 2018 18:50:18 +0200 Subject: [PATCH 26/68] [cleanup] removing all unused files from former update_domains.sh --- src/functions_dns.sh | 223 -------------------------------------- src/functions_hosting.sh | 225 --------------------------------------- src/update_domains.sh | 170 ----------------------------- 3 files changed, 618 deletions(-) delete mode 100755 src/functions_dns.sh delete mode 100644 src/functions_hosting.sh diff --git a/src/functions_dns.sh b/src/functions_dns.sh deleted file mode 100755 index 7ec2f602..00000000 --- a/src/functions_dns.sh +++ /dev/null @@ -1,223 +0,0 @@ -#!/bin/bash -# dns.sh next-gen by Fufroma - -# Init some vars -. /etc/alternc/local.sh -. /usr/lib/alternc/functions.sh - -# Init some other vars -ZONE_TEMPLATE="/etc/alternc/templates/bind/templates/zone.template" -NAMED_TEMPLATE="/etc/alternc/templates/bind/templates/named.template" -NAMED_CONF="/var/lib/alternc/bind/automatic.conf" -RNDC="/usr/sbin/rndc" - -dns_zone_file() { - echo "/var/lib/alternc/bind/zones/$1" -} - -dns_is_locked() { - local domain=$1 - if [ ! -r "$(dns_zone_file $domain)" ] ; then - return 1 - fi - grep "LOCKED:YES" "$(dns_zone_file $domain)" - return $? -} - -dns_get_serial() { - local domain=$1 - local serial=$(( $(grep "; serial" $(dns_zone_file $domain) 2>/dev/null|awk '{ print $1;}') + 1 )) - local serial2=$(date +%Y%m%d00) - if [ $serial -gt $serial2 ] ; then - echo $serial - else - echo $serial2 - fi -} - -dns_get_zonettl() { - local domain=$1 - local zonettl=$( - $MYSQL_DO "SELECT zonettl FROM domaines d WHERE d.domaine='$domain';" - ) - # default value - if [ "$zonettl" == "" ] ; then - zonettl="86400" - fi - if [ "$zonettl" -eq "0" ] ; then - zonettl="86400" - fi - echo $zonettl -} - -dns_chmod() { - local domain=$1 - chgrp bind $(dns_zone_file $domain) - chmod 640 $(dns_zone_file $domain) - return 0 -} - -dns_named_conf() { - local domain=$1 - - if [ ! -f "$(dns_zone_file $domain)" ] ; then - echo Error : no file $(dns_zone_file $domain) - return 1 - fi - - # Add the entry - grep -q "\"${domain/./\\.}\"" "$NAMED_CONF" - if [ $? -ne 0 ] ; then - local tempo=$(cat "$NAMED_TEMPLATE") - tempo=${tempo/@@DOMAINE@@/$domain} - tempo=${tempo/@@ZONE_FILE@@/$(dns_zone_file $domain)} - echo $tempo >> "$NAMED_CONF" - # Kindly ask Bind to reload its configuration - # (the zone file is already created and populated) - $RNDC reconfig - # Hook it ! - run-parts --arg=dns_reconfig --arg="$domain" /usr/lib/alternc/reload.d - fi - -} - -dns_delete() { - local domain=$1 - - # Delete the zone file - if [ -w "$(dns_zone_file $domain)" ] ; then - rm -f "$(dns_zone_file $domain)" - fi - - local reg_domain=${domain/./\\.} - - # Remove from the named conf - local file=$(cat "$NAMED_CONF") - echo -e "$file" |grep -v "\"$reg_domain\"" > "$NAMED_CONF" - - # Remove the conf from openDKIM - rm -rf "/etc/opendkim/keys/$domain" - grep -v "^$reg_domain\$" /etc/opendkim/TrustedHosts >/etc/opendkim/TrustedHosts.alternc-tmp && mv /etc/opendkim/TrustedHosts.alternc-tmp /etc/opendkim/TrustedHosts - grep -v "^alternc\._domainkey\.$reg_domain " /etc/opendkim/KeyTable >/etc/opendkim/KeyTable.alternc-tmp && mv /etc/opendkim/KeyTable.alternc-tmp /etc/opendkim/KeyTable - grep -v "^$domain alternc\._domainkey\.$reg_domain\$" /etc/opendkim/SigningTable >/etc/opendkim/SigningTable.alternc-tmp && mv /etc/opendkim/SigningTable.alternc-tmp /etc/opendkim/SigningTable - - # Ask the dns server for restart - $RNDC reconfig - # Hook it ! - run-parts --arg=dns_reconfig --arg="$domain" /usr/lib/alternc/reload.d -} - -# DNS regenerate -dns_regenerate() { - local domain=$1 - local manual_tag=";;; END ALTERNC AUTOGENERATE CONFIGURATION" - local zone_file=$(dns_zone_file $domain) - - # Check if locked - dns_is_locked "$domain" - if [ $? -eq 0 ]; then - echo "DNS $domain LOCKED" - return 1 - fi - - # Get the serial number if there is one - local serial=$(dns_get_serial "$domain") - - # Get the zone ttl - local zonettl=$(dns_get_zonettl "$domain") - - # Generate the headers with the template - local file=$(cat "$ZONE_TEMPLATE") - - # Add the entry - file=$( - echo -e "$file" - $MYSQL_DO "select distinct 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.domaine='$domain' and sd.enable in ('ENABLE', 'ENABLED') order by entry ;" - ) - - ##### Mail autodetect for thunderbird / outlook - START - # If $file contain DEFAULT_MX - if [ ! -z "$(echo -e "$file" |egrep 'DEFAULT_MX' )" ] ; then - # If $file ! contain autoconfig -> add entry - if [ -z "$(echo -e "$file" |egrep '^autoconfig' )" ] ; then - file="$(echo -e "$file" ; echo -e "autoconfig IN CNAME $FQDN.\n")" - fi - # if $file ! contain autodiscover -> add entry - if [ -z "$(echo -e "$file" |egrep '^autodiscover' )" ] ; then - file="$(echo -e "$file" ; echo -e "autodiscover IN CNAME $FQDN.\n")" - fi - fi # End if containt DEFAULT_MX - ##### Mail autodetect for thunderbird / outlook - END - - ##### OpenDKIM signature management - START - # If $file contain DEFAULT_MX - if [ ! -z "$(echo -e "$file" |egrep 'DEFAULT_MX' )" ] ; then - # If necessary, we generate the key: - if [ ! -d "/etc/opendkim/keys/$domain" ] ; then - mkdir -p "/etc/opendkim/keys/$domain" - - pushd "/etc/opendkim/keys/$domain" >/dev/null - opendkim-genkey -r -d "$domain" -s "alternc" - chown opendkim:opendkim alternc.private - popd - - local reg_domain=${domain/./\\.} - - grep -q "^$reg_domain\$" /etc/opendkim/TrustedHosts || echo "$domain" >>/etc/opendkim/TrustedHosts - grep -q "^alternc\._domainkey\.$reg_domain " /etc/opendkim/KeyTable || echo "alternc._domainkey.$domain $domain:alternc:/etc/opendkim/keys/$domain/alternc.private" >> /etc/opendkim/KeyTable - grep -q "^$domain alternc\._domainkey\.$reg_domain\$" /etc/opendkim/SigningTable || echo "$domain alternc._domainkey.$domain" >> /etc/opendkim/SigningTable - fi - # we add alternc._domainkey with the proper key - - if [ -r "/etc/opendkim/keys/$domain/alternc.txt" ] ; then - file="$(echo -e "$file" ; cat "/etc/opendkim/keys/$domain/alternc.txt")" - fi - fi - ##### OpenDKIM signature management - END - - # Replace the vars by their values - # Here we can add dynamic value for the default MX - file=$( echo -e "$file" | sed -e " - s/%%fqdn%%/$FQDN/g; - s/%%ns1%%/$NS1_HOSTNAME/g; - s/%%ns2%%/$NS2_HOSTNAME/g; - s/%%DEFAULT_MX%%/$DEFAULT_MX/g; - s/%%DEFAULT_SECONDARY_MX%%/$DEFAULT_SECONDARY_MX/g; - s/@@fqdn@@/$FQDN/g; - s/@@ns1@@/$NS1_HOSTNAME/g; - s/@@ns2@@/$NS2_HOSTNAME/g; - s/@@DEFAULT_MX@@/$DEFAULT_MX/g; - s/@@DEFAULT_SECONDARY_MX@@/$DEFAULT_SECONDARY_MX/g; - s/@@DOMAINE@@/$domain/g; - s/@@SERIAL@@/$serial/g; - s/@@PUBLIC_IP@@/$PUBLIC_IP/g; - s/@@ZONETTL@@/$zonettl/g; - " ) - - # Add the manually entered resource records (after the special tag ;;; END ALTERNC AUTOGENERATE CONFIGURATION) - if [ -r "$zone_file" ] ; then - file=$( - echo -e "$file" - grep -A 10000 "$manual_tag" "$zone_file" - ) - fi - # Add the special tag at the end of the zone, if it is not here yet: - if ! echo -e "$file" | grep -q "$manual_tag" - then - file=$(echo -e "$file"; echo "$manual_tag") - fi - - # Init the file - echo -e "$file" > "$zone_file" - - # And set his rights - dns_chmod $domain - # Add it to named conf - dns_named_conf $domain - - # Hook it ! - run-parts --arg=dns_reload_zone --arg="$domain" /usr/lib/alternc/reload.d - - # ask bind to reload the zone - $RNDC reload $domain -} diff --git a/src/functions_hosting.sh b/src/functions_hosting.sh deleted file mode 100644 index 61bd7207..00000000 --- a/src/functions_hosting.sh +++ /dev/null @@ -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 -} - diff --git a/src/update_domains.sh b/src/update_domains.sh index 3869ac72..403581e6 100755 --- a/src/update_domains.sh +++ b/src/update_domains.sh @@ -3,173 +3,3 @@ /usr/lib/alternc/update_domains.php -exit - -# legacy code here - -PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - -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 - From af3751742af21e5b262cda3cad3ede683320b35e Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Wed, 18 Jul 2018 10:56:35 +0200 Subject: [PATCH 27/68] [fix] autodiscover vhost had wrong filename --- .../apache2/{autodiscover-both.conf => autodiscover.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename etc/alternc/templates/apache2/{autodiscover-both.conf => autodiscover.conf} (100%) diff --git a/etc/alternc/templates/apache2/autodiscover-both.conf b/etc/alternc/templates/apache2/autodiscover.conf similarity index 100% rename from etc/alternc/templates/apache2/autodiscover-both.conf rename to etc/alternc/templates/apache2/autodiscover.conf From e118f31397599a100156af4b6472c892d8004d95 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Wed, 18 Jul 2018 11:02:50 +0200 Subject: [PATCH 28/68] [fix] opendkim add and del are now idempotent --- bureau/class/m_mail.php | 45 ++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index 15ed9fbb..3570fccd 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -1137,25 +1137,32 @@ ORDER BY function dkim_add($domain,$uid) { global $db; $target_dir = "/etc/opendkim/keys/$domain"; - if (file_exists($target_dir.'/alternc.txt')) return; // Do not generate if exist - $this->shouldreloaddkim=true; - if (! is_dir($target_dir)) mkdir($target_dir); // create dir - // Generate the key - $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 into files: - 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); - // 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 + // 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 + } } @@ -1173,6 +1180,8 @@ ORDER BY 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 } From 13564a9d73643f00a37e749f2e6d11780b8dcab1 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 16 Oct 2018 23:04:46 +0200 Subject: [PATCH 29/68] =?UTF-8?q?[fix]=C2=A0m=5Flxc=20didn't=20work=20on?= =?UTF-8?q?=20new=20=20instead=20of=20...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bureau/class/m_lxc.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bureau/class/m_lxc.php b/bureau/class/m_lxc.php index ed91a883..1f31a3c6 100644 --- a/bureau/class/m_lxc.php +++ b/bureau/class/m_lxc.php @@ -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; } From b4aa7c3957df2cc8bc63117f90c55b895680d4d0 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 16 Oct 2018 23:08:54 +0200 Subject: [PATCH 30/68] =?UTF-8?q?[fix]=C2=A0m=5Fbind.php=20fixing=20reconf?= =?UTF-8?q?ig=20instead=20of=20reload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bureau/class/m_bind.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bureau/class/m_bind.php b/bureau/class/m_bind.php index 7cb493b8..5403de51 100644 --- a/bureau/class/m_bind.php +++ b/bureau/class/m_bind.php @@ -167,7 +167,7 @@ class m_bind { } if ($this->shouldreconfig) { $ret=0; - exec($this->RNDC." reload 2>&1",$out,$ret); + 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 { From fdda4e95e89d95055e47357eaa5ad730b941e34b Mon Sep 17 00:00:00 2001 From: Alexandru Date: Thu, 9 Aug 2018 13:46:25 -0700 Subject: [PATCH 31/68] Fix bind allow-transfer on internal ipv6 --- etc/alternc/templates/bind/named.conf.options | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/alternc/templates/bind/named.conf.options b/etc/alternc/templates/bind/named.conf.options index 68845ef7..df98390a 100644 --- a/etc/alternc/templates/bind/named.conf.options +++ b/etc/alternc/templates/bind/named.conf.options @@ -18,13 +18,13 @@ options { auth-nxdomain no; # conform to RFC1035 allow-query { "internal"; }; - allow-transfer { "allslaves"; }; + allow-transfer { "allslaves"; "internal"; }; recursion no; }; acl "internal" { { - 127.0.0.1; + 127.0.0.1; ::1; }; }; From 8af6b0d1f6fd0465bb9662c495217f113457f79e Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Tue, 31 Jul 2018 15:41:10 -0400 Subject: [PATCH 32/68] Fix condition check for replacing the chainfile statement in vhost templates --- bureau/class/m_ssl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bureau/class/m_ssl.php b/bureau/class/m_ssl.php index 73229021..dcae0c9f 100644 --- a/bureau/class/m_ssl.php +++ b/bureau/class/m_ssl.php @@ -627,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); From e67d628e413ac6d488b9872eb4e88572a6f9681a Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Mon, 22 Oct 2018 17:00:38 +0200 Subject: [PATCH 33/68] =?UTF-8?q?[fix]=C2=A0integration=20of=20PR-290=20:?= =?UTF-8?q?=20Fix=20unit=20test=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 ++++ .travis.yml | 10 ++++++---- bureau/class/m_action.php | 2 +- bureau/class/m_hooks.php | 5 +++++ phpunit/lib/AlterncTest.php | 6 ++++-- phpunit/tests/bureau/class/m_actionTest.php | 2 +- phpunit/tests/bureau/class/m_mailTest.php | 3 +++ 7 files changed, 24 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 3c668233..40be9b0b 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,7 @@ 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/ diff --git a/.travis.yml b/.travis.yml index 40af921b..882336ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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: diff --git a/bureau/class/m_action.php b/bureau/class/m_action.php index 0c0aca29..27351686 100644 --- a/bureau/class/m_action.php +++ b/bureau/class/m_action.php @@ -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; diff --git a/bureau/class/m_hooks.php b/bureau/class/m_hooks.php index 1093b077..0e10746a 100644 --- a/bureau/class/m_hooks.php +++ b/bureau/class/m_hooks.php @@ -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)) { diff --git a/phpunit/lib/AlterncTest.php b/phpunit/lib/AlterncTest.php index d31eb8d3..b9eb7c41 100644 --- a/phpunit/lib/AlterncTest.php +++ b/phpunit/lib/AlterncTest.php @@ -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; } diff --git a/phpunit/tests/bureau/class/m_actionTest.php b/phpunit/tests/bureau/class/m_actionTest.php index 72767e14..d429cb86 100644 --- a/phpunit/tests/bureau/class/m_actionTest.php +++ b/phpunit/tests/bureau/class/m_actionTest.php @@ -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); diff --git a/phpunit/tests/bureau/class/m_mailTest.php b/phpunit/tests/bureau/class/m_mailTest.php index c1bf6a03..d34b7c76 100644 --- a/phpunit/tests/bureau/class/m_mailTest.php +++ b/phpunit/tests/bureau/class/m_mailTest.php @@ -320,6 +320,9 @@ class m_mailTest extends AlterncTest public function testCreate_alias() { // Test #1580 + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); } /** From d06f2877e144452d9b33c4ff3fd4902764036536 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 12 Jul 2018 12:14:12 -0400 Subject: [PATCH 34/68] Normalize spacing in roundcube vhost template --- roundcube/templates/apache2/roundcube.conf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/roundcube/templates/apache2/roundcube.conf b/roundcube/templates/apache2/roundcube.conf index cfa83db1..16911008 100644 --- a/roundcube/templates/apache2/roundcube.conf +++ b/roundcube/templates/apache2/roundcube.conf @@ -20,9 +20,9 @@ # Access to tinymce files - Options +Indexes +MultiViews +FollowSymLinks - AllowOverride None - Require all granted + Options +Indexes +MultiViews +FollowSymLinks + AllowOverride None + Require all granted @@ -56,8 +56,8 @@ Alias /javascript /usr/share/javascript/ - Options +FollowSymLinks +MultiViews - Require all granted + Options +FollowSymLinks +MultiViews + Require all granted SSLEngine On From b2f75383716a50955291f910b7da619f7a58c748 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 12 Jul 2018 12:14:27 -0400 Subject: [PATCH 35/68] Update roundcube vhost template to apache 2.4 --- roundcube/templates/apache2/roundcube.conf | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/roundcube/templates/apache2/roundcube.conf b/roundcube/templates/apache2/roundcube.conf index 16911008..a72c65f6 100644 --- a/roundcube/templates/apache2/roundcube.conf +++ b/roundcube/templates/apache2/roundcube.conf @@ -37,20 +37,19 @@ Options -FollowSymLinks AllowOverride None + Require all denied Options -FollowSymLinks AllowOverride None - Order allow,deny - Deny from all + Require all denied Options -FollowSymLinks AllowOverride None - Order allow,deny - Deny from all + Require all denied Alias /javascript /usr/share/javascript/ From 54f5491dad32606118c8fa1c709f691da9d03e55 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 12 Jul 2018 12:21:55 -0400 Subject: [PATCH 36/68] Remove last vestiges of alternc-roundcube user --- debian/alternc-roundcube.postinst | 5 ----- roundcube/roundcube-install | 9 ++++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/debian/alternc-roundcube.postinst b/debian/alternc-roundcube.postinst index 0d99169d..3acb05bf 100644 --- a/debian/alternc-roundcube.postinst +++ b/debian/alternc-roundcube.postinst @@ -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 diff --git a/roundcube/roundcube-install b/roundcube/roundcube-install index 4e9149b3..8f8cada6 100644 --- a/roundcube/roundcube-install +++ b/roundcube/roundcube-install @@ -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 - From 9052e6ac31aacf5648e711ec76f23f64f76c9373 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 12 Jul 2018 09:59:45 -0400 Subject: [PATCH 37/68] Deploy dovecot configuration for SSL --- install/alternc.install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/alternc.install b/install/alternc.install index 099ec093..611d91f0 100755 --- a/install/alternc.install +++ b/install/alternc.install @@ -112,7 +112,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" From ad201fd4f24d60fe5bb30da9e596dcb162608300 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 12 Jul 2018 09:57:29 -0400 Subject: [PATCH 38/68] Fix syntax error in bro_editor --- bureau/admin/bro_editor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bureau/admin/bro_editor.php b/bureau/admin/bro_editor.php index 558a4517..e07e7133 100755 --- a/bureau/admin/bro_editor.php +++ b/bureau/admin/bro_editor.php @@ -76,7 +76,7 @@ if (isset($save) && $save) { } $addhead['css'][]=''; -$addhead['js'][]='' +$addhead['js'][]=''; include_once("head.php"); ?> From dc1708fecdc7be2ee646b7f235f4d678c8542dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Grenier?= Date: Mon, 9 Jul 2018 21:06:05 -0300 Subject: [PATCH 39/68] [fix] typo? script not crash anymore with unexpected '&' --- src/reload-certs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reload-certs b/src/reload-certs index 33007382..473e5c61 100644 --- a/src/reload-certs +++ b/src/reload-certs @@ -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"); From 1809cd67da093eeded9d1589dd4e4d77a52011d7 Mon Sep 17 00:00:00 2001 From: Dominique Rousseau Date: Wed, 4 Jul 2018 17:04:45 +0200 Subject: [PATCH 40/68] add php config for sys_temp_dir in vhost templates (for PHP 5.4+) --- etc/alternc/templates/apache2/vhost-both.conf | 2 ++ etc/alternc/templates/apache2/vhost-http.conf | 1 + etc/alternc/templates/apache2/vhost-https.conf | 1 + 3 files changed, 4 insertions(+) diff --git a/etc/alternc/templates/apache2/vhost-both.conf b/etc/alternc/templates/apache2/vhost-both.conf index 301834b8..4240975a 100644 --- a/etc/alternc/templates/apache2/vhost-both.conf +++ b/etc/alternc/templates/apache2/vhost-both.conf @@ -7,6 +7,7 @@ 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 @@ 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 diff --git a/etc/alternc/templates/apache2/vhost-http.conf b/etc/alternc/templates/apache2/vhost-http.conf index 5754a8e9..df6165f2 100644 --- a/etc/alternc/templates/apache2/vhost-http.conf +++ b/etc/alternc/templates/apache2/vhost-http.conf @@ -26,6 +26,7 @@ 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 diff --git a/etc/alternc/templates/apache2/vhost-https.conf b/etc/alternc/templates/apache2/vhost-https.conf index 29b80df6..5438454c 100644 --- a/etc/alternc/templates/apache2/vhost-https.conf +++ b/etc/alternc/templates/apache2/vhost-https.conf @@ -20,6 +20,7 @@ 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 From abcc48b77d0c0644ae5544247a4fd34df7ac960b Mon Sep 17 00:00:00 2001 From: alban Date: Tue, 23 Oct 2018 16:35:04 +0200 Subject: [PATCH 41/68] [fix] Translations : remove some fuzzy translations and fix #298 --- bureau/locales/fr_FR/LC_MESSAGES/messages.po | 46 +++++++------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/bureau/locales/fr_FR/LC_MESSAGES/messages.po b/bureau/locales/fr_FR/LC_MESSAGES/messages.po index b4bccefb..fc79eb71 100644 --- a/bureau/locales/fr_FR/LC_MESSAGES/messages.po +++ b/bureau/locales/fr_FR/LC_MESSAGES/messages.po @@ -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 dissier '%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' à é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" From ad17a8715b3b86bcfa5d78ee6d5357279b3f0885 Mon Sep 17 00:00:00 2001 From: alban Date: Tue, 23 Oct 2018 16:37:51 +0200 Subject: [PATCH 42/68] [fix] Translations : fix translations --- bureau/locales/fr_FR/LC_MESSAGES/messages.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bureau/locales/fr_FR/LC_MESSAGES/messages.po b/bureau/locales/fr_FR/LC_MESSAGES/messages.po index fc79eb71..49697126 100644 --- a/bureau/locales/fr_FR/LC_MESSAGES/messages.po +++ b/bureau/locales/fr_FR/LC_MESSAGES/messages.po @@ -1664,7 +1664,7 @@ msgstr "Les fichiers / répertoires %s ont été déplacé avec succès" #: ../admin/bro_main.php:153 msgid "The folder '%s' was successfully renamed to '%s'" -msgstr "Le dissier '%s' a été renommé '%s' avec succès" +msgstr "Le dossier '%s' a été renommé '%s' avec succès" #: ../admin/bro_main.php:155 msgid "The file '%s' was successfully renamed to '%s'" @@ -1684,7 +1684,7 @@ msgstr "Les permissions ont été appliquées avec succès" #: ../admin/bro_main.php:175 msgid "The extraction of the file '%s' succeeded" -msgstr "L'extraction du fichier '%s' à été effectuée 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" From 36fb5288184ffe756a4b34b6624dfdf43fa5879a Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 12 Jul 2018 10:25:57 -0400 Subject: [PATCH 43/68] Deploy alternc.conf apache configuration --- install/alternc.install | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/install/alternc.install b/install/alternc.install index 611d91f0..d6a0b514 100755 --- a/install/alternc.install +++ b/install/alternc.install @@ -393,6 +393,11 @@ if [ -x /usr/sbin/apache2 ]; then a2enconf alternc-ssl fi + 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 $s" fi From c8d814ff68cb8ae1ee581006d7c94e64907b33fa Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 23 Oct 2018 17:59:50 +0200 Subject: [PATCH 44/68] [fix] slave_dns now broken since PR #295 --- src/slave_dns | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/slave_dns b/src/slave_dns index 0b20420e..b63d476c 100644 --- a/src/slave_dns +++ b/src/slave_dns @@ -1,35 +1,33 @@ -#!/bin/bash +#!/usr/bin/php +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" From 020eb932d6cb66b9120d4a16f5dad9db65ed3369 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 23 Oct 2018 18:00:15 +0200 Subject: [PATCH 45/68] [enh] adding php7.0 curl as a suggestion in debian package --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 166cd069..ce11aa61 100644 --- a/debian/control +++ b/debian/control @@ -149,7 +149,7 @@ Depends: debianutils (>= 1.13.1) , dovecot-sieve , dovecot-managesieved , default-mysql-client - , php5-curl + , php5-curl | php7.0-curl , ${misc:Depends} Recommends: quota From 70224f71d6fe4d28aa160ccfc4b1cc860e01ff7e Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 23 Oct 2018 18:46:52 +0200 Subject: [PATCH 46/68] [fix] (for 3.5) fixing autodiscover template --- etc/alternc/templates/apache2/autodiscover.conf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/etc/alternc/templates/apache2/autodiscover.conf b/etc/alternc/templates/apache2/autodiscover.conf index 123a09f3..a68a4120 100644 --- a/etc/alternc/templates/apache2/autodiscover.conf +++ b/etc/alternc/templates/apache2/autodiscover.conf @@ -7,6 +7,7 @@ ServerName %%fqdn%% + RewriteEngine On # Mail autoconfig RewriteRule ^/mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L] RewriteRule ^/mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L] @@ -20,7 +21,8 @@ RewriteRule ^Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L] RewriteRule ^Autodiscover.xml$ mailautoconfig_outlook.php [L] RewriteRule ^autodiscover.xml$ mailautoconfig_outlook.php [L] - + RewriteRule (.*) - [F] + @@ -31,6 +33,7 @@ ServerName %%fqdn%% + RewriteEngine On # Mail autoconfig RewriteRule ^/mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L] RewriteRule ^/mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L] @@ -44,6 +47,7 @@ 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%% From 4770c268d89342634af9ae4f5d1ae3067361182e Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 23 Oct 2018 18:47:25 +0200 Subject: [PATCH 47/68] [fix] (for 3.5) fixing mysql.sql not setting has_https_option to TRUE on vhost --- install/mysql.sql | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/install/mysql.sql b/install/mysql.sql index 89faba08..54027e07 100644 --- a/install/mysql.sql +++ b/install/mysql.sql @@ -479,20 +479,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 -('dkim', 'DKIM Key', 'TXT', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN'), +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'), - ('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') + ('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'; @@ -796,5 +796,5 @@ CREATE TABLE IF NOT EXISTS `certificates` ( -- make it re-exec-proof -- BUT don't overwrite existing value ! -INSERT IGNORE INTO alternc_status SET name='alternc_version',value='3.5.0.1.sql'; +INSERT IGNORE INTO alternc_status SET name='alternc_version',value='3.5.0.2.php'; From ca0ed3dd407c48d309bf052aa91f0602c03fe4e3 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 23 Oct 2018 19:02:15 +0200 Subject: [PATCH 48/68] [fix] (for 3.5) fixing longstanding bug when we didn't deleted (or deleted too many) vhosts files in /var/lib/alternc/apache-vhost/. --- bureau/class/m_apache.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bureau/class/m_apache.php b/bureau/class/m_apache.php index 98f4f17f..8371f039 100644 --- a/bureau/class/m_apache.php +++ b/bureau/class/m_apache.php @@ -106,12 +106,13 @@ class m_apache { * launched for each FQDN for which we want to delete a vhost template */ function hook_updatedomains_web_del($subdomid) { - global $db; + 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"]; - @unlink($confdir."/".$subdom["fqdn"].".conf"); + $deleteme= $subdom["sub"].(($subdom["sub"])?".":"").$subdom["domaine"].".conf"; + @unlink($confdir."/".$deleteme); $this->shouldreload=true; } From b50f028e0e6ddbf46e4ea6440a49ab3b444a3092 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 23 Oct 2018 19:21:22 +0200 Subject: [PATCH 49/68] [fix] (for 3.5) delete DMARC and SPF and DKIM in cascade when del_mx_domain --- bureau/class/m_mail.php | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index 3570fccd..52c90f25 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -466,12 +466,17 @@ 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->dkim_del($domain); + + $db->query("UPDATE domaines SET dns_action='UPDATE' WHERE id= ? ;", array($dom_id)); return true; } @@ -1052,6 +1057,16 @@ 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)); + } + // ------------------------------------------------------------ /** @@ -1087,6 +1102,17 @@ 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; @@ -1113,7 +1139,7 @@ ORDER BY $this->dkim_add($domain["domaine"],$domain["compte"]); } foreach($del as $domain) { - $this->dkim_del($domain["domaine"],$domain["compte"]); + $this->dkim_del($domain["domaine"]); } } @@ -1170,7 +1196,7 @@ ORDER BY /** * Delete a domain from OpenDKIM configuration */ - function dkim_del($domain,$uid) { + function dkim_del($domain) { $target_dir = "/etc/opendkim/keys/$domain"; if (file_exists($target_dir)) { $this->shouldreloaddkim=true; From ad6bb372eab3870170adc89b571ea376738c6176 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 23 Oct 2018 19:23:14 +0200 Subject: [PATCH 50/68] [fix] (for 3.5) delete DMARC and SPF and DKIM in cascade when del_mx_domain --- bureau/class/m_mail.php | 1 + 1 file changed, 1 insertion(+) diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index 52c90f25..ed1c08bc 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -1197,6 +1197,7 @@ ORDER BY * 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; From 27f907ee99cde3dc4e11a2f7ae1f5ec09e08675d Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Tue, 23 Oct 2018 19:27:54 +0200 Subject: [PATCH 51/68] [fix] (for 3.5) delete ALSO autoconf / autodiscover in cascade when del_mx_domain --- bureau/class/m_mail.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index ed1c08bc..7ba99632 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -474,6 +474,7 @@ ORDER BY $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)); @@ -1026,6 +1027,16 @@ ORDER BY 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)); + } // ------------------------------------------------------------ /** From 8c6dcadca043079ea45809f591076a5c2d73cf8a Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 14:58:18 +0200 Subject: [PATCH 52/68] =?UTF-8?q?[fix]=C2=A0fixing=20default=5Fspf=5Fvalue?= =?UTF-8?q?=20and=20default=5Fdmarc=5Fvalue=20NOT=20being=20initialized=20?= =?UTF-8?q?at=20runtime.=20Do=20it=20at=20alternc.instal=20time.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install/alternc.install | 3 +++ install/variables.php | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 install/variables.php diff --git a/install/alternc.install b/install/alternc.install index d6a0b514..4385ddbb 100755 --- a/install/alternc.install +++ b/install/alternc.install @@ -596,6 +596,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` diff --git a/install/variables.php b/install/variables.php new file mode 100644 index 00000000..f07cf92f --- /dev/null +++ b/install/variables.php @@ -0,0 +1,17 @@ +#!/usr/bin/php + Date: Thu, 29 Mar 2018 12:34:05 +0200 Subject: [PATCH 53/68] adding sync-unix-accounts.php, synchronize unix accounts with AlternC ones. not enabled by default, not even installed yet --- src/sync-unix-accounts.php | 167 +++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 src/sync-unix-accounts.php diff --git a/src/sync-unix-accounts.php b/src/sync-unix-accounts.php new file mode 100644 index 00000000..14918394 --- /dev/null +++ b/src/sync-unix-accounts.php @@ -0,0 +1,167 @@ +#!/usr/bin/php +query("SELECT uid,login FROM membres;"); +while ($db->next_record()) { + if (in_array($db->Record["login"],$skip)) continue; + $members[$db->Record["uid"]]=$db->Record["login"]; +} + +$f=fopen("/etc/passwd","rb"); +while ($s=fgets($f,1024)) { + list($user,$pass,$uid,$gid,$gecos,$home,$shell)=explode(":",$s,7); + if ($uid<2000 || $uid>32000 || $uid!=$gid || substr($home,0,strlen($L_ALTERNC_HTML))!=$L_ALTERNC_HTML) continue; + $unix[$uid]=$user; +} + +// print_r($unix); print_r($members); +// $L_ALTERNC_HTML + +// What shall we create / delete ? +$create=array(); +$delete=array(); + +foreach($members as $muid=>$mlogin) { + if (!isset($unix[$muid])) { + $create[$muid]=$mlogin; + } else { + if ($unix[$muid]!=$mlogin) { + $delete[$muid]=1; + } + } +} +foreach($unix as $uuid=>$ulogin) { + if (!isset($members[$uuid])) { + $delete[$uuid]=$ulogin; + } +} + +if (!count($create) && !count($delete)) { + @unlink($lock); + exit(0); +} + +syslog(LOG_INFO,"Will create ".count($create)." Unix account and delete ".count($delete)."."); + + +// print_r($create); print_r($delete); + +// ------------------------------------------------------------ +// /ETC/PASSWD +copy("/etc/passwd","/etc/passwd.bak"); +$f=fopen("/etc/passwd","rb"); +flock($f,LOCK_EX); +$g=fopen("/etc/passwd.alternc","wb"); +$lastwascr=false; +while ($s=fgets($f,1024)) { + list($user,$pass,$uid,$gid,$gecos,$home,$shell)=explode(":",$s,7); + if ($uid<2000 || $uid>32000 || $uid!=$gid + || substr($home,0,strlen($L_ALTERNC_HTML))!=$L_ALTERNC_HTML + || !isset($delete[$uid]) + ) { + fputs($g,$s); + $lastwascr = (substr($s,-1)=="\n"); + } +} +if (!$lastwascr) { // last line didn't end by \n !! normalize it: + fputs($g,"\n"); +} +foreach($create as $uid=>$login) { + fputs($g,$login.":x:".$uid.":".$uid.":,,,:".$L_ALTERNC_HTML."/".substr($login,0,1)."/".$login.":$newshell\n"); +} +fclose($f); +fclose($g); +rename("/etc/passwd.alternc","/etc/passwd"); +syslog(LOG_INFO,"Wrote /etc/passwd"); + +// ------------------------------------------------------------ +// /ETC/GROUP +copy("/etc/group","/etc/group.bak"); +$f=fopen("/etc/group","rb"); +flock($f,LOCK_EX); +$g=fopen("/etc/group.alternc","wb"); +$lastwascr=false; +while ($s=fgets($f,1024)) { + list($user,$pass,$gid,$users)=explode(":",$s,4); + if ($gid<2000 || $gid>32000 + || !isset($delete[$gid]) + ) { + fputs($g,$s); + $lastwascr = (substr($s,-1)=="\n"); + } +} +if (!$lastwascr) { // last line didn't end by \n !! normalize it: + fputs($g,"\n"); +} +foreach($create as $uid=>$login) { + fputs($g,$login.":x:".$uid.":\n"); +} +fclose($f); +fclose($g); +rename("/etc/group.alternc","/etc/group"); +syslog(LOG_INFO,"Wrote /etc/group"); + +// ------------------------------------------------------------ +// /ETC/SHADOW +copy("/etc/shadow","/etc/shadow.bak"); +$f=fopen("/etc/shadow","rb"); +flock($f,LOCK_EX); +$g=fopen("/etc/shadow.alternc","wb"); +$lastwascr=false; +while ($s=fgets($f,1024)) { + list($user,$pass,$rest)=explode(":",$s,3); + if ( + !in_array($user,$delete) + ) { + fputs($g,$s); + $lastwascr = (substr($s,-1)=="\n"); + } +} +if (!$lastwascr) { // last line didn't end by \n !! normalize it: + fputs($g,"\n"); +} +foreach($create as $uid=>$login) { + fputs($g,$login.":*:17380:0:99999:7:::\n"); +} +fclose($f); +fclose($g); +chmod("/etc/shadow.alternc",0640); +rename("/etc/shadow.alternc","/etc/shadow"); +syslog(LOG_INFO,"Wrote /etc/shadow"); + +if (count($create)) syslog(LOG_INFO,"Wrote unix system files, ADDED:".implode(" ",$create)); +if (count($delete)) syslog(LOG_INFO,"Wrote unix system files, DELETED:".implode(" ",$delete)); + + +@unlink($lock); From 6ae5e22c315664cd6d5d32d6a84c0650ecc19272 Mon Sep 17 00:00:00 2001 From: azerttyu Date: Mon, 30 Apr 2018 10:47:12 +0200 Subject: [PATCH 54/68] Revert "adding sync-unix-accounts.php, synchronize unix accounts with AlternC ones. not enabled by default, not even installed yet" * We revert this commit as it's provided by an AlternC plugin * Report to https://github.com/alternc/alternc-nss to get more informations Note : This reverts commit 240a7738fc0aa1626b49c4f072b1e80cfd2c0d48. --- src/sync-unix-accounts.php | 167 ------------------------------------- 1 file changed, 167 deletions(-) delete mode 100644 src/sync-unix-accounts.php diff --git a/src/sync-unix-accounts.php b/src/sync-unix-accounts.php deleted file mode 100644 index 14918394..00000000 --- a/src/sync-unix-accounts.php +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/php -query("SELECT uid,login FROM membres;"); -while ($db->next_record()) { - if (in_array($db->Record["login"],$skip)) continue; - $members[$db->Record["uid"]]=$db->Record["login"]; -} - -$f=fopen("/etc/passwd","rb"); -while ($s=fgets($f,1024)) { - list($user,$pass,$uid,$gid,$gecos,$home,$shell)=explode(":",$s,7); - if ($uid<2000 || $uid>32000 || $uid!=$gid || substr($home,0,strlen($L_ALTERNC_HTML))!=$L_ALTERNC_HTML) continue; - $unix[$uid]=$user; -} - -// print_r($unix); print_r($members); -// $L_ALTERNC_HTML - -// What shall we create / delete ? -$create=array(); -$delete=array(); - -foreach($members as $muid=>$mlogin) { - if (!isset($unix[$muid])) { - $create[$muid]=$mlogin; - } else { - if ($unix[$muid]!=$mlogin) { - $delete[$muid]=1; - } - } -} -foreach($unix as $uuid=>$ulogin) { - if (!isset($members[$uuid])) { - $delete[$uuid]=$ulogin; - } -} - -if (!count($create) && !count($delete)) { - @unlink($lock); - exit(0); -} - -syslog(LOG_INFO,"Will create ".count($create)." Unix account and delete ".count($delete)."."); - - -// print_r($create); print_r($delete); - -// ------------------------------------------------------------ -// /ETC/PASSWD -copy("/etc/passwd","/etc/passwd.bak"); -$f=fopen("/etc/passwd","rb"); -flock($f,LOCK_EX); -$g=fopen("/etc/passwd.alternc","wb"); -$lastwascr=false; -while ($s=fgets($f,1024)) { - list($user,$pass,$uid,$gid,$gecos,$home,$shell)=explode(":",$s,7); - if ($uid<2000 || $uid>32000 || $uid!=$gid - || substr($home,0,strlen($L_ALTERNC_HTML))!=$L_ALTERNC_HTML - || !isset($delete[$uid]) - ) { - fputs($g,$s); - $lastwascr = (substr($s,-1)=="\n"); - } -} -if (!$lastwascr) { // last line didn't end by \n !! normalize it: - fputs($g,"\n"); -} -foreach($create as $uid=>$login) { - fputs($g,$login.":x:".$uid.":".$uid.":,,,:".$L_ALTERNC_HTML."/".substr($login,0,1)."/".$login.":$newshell\n"); -} -fclose($f); -fclose($g); -rename("/etc/passwd.alternc","/etc/passwd"); -syslog(LOG_INFO,"Wrote /etc/passwd"); - -// ------------------------------------------------------------ -// /ETC/GROUP -copy("/etc/group","/etc/group.bak"); -$f=fopen("/etc/group","rb"); -flock($f,LOCK_EX); -$g=fopen("/etc/group.alternc","wb"); -$lastwascr=false; -while ($s=fgets($f,1024)) { - list($user,$pass,$gid,$users)=explode(":",$s,4); - if ($gid<2000 || $gid>32000 - || !isset($delete[$gid]) - ) { - fputs($g,$s); - $lastwascr = (substr($s,-1)=="\n"); - } -} -if (!$lastwascr) { // last line didn't end by \n !! normalize it: - fputs($g,"\n"); -} -foreach($create as $uid=>$login) { - fputs($g,$login.":x:".$uid.":\n"); -} -fclose($f); -fclose($g); -rename("/etc/group.alternc","/etc/group"); -syslog(LOG_INFO,"Wrote /etc/group"); - -// ------------------------------------------------------------ -// /ETC/SHADOW -copy("/etc/shadow","/etc/shadow.bak"); -$f=fopen("/etc/shadow","rb"); -flock($f,LOCK_EX); -$g=fopen("/etc/shadow.alternc","wb"); -$lastwascr=false; -while ($s=fgets($f,1024)) { - list($user,$pass,$rest)=explode(":",$s,3); - if ( - !in_array($user,$delete) - ) { - fputs($g,$s); - $lastwascr = (substr($s,-1)=="\n"); - } -} -if (!$lastwascr) { // last line didn't end by \n !! normalize it: - fputs($g,"\n"); -} -foreach($create as $uid=>$login) { - fputs($g,$login.":*:17380:0:99999:7:::\n"); -} -fclose($f); -fclose($g); -chmod("/etc/shadow.alternc",0640); -rename("/etc/shadow.alternc","/etc/shadow"); -syslog(LOG_INFO,"Wrote /etc/shadow"); - -if (count($create)) syslog(LOG_INFO,"Wrote unix system files, ADDED:".implode(" ",$create)); -if (count($delete)) syslog(LOG_INFO,"Wrote unix system files, DELETED:".implode(" ",$delete)); - - -@unlink($lock); From 5a5fc801f8337e4aa0351b1f5726e8617440679b Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 14 Jun 2018 14:12:14 -0400 Subject: [PATCH 55/68] Generate opendkim configuration in stretch when alternc.install is run The default configuration in stretch doesn't work very well and needs a couple of tweaks. This will generate the service files and make sure opendkim is run as the opendkim user instead of root. The alternc opendkim.conf template is updated so that the connection can be made locally through a socket. --- etc/alternc/templates/opendkim.conf | 4 ++++ install/alternc.install | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/etc/alternc/templates/opendkim.conf b/etc/alternc/templates/opendkim.conf index 7499491f..d2edbb7c 100644 --- a/etc/alternc/templates/opendkim.conf +++ b/etc/alternc/templates/opendkim.conf @@ -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 \ No newline at end of file diff --git a/install/alternc.install b/install/alternc.install index 4385ddbb..0f1e84e8 100755 --- a/install/alternc.install +++ b/install/alternc.install @@ -649,6 +649,15 @@ touch /etc/opendkim/TrustedHosts /etc/opendkim/SigningTable /etc/opendkim/KeyTab grep -q "^127.0.0.1\$" /etc/opendkim/TrustedHosts || echo "127.0.0.1" >>/etc/opendkim/TrustedHosts 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 [ "$(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 '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" From 4371bb59d58d3d94abb6b4c088dfac74b69c98ac Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Thu, 14 Jun 2018 15:00:09 -0400 Subject: [PATCH 56/68] Fix sed invocation to it runs in-place --- install/alternc.install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/alternc.install b/install/alternc.install index 0f1e84e8..692460d5 100755 --- a/install/alternc.install +++ b/install/alternc.install @@ -654,7 +654,7 @@ if [ "$(lsb_release -s -c)" == 'stretch' ] ; then # 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 's/inet:8891@127.0.0.1/& -u opendkim/' /etc/systemd/system/opendkim.service.d/override.conf + 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 From 7e8d5487e3573365dbd9eefe07b0521ef5696f62 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 15:38:06 +0200 Subject: [PATCH 57/68] [fix] (for 3.5) adding has https option for autodiscover type --- install/mysql.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/mysql.sql b/install/mysql.sql index 54027e07..a0b014b2 100644 --- a/install/mysql.sql +++ b/install/mysql.sql @@ -481,7 +481,7 @@ CREATE TABLE IF NOT EXISTS `domaines_type` ( 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'), +('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), From 15ec54d41c750c41fe83591bf11c58d716ec201d Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 15:49:21 +0200 Subject: [PATCH 58/68] =?UTF-8?q?[fix]=C2=A0adding=20SYSTEMD=20detection?= =?UTF-8?q?=20in=20alternc.install=20to=20run=20opendkim=20properly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install/alternc.install | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/install/alternc.install b/install/alternc.install index 692460d5..b56eaf55 100755 --- a/install/alternc.install +++ b/install/alternc.install @@ -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 @@ -649,7 +657,8 @@ touch /etc/opendkim/TrustedHosts /etc/opendkim/SigningTable /etc/opendkim/KeyTab grep -q "^127.0.0.1\$" /etc/opendkim/TrustedHosts || echo "127.0.0.1" >>/etc/opendkim/TrustedHosts 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 [ "$(lsb_release -s -c)" == 'stretch' ] ; then + +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. From 6ee74b5b039819a84adeb47b660b46ac1e577ce5 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 15:55:21 +0200 Subject: [PATCH 59/68] [fix] adding variables.php for SPF and DKIM patch. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 20bd31b9..9c885ebc 100644 --- a/Makefile +++ b/Makefile @@ -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: From 5fb091660e1605fce46d785b4d0fd66e158fe945 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 15:55:39 +0200 Subject: [PATCH 60/68] =?UTF-8?q?[fix]=C2=A0error=20with=20dom=20lock=20in?= =?UTF-8?q?=20m=5Fdom?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bureau/class/m_dom.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bureau/class/m_dom.php b/bureau/class/m_dom.php index ead61a90..7d94e238 100644 --- a/bureau/class/m_dom.php +++ b/bureau/class/m_dom.php @@ -1438,7 +1438,7 @@ class m_dom { * */ function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 3600) { - global $db, $msg, $hooksthis; + global $db, $msg, $hooks, $domislocked; $msg->log("dom", "edit_domain", $dom . "/" . $dns . "/" . $gesmx); // Locked ? if (!$domislocked && !$force) { From f5d153c16197e5265a09d8abc8b1bb6e6d71abc7 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 16:14:45 +0200 Subject: [PATCH 61/68] [fix] removing apache_logformat from tar --- install/alternc.install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/alternc.install b/install/alternc.install index b56eaf55..b098c48e 100755 --- a/install/alternc.install +++ b/install/alternc.install @@ -99,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" From 74cbc88fc136c23070b2d06085e24a3146f87696 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 16:15:29 +0200 Subject: [PATCH 62/68] [fix] adding lsb-release dependency --- debian/control | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/control b/debian/control index ce11aa61..a8143360 100644 --- a/debian/control +++ b/debian/control @@ -63,6 +63,7 @@ Depends: debianutils (>= 1.13.1) , php5-curl | php7.0-curl , quota , pwgen + , lsb-release , ${misc:Depends} Recommends: default-mysql-server , ntp @@ -150,6 +151,7 @@ Depends: debianutils (>= 1.13.1) , dovecot-managesieved , default-mysql-client , php5-curl | php7.0-curl + , lsb-release , ${misc:Depends} Recommends: quota From fa1fae9af788474ada91793fa665fe365e9dbdcf Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 16:47:39 +0200 Subject: [PATCH 63/68] =?UTF-8?q?[fix]=C2=A0adding=20mysql-server=20or=20m?= =?UTF-8?q?ariadb-server=20in=20dependencies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debian/control | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/control b/debian/control index a8143360..abb8b2e2 100644 --- a/debian/control +++ b/debian/control @@ -59,13 +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 @@ -149,7 +149,7 @@ 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 , lsb-release , ${misc:Depends} From 654edab277729aaff9a1d33bd4bc531edd52d728 Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 16:47:52 +0200 Subject: [PATCH 64/68] =?UTF-8?q?[fix]=C2=A0=20simplify=20restart=20of=20s?= =?UTF-8?q?ervices=20for=20apache2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install/alternc.install | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/install/alternc.install b/install/alternc.install index b098c48e..c367e367 100755 --- a/install/alternc.install +++ b/install/alternc.install @@ -373,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 @@ -406,7 +405,7 @@ if [ -x /usr/sbin/apache2 ]; then a2enconf alternc fi - SERVICES="$SERVICES $s" + SERVICES="$SERVICES apache2" fi # Manage sudoers.d include appearing in Squeeze: From 6a4ee2dc3b291d95c260cea474c7e8af1cab17f2 Mon Sep 17 00:00:00 2001 From: alban Date: Thu, 25 Oct 2018 17:27:16 +0200 Subject: [PATCH 65/68] [fix] fixperms should have a -h option and colors --- src/fixperms.sh | 58 ++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/src/fixperms.sh b/src/fixperms.sh index bd39c977..938167c9 100755 --- a/src/fixperms.sh +++ b/src/fixperms.sh @@ -22,36 +22,47 @@ # Purpose of file: Fix permission, ACL and ownership of AlternC's files # ---------------------------------------------------------------------- # +red () { echo -e "\e[31m$@ \e[0m" ; } +usage () { + [[ -n "$@" ]] && red "$@\n" + cat<// -# 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/// + 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" +LOCK_FIXPERMS="/tmp/test" 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" @@ -79,17 +90,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 From a3627a5f35a51edd88dcc6bf8a45e372423b0e05 Mon Sep 17 00:00:00 2001 From: alban Date: Thu, 25 Oct 2018 17:30:22 +0200 Subject: [PATCH 66/68] [fix] + fixperms should have a -h option and colors --- src/fixperms.sh | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/fixperms.sh b/src/fixperms.sh index 938167c9..7bf4bc49 100755 --- a/src/fixperms.sh +++ b/src/fixperms.sh @@ -42,7 +42,6 @@ query="SELECT uid,login FROM membres ORDER BY login" sub_dir="" file="" LOCK_FIXPERMS="/etc/alternc/disable_all_fixperms" -LOCK_FIXPERMS="/tmp/test" if [ -f "$LOCK_FIXPERMS" ] ; then @@ -67,16 +66,14 @@ do 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") From 03e1786159339ebae8c572d6f106eb5ddfdee5ee Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Thu, 25 Oct 2018 17:33:21 +0200 Subject: [PATCH 67/68] =?UTF-8?q?[fix]=C2=A0fix=20dmarc=20and=20spf=20not?= =?UTF-8?q?=20working?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bureau/class/m_mail.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index 7ba99632..bb5aee2a 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -957,12 +957,14 @@ ORDER BY // set spf & dmarc for this domain $db->query("SELECT domaine,compte FROM domaines WHERE id= ?;", array($domain_id)); if ($db->next_record()) { - $this->set_dns_autoconf($db->Record["domaine"],$db->Record["compte"]); + $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); @@ -1046,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); @@ -1087,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); From 7a6d800e21b9d3fc1b2ad26fef5159e95fd84954 Mon Sep 17 00:00:00 2001 From: alban Date: Fri, 26 Oct 2018 16:43:39 +0200 Subject: [PATCH 68/68] [fix] apache2.conf should Satisfy Any by default --- etc/alternc/templates/alternc/apache2.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/etc/alternc/templates/alternc/apache2.conf b/etc/alternc/templates/alternc/apache2.conf index e37d29e4..444e8b78 100644 --- a/etc/alternc/templates/alternc/apache2.conf +++ b/etc/alternc/templates/alternc/apache2.conf @@ -14,6 +14,7 @@ AssignUserId www-data www-data Options +FollowSymLinks AllowOverride None Require all denied + Satisfy Any #### End security parameters