From b0b0fa408e3c5e836e939fff5507b5d5edf6772e Mon Sep 17 00:00:00 2001 From: Benjamin Sonntag Date: Wed, 17 Jun 2015 19:56:51 +0200 Subject: [PATCH] adding experimental DMARC (relax) and SPF (relax) default support --- bureau/class/m_mail.php | 99 +++++++++++++++++++++++++++++++++++- bureau/class/variables.php | 2 + debian/changelog | 1 + install/upgrades/3.4.2.sql | 1 - install/upgrades/3.4.2~a.php | 22 ++++++++ 5 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 install/upgrades/3.4.2~a.php diff --git a/bureau/class/m_mail.php b/bureau/class/m_mail.php index 9a1bd600..f6d63704 100644 --- a/bureau/class/m_mail.php +++ b/bureau/class/m_mail.php @@ -451,6 +451,12 @@ ORDER BY $this->delete($one["id"]); } } + $db->query("SELECT domaine FROM domaines WHERE id=$domain_id;"); + if ($db->next_record()) { + $db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine='".addslashes($db->Record["domaine"])."' AND type='txt' AND sub='' AND (valeur LIKE 'v=spf1 %' OR valeur LIKE 'v=dmarc1;%');"); + $db->query("UPDATE domaines SET dns_action='UPDATE' WHERE id=$domain_id;"); + } + return true; } @@ -907,11 +913,102 @@ ORDER BY return false; } $mailname=$db->f("value"); - + // set spf & dmarc for this domain + $db->query("SELECT domaine FROM domaines WHERE id=$domain_id;"); + if ($db->next_record()) { + if ($spf=variable_get("default_spf_value")) { + $this->set_dns_spf($db->Record["domaine"],$spf); + } + if ($dmarc=variable_get("default_dmarc_value")) { + $this->set_dns_dmarc($db->Record["domaine"],$dmarc); + } + } return $this->create_alias($domain_id, 'postmaster', $mem->user['login'].'@'.$mailname ); } + /* ----------------------------------------------------------------- */ + /** hook function called by variables when a variable is changed + * @access private + */ + function hook_variable_set($name,$old,$new) { + global $err, $db; + $err->log("mail","hook_variable_set($name,$old,$new)"); + + if ($name=="default_spf_value") { + $new=trim($new); + $old=trim($old); + $db->query("SELECT domaine,login,compte FROM domaines, membres WHERE gesdns=1 AND gesmx=1 and membres.uid=domaines.compte;"); + while ($db->next_record()) { + $this->set_dns_spf($db->Record["domaine"],$new,$old,$db->Record["compte"],$db->Record["login"]); + } + } + + if ($name=="default_dmarc_value") { + $new=trim($new); + $old=trim($old); + $db->query("SELECT domaine,login,compte FROM domaines, membres WHERE gesdns=1 AND gesmx=1 and membres.uid=domaines.compte;"); + while ($db->next_record()) { + $this->set_dns_dmarc($db->Record["domaine"],$new,$old,$db->Record["compte"],$db->Record["login"]); + } + } + + } + + + /* ----------------------------------------------------------------- */ + /** 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. + * don't change spf if current value is not $old + * @access private + */ + function set_dns_spf($domain, $spf, $previous=-1, $uid=-1, $login=-1) { + global $db, $cuid, $dom, $mem; + // defaults + if ($uid===-1) $uid=intval($cuid); else $uid=intval($uid); + if ($login===-1) $login=$mem->user["login"]; + // Search for the record in sub_domaines table + $db->query("SELECT * FROM sub_domaines WHERE compte=$uid AND domaine='".addslashes($domain)."' AND sub='' AND type='txt' AND valeur LIKE 'v=spf1 %' AND web_action!='DELETE';"); + if ($db->next_record()) { + if ($previous!==-1 && $db->Record["valeur"]=="v=spf1 ".$spf) { + return; // skip, no change asked. + } + $db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE id='".$db->Record["id"]."';"); + } + $db->query("INSERT INTO sub_domaines SET compte=$uid, domaine='".addslashes($domain)."', sub='', type='txt', valeur='".addslashes("v=spf1 ".$spf)."', web_action='UPDATE';"); + $db->query("UPDATE domaines SET dns_action='UPDATE' WHERE domaine='".addslashes($domain)."';"); + } + + + + /* ----------------------------------------------------------------- */ + /** Set or UPDATE the DNS record for the domain $dom(str) to be $dmarc + * account's login is current and if not it's $login. + * don't change dmarc if current value is not $old + * @access private + */ + function set_dns_dmarc($domain, $dmarc, $previous=-1, $uid=-1, $login=-1) { + global $db, $cuid, $dom, $mem, $L_FQDN; + // defaults + if ($uid===-1) $uid=intval($cuid); else $uid=intval($uid); + if ($login===-1) $login=$mem->user["login"]; + $dmarc=str_replace("%%ADMINMAIL%%","admin@".$L_FQDN,$dmarc); + $dmarc=str_replace("%%USERMAIL%%",$login."@".$L_FQDN,$dmarc); + + // Search for the record in sub_domaines table + $db->query("SELECT * FROM sub_domaines WHERE compte=$uid AND domaine='".addslashes($domain)."' AND sub='' AND type='txt' AND valeur LIKE 'v=dmarc1;%' AND web_action!='DELETE';"); + if ($db->next_record()) { + if ($previous!==-1 && $db->Record["valeur"]=="v=dmarc1;".$dmarc) { + return; // skip, no change asked. + } + $db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE id='".$db->Record["id"]."';"); + } + $db->query("INSERT INTO sub_domaines SET compte=$uid, domaine='".addslashes($domain)."', sub='', type='txt', valeur='".addslashes("v=dmarc1;".$dmarc)."', web_action='UPDATE';"); + $db->query("UPDATE domaines SET dns_action='UPDATE' WHERE domaine='".addslashes($domain)."';"); + } + + + /* ----------------------------------------------------------------- */ /** hook function called by AlternC-upnp to know which open diff --git a/bureau/class/variables.php b/bureau/class/variables.php index e7ec3bf6..212f5b5e 100644 --- a/bureau/class/variables.php +++ b/bureau/class/variables.php @@ -118,6 +118,7 @@ function variable_set($name, $value, $comment=null) { $value2 = serialize($value); } if (!array_key_exists($name,$conf) || $value!=$conf[$name]) { + $previous=$conf[$name]; $conf[$name] = $value; if ( empty($comment) ) { @@ -127,6 +128,7 @@ function variable_set($name, $value, $comment=null) { $query = "INSERT INTO variable (name, value, comment) values ('".$name."', '".addslashes($value2)."', '$comment') on duplicate key update name='$name', value='$value', comment='$comment';"; } $db->query($query); + $hooks->invoke("hook_variable_set", array("name" => $name, "old"=> $previous, "new"=>$value ) ); } } diff --git a/debian/changelog b/debian/changelog index 473bbecc..0dd0b1e9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,6 +9,7 @@ alternc (3.1.7) oldoldstable; urgency=low * fix added /run/alternc in open_basedir, fix ACTIONS not working * fix permission in browser not working * fix FTP access security UX + * enh add DMARC and SPF management for gesmx & gesdns domains through variables -- Benjamin Sonntag Thu, 16 Jun 2015 16:10:12 +0200 diff --git a/install/upgrades/3.4.2.sql b/install/upgrades/3.4.2.sql index 3dfde5ee..6f40fe46 100644 --- a/install/upgrades/3.4.2.sql +++ b/install/upgrades/3.4.2.sql @@ -6,4 +6,3 @@ UPDATE domaines_type SET compatibility=REPLACE(compatibility, 'cname,',''); ALTER TABLE actions CHANGE `type` `type` enum('CREATE_FILE','FIX_USER','CREATE_DIR','DELETE','MOVE','FIX_DIR','FIX_FILE','CHMOD') DEFAULT NULL; - diff --git a/install/upgrades/3.4.2~a.php b/install/upgrades/3.4.2~a.php new file mode 100644 index 00000000..449ea99d --- /dev/null +++ b/install/upgrades/3.4.2~a.php @@ -0,0 +1,22 @@ +#!/usr/bin/php +