aboutsummaryrefslogtreecommitdiffstats
path: root/config/postfix/postfix.inc
diff options
context:
space:
mode:
authormarcelloc <marcellocoutinho@gmail.com>2011-09-05 15:32:33 -0300
committerCharlie <root@srvchunk01.trf1.jus.br>2011-09-05 15:32:33 -0300
commit548dfb250399802d0908fb7e93e24a4656e7e0f2 (patch)
treedc88ed322eaab90f119bf052e6a0162ab7a08dcb /config/postfix/postfix.inc
parentd0e3555d5741960af91a0ebe504faddc31bea381 (diff)
downloadpfsense-packages-548dfb250399802d0908fb7e93e24a4656e7e0f2.tar.gz
pfsense-packages-548dfb250399802d0908fb7e93e24a4656e7e0f2.tar.bz2
pfsense-packages-548dfb250399802d0908fb7e93e24a4656e7e0f2.zip
Postfix Forwarder package v2
postfix + postscreen + rbl + spf + ldap search Author: marcelloc <marcellocoutinho@gmail.com>
Diffstat (limited to 'config/postfix/postfix.inc')
-rw-r--r--config/postfix/postfix.inc651
1 files changed, 628 insertions, 23 deletions
diff --git a/config/postfix/postfix.inc b/config/postfix/postfix.inc
index cf470c8f..2a762ae4 100644
--- a/config/postfix/postfix.inc
+++ b/config/postfix/postfix.inc
@@ -27,50 +27,523 @@
POSSIBILITY OF SUCH DAMAGE.
*/
-
require_once("util.inc");
+require_once("functions.inc");
+require_once("pkg-utils.inc");
+require_once("globals.inc");
-function sync_package_postfix() {
+function px_text_area_decode($text){
+ return preg_replace('/\r\n/', "\n",base64_decode($text));
+}
+
+function px_get_real_interface_address($iface) {
global $config;
+ $iface = convert_friendly_interface_to_real_interface_name($iface);
+ $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6"));
+ list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line);
+ return array($ip, long2ip(hexdec($netmask)));
+}
+function sync_relay_recipients($via_cron="cron"){
+ global $config;
+ #relay recipients
+ if ($config['installedpackages']['postfixrecipients']['config']) {
+ $relay_recipients="";
+ $relay_ldap_recipients="";
+ $ad_export="/usr/local/etc/postfix/adexport.pl";
+ foreach ($config['installedpackages']['postfixrecipients']['config'] as $postfix_recipients_config) {
+ if($postfix_recipients_config['location'] && file_exists($postfix_recipients_config['location']))
+ $relay_recipients .= file_get_contents($postfix_recipients_config['location']);
+ if($postfix_recipients_config['custom_recipients'])
+ $relay_recipients .= px_text_area_decode($postfix_recipients_config['custom_recipients']);
+ if($postfix_recipients_config['enable_ldap']){
+ #validate cront job
+ if(preg_match("/(\d+)(\w)/",$postfix_recipients_config['freq'],$matches)){
+ $cron_sufix="\t*\t*\troot\t/usr/local/bin/php /usr/local/www/postfix_recipientes.php";
+ switch ($matches[2]){
+ case m:
+ $cron= "*/".$matches[1]."\t*\t*".$cron_sufix;
+ break;
+ case h:
+ $cron= "0\t*/".$matches[1]."\t*".$cron_sufix;
+ break;
+ case d:
+ $cron= "0\t0\t*/".$matches[1].$cron_sufix;
+ break;
+ default:
+ $input_errors[] = "A valid number with a time reference is required for the field 'Frequency'";
+ }
+ #update cront job file
+ $crontab = file('/etc/crontab');
+ foreach ($crontab as $line)
+ $new_cron.=(preg_match("/postfix_recipientes.php/",$line)?$cron."\n":$line);
+ #include if conf does not exist in crontab
+ $new_cron.=(!preg_match("/postfix_recipientes.php/",$new_cron)?"\n".$cron."\n\n":"");
+ file_put_contents("/etc/crontab",$new_cron, LOCK_EX);
+ #check crontab changes
+ $md5_new_file = trim(md5_file('/etc/crontab'));
+ if(file_exists('/etc/crontab.md5'))
+ $md5_old_file = trim(file_get_contents('/etc/crontab.md5'));
+ if($md5_new_file <> $md5_old_file){
+ mwexec('/usr/bin/killall -HUP cron');
+ file_put_contents("/etc/crontab.md5",$md5_new_file, LOCK_EX);
+ }
+ }
+ $relay_ldap_recipients="";
+ if ($via_cron == "gui"){
+ #running via pfsense gui, not time for ldap fetch.
+ $ldap_recipients='/usr/local/etc/postfix/relay_ldap_recipients.txt';
+ if (!file_exists($ldap_recipients))
+ system('/usr/bin/touch '. $ldap_recipients);
+ $relay_ldap_recipients=file_get_contents($ldap_recipients);
+ }
+ else{
+ #running via crontab, time to get ldap content.
+ $ldap_temp=array();
+ foreach ($postfix_recipients_config['row'] as $postfix_ldap) {
+ print "extracting from ".$postfix_ldap['dc']."...";
+ $filename="/usr/local/etc/postfix/relay_ldap_recipients.".$postfix_ldap['dc'].".txt";
+ exec($ad_export." ".$postfix_ldap['dc']." ".$postfix_ldap['cn']." ".$postfix_ldap['username']." ".$postfix_ldap['password'],$ldap_fetch,$status);
+ if ($status == 0){
+ #write backup conf for ldap server
+ $fp=fopen($filename,"w+");
+ foreach($ldap_fetch as $key => $value)
+ fwrite($fp,$value."\n");
+ fclose($fp);
+ }
+ else{
+ if (file_exists($filename)) {
+ #LDAP fetch failed...read backup file.
+ print "Restoring backup file for ".$postfix_ldap['dc']."...";
+ $ldap_fetch=file($filename);
+ }
+ else{
+ #we never got any info from this server.
+ print "There is no backup file for ".$postfix_ldap['dc']."...";
+ $ldap_fetch=array();
+ }
+ }
+ $ldap_all = array_merge($ldap_temp,$ldap_fetch);
+ $ldap_temp=$ldap_all;
+ print "(".count($ldap_fetch).")\n";
+ $ldap_fetch=array();
+ }
+ $ldap_unique=array_unique($ldap_all);
+ print "Total ldap recipients:".count($ldap_all)."\tunique:".count($ldap_unique)."\n";
+ foreach($ldap_unique as $recipient)
+ $relay_ldap_recipients.=($recipient != ""?$recipient." OK\n":"");
+
+ #save ldap relay recipients
+ file_put_contents("/usr/local/etc/postfix/relay_ldap_recipients.txt",$relay_ldap_recipients, LOCK_EX);
+ }
+ }
+ }
+ #save all relay recipients and reload postfix
+ file_put_contents("/usr/local/etc/postfix/relay_recipientes",$relay_ldap_recipients."\n".$relay_recipients, LOCK_EX);
+ exec("/usr/local/sbin/postmap /usr/local/etc/postfix/relay_recipientes");
+ mwexec("/usr/local/sbin/postfix reload");
+ }
+ if($relay_recipients !="" || $relay_ldap_recipients!="")
+ return("relay_recipient_maps = hash:/usr/local/etc/postfix/relay_recipientes\n");
+}
+function sync_package_postfix() {
+ global $config;
$relay_domains = "";
$transport = "";
- $message_size_limit = "10240000";
-
- if (is_array($config['installedpackages']['postfix']['config'])) {
- foreach ($config['installedpackages']['postfix']['config'] as $postfix_config) {
- if (isset($postfix_config['message_size_limit']))
- $message_size_limit = $postfix_config['message_size_limit'];
- if (is_array($postfix_config['row'])) {
- foreach ($postfix_config['row'] as $postfix_row) {
- $relay_domains .= ' ' . $postfix_row['domain'];
- if (!empty($postfix_row['mailserverip']))
- $transport .= $postfix_row['domain'] . " smtp:[" . $postfix_row['mailserverip'] . "]\n";
+ $postfix_config=$config['installedpackages']['postfix']['config'][0];
+ $message_size_limit=($postfix_config['message_size_limit']?$postfix_config['message_size_limit']:"10240000");
+ $process_limit=($postfix_config['process_limit']?$postfix_config['process_limit']:"100");
+ if (is_array($postfix_config['row'])) {
+ foreach ($postfix_config['row'] as $postfix_row) {
+ $relay_domains .= ' ' . $postfix_row['domain'];
+ if (!empty($postfix_row['mailserverip']))
+ $transport .= $postfix_row['domain'] . " smtp:[" . $postfix_row['mailserverip'] . "]\n";
}
}
+ #check logging
+ if ($postfix_config['log_to']){
+ switch($postfix_config['log_to']){
+ case 'maillog':
+ system("/usr/bin/touch /var/log/maillog");
+ $mail_syslog="mail.crit;";
+ break;
+ case 'none':
+ $mail_syslog="mail.crit;";
+ break;
+ default:
+ $mail_syslog='mail.*;';
+ break;
+ }
+ #update /etc/inc/system.inc
+ $sys_log_file='/etc/inc/system.inc';
+ $sys_log = file($sys_log_file);
+ $new_sys_log="";
+ $found_mail=0;
+ foreach ($sys_log as $line){
+ $new_line=preg_replace('/mail.(.|crit);/',$mail_syslog,$line);
+ #set syslog entry mail.* %/var/log/maillog when log_to = system
+ if (preg_match ('/mail.(.|crit);/',$line) && $postfix_config['log_to'] =="maillog")
+ $new_sys_log .= 'mail.*'."\t\t\t\t\t\t".'/var/log/maillog'."\n";
+ #remove syslog entry mail.* %/var/log/maillog when log_to != system
+ if (preg_match ("/^mail/",$line))
+ $new_sys_log .="";
+ else
+ $new_sys_log .= $new_line;
+ }
+ file_put_contents($sys_log_file,$new_sys_log, LOCK_EX);
+ #mwexec('/usr/local/bin/php -q /usr/local/www/postfix_syslog.php');
+ #restart syslog daemon
+ system_syslogd_start();
+ }
+
+ /*
+ #insert new syslog definition
+ if (preg_match("/.*mail.crit.(.*)/",$line,$matches)){
+ if ($postfix_config['log_to'] == "/var/log/system.log"){
+ system("/usr/bin/touch /var/log/maillog");
+ $new_sys_log .= $postfix_log.$matches[1]."\n".$line;
+ }
+ else
+ {$new_sys_log .= $postfix_log.$postfix_log_sufix."\n".$line;}
+ }
+ else{
+ #remove previous syslog definition
+ $new_sys_log .= (preg_match("/mail.(info|debug|log)/",$line)?"":$line);
+ }
+ }
+ file_put_contents($sys_log_file,$new_sys_log, LOCK_EX);
+
+ }
+
+ #update /var/etc/syslog.conf
+ $sys_log_file="/var/etc/syslog.conf";
+ $sys_log = file($sys_log_file);
+ $postfix_log .= $postfix_log_sufix;
+ $new_sys_log="";
+ foreach ($sys_log as $line)
+ $new_sys_log.=(preg_match("/mail.(info|debug|log)/",$line)?$postfix_log."\n":$line);
+ #include if conf does not exist in crontab
+ $new_sys_log.=(!preg_match("/mail.(info|debug|log)/",$new_sys_log)?"\n".$postfix_log."\n\n":"");
+ file_put_contents($sys_log_file,$new_sys_log, LOCK_EX);
+ #check crontab changes
+ $md5_new_file = trim(md5_file($sys_log_file));
+ $md5_old_file = trim(file_get_contents($sys_log_file.'.md5'));
+ if($md5_new_file <> $md5_old_file){
+ mwexec('/usr/bin/killall -HUP syslogd');
+ file_put_contents($sys_log_file.'.md5',$md5_new_file, LOCK_EX);
}
+ */
+ #}
+
+ #check_debug
+ if($postfix_config['debug_list'] && $postfix_config['debug_list']!=""){
+ $check_debug ="\n#Debugging postfix\n";
+ $check_debug.="debug_peer_list = ".px_text_area_decode($postfix_config['debug_list'])."\n";
+ $check_debug.="debug_peer_level = ".$postfix_config['debug_level']."\n\n";
}
+ #check relay recipients
+ $all_relay_recipients=sync_relay_recipients('gui');
+
+ $copyright=<<<ABOUT
+#Part of the Postfix package for pfSense
+#Copyright (C) 2010 Erik Fonnesbeck
+#Copyright (C) 2011 Marcello Coutinho
+#All rights reserved.
+#DO NOT EDIT THIS FILE
+
- $postfix_main =
+ABOUT;
+ $postfix_main="#main.cf\n".$copyright;
+ #Header Maps
+ if ($config['installedpackages']['postfixacl']['config'][0]['header_maps']){
+ $postfix_main .= "header_checks = regexp:/usr/local/etc/postfix/header_check\n";
+ $header_check = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['header_maps']);
+ }
+ #MIME Maps
+ if ($config['installedpackages']['postfixacl']['config'][0]['mime_maps']){
+ $postfix_main .= "mime_header_checks = regexp:/usr/local/etc/postfix/mime_check\n";
+ $mime_check = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['mime_maps']);
+ }
+ #Body Maps
+ if ($config['installedpackages']['postfixacl']['config'][0]['body_maps']){
+ $postfix_main .= "body_checks = regexp:/usr/local/etc/postfix/body_check\n";
+ $body_check = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['body_maps']);
+ }
+ #Client CIDR
+ if ($config['installedpackages']['postfixacl']['config'][0]['cal_cidr']){
+ if ($antispam['zombie_blocker']=='disabled')
+ $cal_cidr = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['cal_cidr']);
+ else
+ #formatar o arquivo retirando os 'oks'
+ $cal_cidr_tmp = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['cal_cidr']);
+ $cal_cidr = preg_replace('/ ok/i'," permit",$cal_cidr_tmp);
+ }
+ #Client REGEXP
+ if ($config['installedpackages']['postfixacl']['config'][0]['cal_regexp']){
+ $cal_regexp = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['cal_regexp']);
+ }
+ $postfix_main .= px_text_area_decode($postfix_config['maincf'])."\n".
"relay_domains ={$relay_domains}\n" .
"transport_maps = hash:/usr/local/etc/postfix/transport\n" .
"local_recipient_maps =\n" .
+ $all_relay_recipients.
"mydestination =\n" .
"mynetworks_style = host\n" .
- "message_size_limit = {$message_size_limit}\n";
+ "message_size_limit = {$message_size_limit}\n" .
+ "default_process_limit = {$process_limit}\n";
+ #assign antispam options
+ $antispam=$config['installedpackages']['postfixantispam']['config'][0];
+
+ if($antispam['antispam_enabled']){
+ switch ($antispam['antispam_software']){
+ case "mailscanner":
+ $header_check .= (!preg_match("/^Received:/",$header_check)?"\n/^Received:/ HOLD\n":"");
+ $postfix_main_antispam = "#Saving all mail after header/body/rbl/spf checks to mailscanner\n\n";
+ break;
+ case "policyd2":
+ if ($antispam['antispam_location']){
+ $postfix_main_antispam = <<<EOF
+#using policyd v2
+client_throttle = check_policy_service {$antispam['antispam_location']}
+smtpd_client_restrictions = check_policy_service {$antispam['antispam_location']}
+smtpd_restriction_classes =
+ has_our_domain_as_sender
+ client_throttle
+smtpd_end_of_data_restrictions = check_policy_service {$antispam['antispam_location']}
+
+
+EOF;
+ }
+ else{
+ $postfix_main_antispam = "Policyd v2 has no location set.\n\n";
+ }
+ break;
+ }
+ }
+
+ if ($antispam['header_check'] == "strong")
+ {
+ $postfix_main .= <<<EOF
+disable_vrfy_command = yes
+strict_rfc821_envelopes = yes
+
+#Just reject after helo,sender,client,recipient tests
+smtpd_delay_reject = yes
+
+# Don't talk to mail systems that don't know their own hostname.
+smtpd_helo_required = yes
+smtpd_helo_restrictions = reject_unknown_helo_hostname
+
+smtpd_sender_restrictions = reject_non_fqdn_sender,
+ reject_unknown_sender_domain,
+ reject_unauth_pipelining,
+ reject_multi_recipient_bounce,
+ permit
+# Allow connections from specified local clients and strong check everybody else.
+smtpd_client_restrictions = check_client_access regexp:/usr/local/etc/postfix/cal_regexp,
+ check_client_access cidr:/usr/local/etc/postfix/cal_cidr,
+ reject_unknown_client_hostname,
+ reject_unauth_pipelining,
+ reject_multi_recipient_bounce,
+ permit
+
+smtpd_recipient_restrictions = reject_invalid_helo_hostname,
+ reject_unknown_recipient_domain,
+ reject_non_fqdn_helo_hostname,
+ reject_non_fqdn_recipient,
+ reject_unauth_destination,
+ reject_unauth_pipelining,
+ reject_multi_recipient_bounce,
+ SPFSPFSPFRBLRBLRBL
+
+EOF;
+ }
+else
+ {
+ #erro nas listas de bloqueio
+ $postfix_main .= <<<EOF
+#Just reject after helo,sender,client,recipient tests
+smtpd_delay_reject = yes
+
+# Don't talk to mail systems that don't know their own hostname.
+smtpd_helo_required = yes
+smtpd_helo_restrictions = reject_unknown_helo_hostname
+
+smtpd_sender_restrictions = reject_unknown_sender_domain,
+ RBLRBLRBL
+
+# Allow connections from specified local clients and rbl check everybody else if rbl check are set.
+smtpd_client_restrictions = check_client_access regexp:/usr/local/etc/postfix/cal_regexp,
+ check_client_access cidr:/usr/local/etc/postfix/cal_cidr,
+ RBLRBLRBL
+
+# Whitelisting: local clients may specify any destination domain.
+smtpd_recipient_restrictions = reject_unauth_destination,
+ SPFSPFSPFRBLRBLRBL
+
+EOF;
+ }
+#check spf option
+$spf=($antispam['postfix_spf']?"check_policy_service unix:private/spf,\n\t\t\t\t":"");
+$postfix_main=preg_replace("/SPFSPFSPF/",$spf,$postfix_main);
+$postfix_main .= $postfix_main_antispam.$check_debug;
+switch ($antispam['zombie_blocker'])
+ {
+ case "enforce":
+ case "drop":
+ case "ignore":
+ $postscreen=1;
+ break;
+
+ case "disabled":
+ $postscreen=0;
+ break;
+ }
+ if ($antispam['soft_bounce'] == "enabled")
+ {
+ $postfix_main.="soft_bounce = yes\n";
+ }
+
+ if ($postscreen==1) #Postscreen enabled
+ {
+ if(preg_match("/(\d+),(\d+)(s|m|h|w)/",$antispam['greet_time'],$greet)){
+ $postfix_main.='postscreen_greet_wait = ${stress?'.$greet[1].'}${stress:'.$greet[2].'}'.$greet[3]."\n";
+ }
+ $ag=$antispam['after_greeting'];
+ if($ag["postscreen_disable_vrfy_command"]){
+ $postfix_main.="postscreen_disable_vrfy_command = yes\n";
+ }
+ if($ag["postscreen_non_smtp_command_enable"]){
+ $postfix_main.="postscreen_non_smtp_command_enable = yes\n";
+ $postfix_main.="postscreen_non_smtp_command_action = ".$antispam['zombie_blocker']."\n";
+ }
+ if($ag["postscreen_pipelining_enable"]){
+ $postfix_main.="postscreen_pipelining_enable = yes\n";
+ $postfix_main.="postscreen_pipelining_action = ".$antispam['zombie_blocker']."\n";
+ }
+ if($ag["postscreen_bare_newline_enable"]){
+ $postfix_main.="postscreen_bare_newline_enable = yes\n";
+ $postfix_main.="postscreen_bare_newline_action = ".$antispam['zombie_blocker']."\n";
+ }
+ if($ag["postscreen_greet_check"]){
+ $postfix_main.="postscreen_greet_action = ".$antispam['zombie_blocker']."\n";
+ }
+
+ $postfix_main.="postscreen_access_list = cidr:/usr/local/etc/postfix/cal_cidr\n";
+ $postfix_main.="postscreen_dnsbl_action= ".$antispam['zombie_blocker']."\n";
+ $postfix_main.="postscreen_blacklist_action= ".$antispam['zombie_blocker']."\n";
+
+ #postscreen interface loop
+ $ifaces = ($postfix_config['enabled_interface'] ? $postfix_config['enabled_interface'] : 'wan');
+ $real_ifaces = array();
+ $postfix_master="";
+ foreach (explode(",", $ifaces) as $i => $iface) {
+ $real_ifaces[] = px_get_real_interface_address($iface);
+ if($real_ifaces[$i][0]) {
+ $postfix_master .=$real_ifaces[$i][0].":25 inet n - n - 1 postscreen\n";
+ $postfix_master .=($antispam['soft_bounce'] == "postscreen"?" -o soft_bounce=yes\n":"");
+ }
+ }
+ $postfix_master .= $postfix_inets.<<<MASTEREOF
+smtpd pass - - n - - smtpd
+dnsblog unix - - n - 0 dnsblog
+tlsproxy unix - - n - 0 tlsproxy
+
+MASTEREOF;
+ $rbl2="";
+ if ($antispam['rbl_servers'] != "")
+ {
+ $postfix_main .= "postscreen_dnsbl_sites=" . $antispam['rbl_servers']."\n";
+ $postfix_main .= "postscreen_dnsbl_threshold=" . $antispam['rbl_threshold']."\n";
+ }
+ }
+ else
+ { #Postscreen disabled
+ if ($antispam['rbl_servers'] != "")
+ {
+ $RBL = explode(",",$antispam['rbl_servers']);
+ foreach ($RBL as $rbl)
+ {
+ $prefix=($rbl2 !=""?"\t\t\t\t":"");
+ $rbl2.= $prefix."reject_rbl_client $rbl,\n";
+ }
+ }
+
+ #interface loop
+ $postfix_inets="";
+ $ifaces = ($postfix_config['enabled_interface'] ? $postfix_config['enabled_interface'] : 'loopback');
+ $real_ifaces = array();
+ $postfix_master="";
+ foreach (explode(",", $ifaces) as $i => $iface) {
+ $real_ifaces[] = px_get_real_interface_address($iface);
+ if($real_ifaces[$i][0]) {
+ $postfix_master .=$real_ifaces[$i][0].":25 inet n - n - 1 smtpd\n";
+ }
+ }
+
+ }
+ $rbl2.=($rbl2 !=""?"\t\t\t\tpermit\n":"permit\n");
+ $postfix_main=preg_replace("/RBLRBLRBL/",$rbl2,$postfix_main);
+ $postfix_master .= <<<MASTEREOF2
+pickup fifo n - n 60 1 pickup
+cleanup unix n - n - 0 cleanup
+qmgr fifo n - n 300 1 qmgr
+tlsmgr unix - - n 1000? 1 tlsmgr
+rewrite unix - - n - - trivial-rewrite
+bounce unix - - n - 0 bounce
+defer unix - - n - 0 bounce
+trace unix - - n - 0 bounce
+verify unix - - n - 1 verify
+flush unix n - n 1000? 0 flush
+proxymap unix - - n - - proxymap
+proxywrite unix - - n - 1 proxymap
+smtp unix - - n - - smtp
+relay unix - - n - - smtp
+ -o smtp_fallback_relay=
+showq unix n - n - - showq
+error unix - - n - - error
+retry unix - - n - - error
+discard unix - - n - - discard
+local unix - n n - - local
+virtual unix - n n - - virtual
+lmtp unix - - n - - lmtp
+anvil unix - - n - 1 anvil
+scache unix - - n - 1 scache
+spf unix - n n - - spawn
+ user=nobody argv=/usr/local/sbin/postfix-policyd-spf
+# -o user=nobody
+# -o argv=/usr/local/sbin/postfix-policyd-spf
+
+MASTEREOF2;
+
conf_mount_rw();
log_error("Writing out configuration");
file_put_contents("/usr/local/etc/postfix/main.cf", $postfix_main, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/master.cf", $postfix_master, LOCK_EX);
file_put_contents("/usr/local/etc/postfix/transport", $transport, LOCK_EX);
- exec("/usr/local/sbin/postmap /usr/local/etc/postfix/transport");
+ file_put_contents("/usr/local/etc/postfix/cal_cidr", $cal_cidr, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/cal_regexp", $cal_regexp, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/header_check", $header_check, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/mime_check", $mime_check, LOCK_EX);
+ file_put_contents("/usr/local/etc/postfix/body_check", $body_check, LOCK_EX);
+ $FILES=array("transport");
+ foreach ($FILES as $file)
+ {
+ mwexec("/usr/local/sbin/postmap /usr/local/etc/postfix/".$file);
+ }
+
if (!is_dir("/etc/mail"))
mkdir("/etc/mail", 0755);
if (!file_exists("/etc/mail/aliases"))
touch("/etc/mail/aliases");
exec("/usr/local/bin/newaliases");
-
+ postfix_start();
+ postfix_sync_on_changes();
+}
+function postfix_start(){
+ global $config;
$start = "/usr/local/sbin/postfix start\n";
$stop = "/usr/local/sbin/postfix stop\n";
log_error("Writing rc_file");
@@ -78,18 +551,34 @@ function sync_package_postfix() {
conf_mount_ro();
- log_error("Stopping postfix");
- mwexec("/usr/local/etc/rc.d/postfix.sh stop");
sleep(1);
- log_error("Starting postfix");
- mwexec_bg("/usr/local/etc/rc.d/postfix.sh start");
- log_error("Postfix setup completed");
+ if ($config['installedpackages']['postfix']['config'][0]['enable_postfix']){
+ log_error("Reloading/starting postfix");
+ system('/bin/chmod +x /usr/local/etc/rc.d/postfix.sh');
+ mwexec_bg("/usr/local/sbin/postfix reload || /usr/local/sbin/postfix start");
+ log_error("Postfix setup completed");
+ }
+ else{
+ log_error("Stopping postfix");
+ mwexec("/usr/local/etc/rc.d/postfix.sh stop");
+ system('/bin/chmod -x /usr/local/etc/rc.d/postfix.sh');
+ }
}
function postfix_validate_input($post, &$input_errors) {
foreach ($post as $key => $value) {
if (empty($value))
continue;
+ if($key == "greet_time" && !preg_match("/(\d+),(\d+)(s|m|h|w)/",$value))
+ $input_errors[] = "Wrong greet time sintax.";
+ if($key == "message_size_limit" && !is_numeric($value))
+ $input_errors[] = "Message size limit must be numeric.";
+ if($key == "process_limit" && !is_numeric($value))
+ $input_errors[] = "Process limit must be numeric.";
+ if($key == "freq" && (!preg_match("/^\d+(h|m|d)$/",$value) || $value == 0))
+ $input_errors[] = "A valid number with a time reference is required for the field 'Frequency'";
+ if (substr($key, 0, 2) == "dc" && !is_hostname($value))
+ $input_errors[] = "{$value} is not a valid host name.";
if (substr($key, 0, 6) == "domain" && is_numeric(substr($key, 6))) {
if (!is_domain($value))
$input_errors[] = "{$value} is not a valid domain name.";
@@ -103,6 +592,9 @@ function postfix_validate_input($post, &$input_errors) {
}
function postfix_php_install_command() {
+ #small freebsd packages for full functional ldap and spf options
+ system('/usr/sbin/pkg_add -r postfix-policyd-spf');
+ system('/usr/sbin/pkg_add -r p5-perl-ldap');
sync_package_postfix();
}
@@ -114,4 +606,117 @@ function postfix_php_deinstall_command() {
conf_mount_ro();
}
-?> \ No newline at end of file
+/* Uses XMLRPC to synchronize the changes to a remote node */
+function postfix_sync_on_changes() {
+ global $config, $g;
+ log_error("[postfix] postfix_xmlrpc_sync.php is starting.");
+ $synconchanges = $config['installedpackages']['postfixsync']['config'][0]['synconchanges'];
+ if(!$synconchanges)
+ return;
+ foreach ($config['installedpackages']['postfixsync']['config'] as $rs ){
+ foreach($rs['row'] as $sh){
+ $sync_to_ip = $sh['ipaddress'];
+ $password = $sh['password'];
+ if($password && $sync_to_ip)
+ postfix_do_xmlrpc_sync($sync_to_ip, $password);
+ }
+ }
+ log_error("[postfix] postfix_xmlrpc_sync.php is ending.");
+}
+
+/* Do the actual XMLRPC sync */
+function postfix_do_xmlrpc_sync($sync_to_ip, $password) {
+ global $config, $g;
+
+ if(!$password)
+ return;
+
+ if(!$sync_to_ip)
+ return;
+
+ $xmlrpc_sync_neighbor = $sync_to_ip;
+ if($config['system']['webgui']['protocol'] != "") {
+ $synchronizetoip = $config['system']['webgui']['protocol'];
+ $synchronizetoip .= "://";
+ }
+ $port = $config['system']['webgui']['port'];
+ /* if port is empty lets rely on the protocol selection */
+ if($port == "") {
+ if($config['system']['webgui']['protocol'] == "http")
+ $port = "80";
+ else
+ $port = "443";
+ }
+ $synchronizetoip .= $sync_to_ip;
+
+ /* xml will hold the sections to sync */
+ $xml = array();
+ $xml['postfix'] = $config['installedpackages']['postfix'];
+ $xml['postfixacl'] = $config['installedpackages']['postfixacl'];
+ $xml['postfixrecipients'] = $config['installedpackages']['postfixrecipients'];
+ $xml['postfixantispam'] = $config['installedpackages']['postfixantispam'];
+
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($xml)
+ );
+
+ /* set a few variables needed for sync code borrowed from filter.inc */
+ $url = $synchronizetoip;
+ log_error("Beginning Postfix XMLRPC sync to {$url}:{$port}.");
+ $method = 'pfsense.merge_installedpackages_section_xmlrpc';
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $password);
+ if($g['debug'])
+ $cli->setDebug(1);
+ /* send our XMLRPC message and timeout after 250 seconds */
+ $resp = $cli->send($msg, "250");
+ if(!$resp) {
+ $error = "A communications error occurred while attempting postfix XMLRPC sync with {$url}:{$port}.";
+ log_error($error);
+ file_notice("sync_settings", $error, "Postfix Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $cli->setDebug(1);
+ $resp = $cli->send($msg, "250");
+ $error = "An error code was received while attempting postfix XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "Postfix Settings Sync", "");
+ } else {
+ log_error("Postfix XMLRPC sync successfully completed with {$url}:{$port}.");
+ }
+
+ /* tell postfix to reload our settings on the destionation sync host. */
+ $method = 'pfsense.exec_php';
+ $execcmd = "require_once('/usr/local/pkg/postfix.inc');\n";
+ $execcmd .= "sync_package_postfix();";
+
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($execcmd)
+ );
+
+ log_error("postfix XMLRPC reload data {$url}:{$port}.");
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials('admin', $password);
+ $resp = $cli->send($msg, "250");
+ if(!$resp) {
+ $error = "A communications error occurred while attempting postfix XMLRPC sync with {$url}:{$port} (pfsense.exec_php).";
+ log_error($error);
+ file_notice("sync_settings", $error, "postfix Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $cli->setDebug(1);
+ $resp = $cli->send($msg, "250");
+ $error = "An error code was received while attempting postfix XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "postfix Settings Sync", "");
+ } else {
+ log_error("postfix XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php).");
+ }
+
+}
+
+?>