diff options
Diffstat (limited to 'config/postfix/postfix.inc')
-rw-r--r-- | config/postfix/postfix.inc | 787 |
1 files changed, 761 insertions, 26 deletions
diff --git a/config/postfix/postfix.inc b/config/postfix/postfix.inc index cf470c8f..d009e72a 100644 --- a/config/postfix/postfix.inc +++ b/config/postfix/postfix.inc @@ -3,6 +3,8 @@ postfix.inc part of the Postfix package for pfSense Copyright (C) 2010 Erik Fonnesbeck + Copyright (C) 2011 Marcello Coutinho + All rights reserved. Redistribution and use in source and binary forms, with or without @@ -27,69 +29,678 @@ 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")); + $postfix_enabled=$config['installedpackages']['postfix']['config'][0]['enable_postfix']; + list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line); + return array($ip, long2ip(hexdec($netmask))); +} + +function sync_relay_recipients($via_cron="cron"){ + global $config,$g; + #relay recipients + if ($config['installedpackages']['postfixrecipients']['config']) { + $relay_recipients=""; + $relay_ldap_recipients=""; + $ad_export="/usr/local/etc/postfix/adexport.pl"; + $postfix_enabled=$config['installedpackages']['postfix']['config'][0]['enable_postfix']; + if (is_array($config['installedpackages']['postfixrecipients']['config'])) { + $postfix_recipients_config=$config['installedpackages']['postfixrecipients']['config'][0]; + 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 + $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_recipients",$relay_ldap_recipients."\n".$relay_recipients, LOCK_EX); + exec("/usr/local/sbin/postmap /usr/local/etc/postfix/relay_recipients"); + mwexec("/usr/local/sbin/postfix reload"); + } + if($relay_recipients !="" || $relay_ldap_recipients!="") + return("relay_recipient_maps = hash:/usr/local/etc/postfix/relay_recipients\n"); + +} +function check_cron(){ + global $config, $g; + #check crontab + $new_cron=array(); + $cron_cmd_sqlite = ""; + $cron_postfix_sqlite=""; + $cron_cmd="/usr/local/bin/php -q /usr/local/www/postfix_recipients.php"; + $postfix_enabled=$config['installedpackages']['postfix']['config'][0]['enable_postfix']; + #check ldap update + if (is_array($config['installedpackages']['postfixrecipients']['config'])) + $postfix_recipients_config=$config['installedpackages']['postfixrecipients']['config'][0]; + if(preg_match("/(\d+)(\w)/",$postfix_recipients_config['freq'],$matches)){ + $cron_postfix=array("minute" => "*", + "hour" => "*", + "mday" => "*", + "month" => "*", + "wday" => "*", + "who" => "root", + "command"=> $cron_cmd); + switch ($matches[2]){ + case m: + $cron_postfix["month"]="*/".$matches[1]; + break; + case h: + $cron_postfix["minute"]="0"; + $cron_postfix["hour"]="*/".$matches[1]; + break; + case d: + $cron_postfix["minute"]="0"; + $cron_postfix["hour"]="0"; + $cron_postfix["mday"]="*/".$matches[1]; + break; + default: + $input_errors[] = "A valid number with a time reference is required for the field 'Frequency'"; + } + } + #check crontab Sqlite databases + if (is_array($config['installedpackages']['postfix']['config']) && $postfix_enabled=="on"){ + $cron_sqlite_queue=$config['installedpackages']['postfix']['config'][0]['update_sqlite']; + $cron_cmd_sqlite="/usr/local/bin/php -q /usr/local/www/postfix.php"; + if ($cron_sqlite_queue != "" && $cron_sqlite_queue != "never"){ + $cron_postfix_sqlite=array("minute" => "*", + "hour" => "*", + "mday" => "*", + "month" => "*", + "wday" => "*", + "who" => "root", + "command"=> ""); + switch ($cron_sqlite_queue){ + case '01min': + $cron_postfix_sqlite["command"] = $cron_cmd_sqlite ." 01min"; + break; + case '10min': + $cron_postfix_sqlite["minute"]="*/10"; + $cron_postfix_sqlite["command"] = $cron_cmd_sqlite ." 10min"; + break; + case '01hour': + $cron_postfix_sqlite["minute"]="0"; + $cron_postfix_sqlite["command"] = $cron_cmd_sqlite ." 01hour"; + break; + case '24hours': + $cron_postfix_sqlite["minute"]="0"; + $cron_postfix_sqlite["hour"]="0"; + $cron_postfix_sqlite["command"] = $cron_cmd_sqlite ." 24hours"; + break; + } + } + } + + #check crontab relay recipients + $cron_found=""; + if (is_array($config['cron']['item'])){ + #print "<pre>"; + foreach($config['cron']['item'] as $cron){ + #check valid_recipients cron + if ($cron["command"] == $cron_cmd){ + #postfix cron cmd found + if($postfix_enabled=="on") + $cron_found=$cron; + if($postfix_recipients_config['enable_ldap'] && $postfix_enabled=="on") + #update cron schedule + $new_cron['item'][]=$cron_postfix; + } + #check sqlite update queue + else if(!preg_match("/.usr.local.www.postfix.php/",$cron["command"])){ + #keep all non postfix cron cmds if not empty + if ($cron["command"] != "") + $new_cron['item'][]=$cron; + } + } + $write_cron=1; + # Check if crontab must be changed to valid recipients cmd + if ($postfix_recipients_config['enable_ldap']){ + if ($cron_found!=$cron_postfix){ + #update postfix cron schedule + if (! is_array($cron_found) && $postfix_enabled=="on") + $new_cron['item'][]=$cron_postfix; + $write_cron=1; + } + } + else{ + if (is_array($cron_found)){ + #remove postfix cron cmd + $write_cron=1; + } + } + #check if cron must be changed to Sqlite cmd + if($cron_sqlite_queue != "" && $cron_sqlite_queue != "never"){ + $new_cron['item'][]=$cron_postfix_sqlite; + $config['cron']=$new_cron; + $write_cron=1; + } + } + #call cron functions + if ($write_cron==1){ + $config['cron']=$new_cron; + write_config('Postfix - sync remote sqlite database',$backup = false); + configure_cron(); + } + #remove postfix old cron call + $old_cron=0; + $crontab = file('/etc/crontab'); + $new_crontab=""; + foreach ($crontab as $line){ + if (preg_match("/php..usr.local.www.postfix_recipients.php/",$line)) + $old_cron=1; + else + $new_crontab .= $line; + } + if ($old_cron==1) + file_put_contents("/etc/crontab",$new_crontab, LOCK_EX); + + #print "<pre>". var_dump($new_cron). var_dump($cron_postfix_sqlite).var_dump($config['cron']); + #exit; + + +} +function sync_package_postfix() { + global $config; + + #check patch in /etc/inc/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]; + if (is_array($config['installedpackages']['postfixdomains'])) + $postfix_domains=$config['installedpackages']['postfixdomains']['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_domains['row'])) { + foreach ($postfix_domains['row'] as $postfix_row) { + $relay_domains .= ' ' . $postfix_row['domain']; + if (!empty($postfix_row['mailserverip'])) + $transport .= $postfix_row['domain'] . " smtp:[" . $postfix_row['mailserverip'] . "]\n"; } } + #check cron + check_cron(); + #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; + } + if (!file_exists('/root/system.inc.backup')) { + copy ($sys_log_file,'/root/system.inc.backup'); + } + 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(); } + + #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=<<<EOF +#main.cf\ +{$copyright} +mynetworks = /usr/local/etc/postfix/mynetwork_table +mynetworks_style = host + +EOF; + #Header Maps + $mynetworks = ""; + if ($config['installedpackages']['postfixacl']['config'][0]['mynetworks']){ + $mynetworks = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['mynetworks']); + } + #Header Maps + if ($config['installedpackages']['postfixacl']['config'][0]['header_maps']){ + $postfix_main .= "header_checks = pcre:/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 = pcre:/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 = pcre:/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 PCRE + if ($config['installedpackages']['postfixacl']['config'][0]['cal_pcre']){ + $cal_pcre = px_text_area_decode($config['installedpackages']['postfixacl']['config'][0]['cal_pcre']); + } + $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('@/ HOLD@',$header_check)?"\n/^Received:/ HOLD\n":"\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; + } + } + $reject_unknown_helo_hostname=($antispam['reject_unknown_helo_hostname']?"reject_unknown_helo_hostname":""); + 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 pcre:/usr/local/etc/postfix/cal_pcre, + 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 = permit_mynetworks, + check_client_access pcre:/usr/local/etc/postfix/cal_pcre, + check_client_access cidr:/usr/local/etc/postfix/cal_cidr, + 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 pcre:/usr/local/etc/postfix/cal_pcre, + check_client_access cidr:/usr/local/etc/postfix/cal_cidr, + RBLRBLRBL + +# Whitelisting: local clients may specify any destination domain. +#, +smtpd_recipient_restrictions = permit_mynetworks, + reject_unauth_destination, + SPFSPFSPFRBLRBLRBL +EOF; + } +#check spf option +switch($antispam['postfix_spf']){ + case 'spf_mark_only': + $postfix_main.= "spf_mark_only = yes\n"; + $spf="reject_spf_invalid_sender,\n\t\t\t\t"; + break; + case 'disable': + $spf=""; + break; + default: + $spf=$antispam['postfix_spf'].",\n\t\t\t\t"; + break; +} +$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(preg_match("/postscreen_disable_vrfy_command/",$antispam['after_greeting'])){ + $postfix_main.="postscreen_disable_vrfy_command = yes\n"; + } + if(preg_match("/postscreen_non_smtp_command_enable/",$antispam['after_greeting'])){ + $postfix_main.="postscreen_non_smtp_command_enable = yes\n"; + $postfix_main.="postscreen_non_smtp_command_action = ".$antispam['zombie_blocker']."\n"; + } + if(preg_match("/postscreen_pipelining_enable/",$antispam['after_greeting'])){ + $postfix_main.="postscreen_pipelining_enable = yes\n"; + $postfix_main.="postscreen_pipelining_action = ".$antispam['zombie_blocker']."\n"; + } + if(preg_match("/postscreen_bare_newline_enable/",$antispam['after_greeting'])){ + $postfix_main.="postscreen_bare_newline_enable = yes\n"; + $postfix_main.="postscreen_bare_newline_action = ".$antispam['zombie_blocker']."\n"; + } + if(preg_match("/postscreen_greet_check/",$antispam['after_greeting'])){ + $postfix_main.="postscreen_greet_action = ".$antispam['zombie_blocker']."\n"; + } + + $postfix_main.="postscreen_access_list = permit_mynetworks,\n\t\t\tcidr:/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\t-o user=postfix\n"; + $postfix_master .=($antispam['soft_bounce'] == "postscreen"?"\t-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\t-o user=postfix\n"; + } + } + + } + $rbl2.=($rbl2 !=""?"\t\t\t\tpermit\n":"permit\n"); + $postfix_main=preg_replace("/RBLRBLRBL/",$rbl2,$postfix_main); + + #Header Maps + $anvil_config=$config['installedpackages']['postfixantispam']['config'][0]['anvil']; + if ($anvil_config =='enabled' || ($anvil_config =='postscreen' && $postscreen==1)) + $anvil='anvil unix - - n - 1 anvil'; + + $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 +scache unix - - n - 1 scache +{$anvil} + +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_pcre", $cal_pcre, 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); + file_put_contents("/usr/local/etc/postfix/mynetwork_table", $mynetworks, 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"); - - $start = "/usr/local/sbin/postfix start\n"; + postfix_start(); + postfix_sync_on_changes(); +} +function postfix_start(){ + global $config; + $start=<<<EOF + + sysctl kern.ipc.nmbclusters=65536 + sysctl kern.ipc.somaxconn=16384 + sysctl kern.maxfiles=131072 + sysctl kern.maxfilesperproc=104856 + sysctl kern.threads.max_threads_per_proc=4096 + /usr/local/sbin/postfix start + +EOF; $stop = "/usr/local/sbin/postfix stop\n"; log_error("Writing rc_file"); write_rcfile(array("file" => "postfix.sh", "start" => $start, "stop" => $stop)); 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/etc/rc.d/postfix.sh 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."; @@ -107,11 +718,135 @@ function postfix_php_install_command() { } function postfix_php_deinstall_command() { - mwexec("/usr/local/etc/rc.d/postfix.sh stop"); - sleep(1); + global $config; + #disable service + $config['installedpackages']['postfix']['config'][0]['enable_postfix']=""; + write_config(); + sync_package_postfix(); conf_mount_rw(); unlink_if_exists("/usr/local/etc/rc.d/postfix.sh"); 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; + $synconchanges = $config['installedpackages']['postfixsync']['config'][0]['synconchanges']; + $syncondbchanges= $config['installedpackages']['postfixsync']['config'][0]['rsync']; + if(!$synconchanges && !$syncondbchanges) + return; + log_error("[postfix] postfix_xmlrpc_sync.php is starting."); + foreach ($config['installedpackages']['postfixsync']['config'] as $rs ){ + foreach($rs['row'] as $sh){ + $sync_to_ip = $sh['ipaddress']; + $password = $sh['password']; + $sync_type = $sh['sync_type']; + if($password && $sync_to_ip) + postfix_do_xmlrpc_sync($sync_to_ip, $password,$sync_type); + } + } + log_error("[postfix] postfix_xmlrpc_sync.php is ending."); +} + +/* Do the actual XMLRPC sync */ +function postfix_do_xmlrpc_sync($sync_to_ip, $password,$sync_type) { + 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(); + $sync_xml=$config['installedpackages']['postfixsync']['config'][0]['synconchanges']; + $sync_db=$config['installedpackages']['postfixsync']['config'][0]['rsync']; + if ($sync_xml && preg_match("/xmlrpc/",$sync_type)){ + log_error("Include postfix xmls"); + $xml['postfix'] = $config['installedpackages']['postfix']; + $xml['postfixdomains'] = $config['installedpackages']['postfixdomains']; + $xml['postfixacl'] = $config['installedpackages']['postfixacl']; + $xml['postfixrecipients'] = $config['installedpackages']['postfixrecipients']; + $xml['postfixantispam'] = $config['installedpackages']['postfixantispam']; + } + if (count($xml) > 0){ + /* 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)."); + } + } +} + +?> |