diff --git a/install/lib/installer_base.lib.php b/install/lib/installer_base.lib.php index 103abaef1909859b45017bde0f9c6bda9174e7e3..5e7a14a5cd261f65ac69ca80efbf9bc47487746f 100644 --- a/install/lib/installer_base.lib.php +++ b/install/lib/installer_base.lib.php @@ -1107,7 +1107,7 @@ class installer_base { $server_ini_array = ini_to_array(stripslashes($server_ini_rec['config'])); unset($server_ini_rec); - //* If there are RBL's defined, format the list and add them to smtp_recipient_restrictions to prevent removeal after an update + //* If there are RBL's defined, format the list and add them to smtp_recipient_restrictions to prevent removal after an update $rbl_list = ''; if (@isset($server_ini_array['mail']['realtime_blackhole_list']) && $server_ini_array['mail']['realtime_blackhole_list'] != '') { $rbl_hosts = explode(",", str_replace(" ", "", $server_ini_array['mail']['realtime_blackhole_list'])); @@ -1647,6 +1647,12 @@ class installer_base { public function configure_amavis() { global $conf; + //* These postconf commands will be executed on installation and update + $server_ini_rec = $this->db->queryOneRecord("SELECT mail_server, config FROM ?? WHERE server_id = ?", $conf["mysql"]["database"] . '.server', $conf['server_id']); + $server_ini_array = ini_to_array(stripslashes($server_ini_rec['config'])); + $mail_server = ($server_ini_rec['mail_server']) ? true : false; + unset($server_ini_rec); + // amavisd user config file $configfile = 'amavisd_user_config'; if(is_file($conf['amavis']['config_dir'].'/conf.d/50-user')) copy($conf['amavis']['config_dir'].'/conf.d/50-user', $conf['amavis']['config_dir'].'/50-user~'); @@ -1660,63 +1666,85 @@ class installer_base { wf($conf['amavis']['config_dir'].'/conf.d/50-user', $content); chmod($conf['amavis']['config_dir'].'/conf.d/50-user', 0640); - // TODO: chmod and chown on the config file + $mail_config = $server_ini_array['mail']; + //* only change postfix config if amavisd is active filter + if($mail_server && $mail_config['content_filter'] === 'amavisd') { + // test if lmtp if available + $configure_lmtp = $this->get_postfix_service('lmtp','unix'); - // test if lmtp if available - $configure_lmtp = $this->get_postfix_service('lmtp','unix'); + // Adding the amavisd commands to the postfix configuration + $postconf_commands = array (); - // Adding the amavisd commands to the postfix configuration - // Add array for no error in foreach and maybe future options - $postconf_commands = array (); + // Check for amavisd -> pure webserver with postfix for mailing without antispam + if ($conf['amavis']['installed']) { + $content_filter_service = ($configure_lmtp) ? 'lmtp' : 'amavis'; + $postconf_commands[] = "content_filter = ${content_filter_service}:[127.0.0.1]:10024"; + $postconf_commands[] = 'receive_override_options = no_address_mappings'; + $postconf_commands[] = 'address_verify_virtual_transport = smtp:[127.0.0.1]:10025'; + $postconf_commands[] = 'address_verify_transport_maps = static:smtp:[127.0.0.1]:10025'; + } - // Check for amavisd -> pure webserver with postfix for mailing without antispam - if ($conf['amavis']['installed']) { - $content_filter_service = ($configure_lmtp) ? 'lmtp' : 'amavis'; - $postconf_commands[] = "content_filter = ${content_filter_service}:[127.0.0.1]:10024"; - $postconf_commands[] = 'receive_override_options = no_address_mappings'; - } + $options = preg_split("/,\s*/", exec("postconf -h smtpd_recipient_restrictions")); + $new_options = array(); + foreach ($options as $value) { + $value = trim($value); + if ($value == '') continue; + if (preg_match("|check_recipient_access\s+proxy:mysql:${quoted_config_dir}/mysql-verify_recipients.cf|", $value)) { + continue; + } + $new_options[] = $value; + } + if ($configure_lmtp) { + for ($i = 0; isset($new_options[$i]); $i++) { + if ($new_options[$i] == 'reject_unlisted_recipient') { + array_splice($new_options, $i+1, 0, array("check_recipient_access proxy:mysql:${config_dir}/mysql-verify_recipients.cf")); + break; + } + } + # postfix < 3.3 needs this when using reject_unverified_recipient: + if(version_compare($postfix_version, 3.3, '<')) { + $postconf_commands[] = "enable_original_recipient = yes"; + } + } + $postconf_commands[] = "smtpd_recipient_restrictions = ".implode(", ", $new_options); - // Make a backup copy of the main.cf file - copy($conf['postfix']['config_dir'].'/main.cf', $conf['postfix']['config_dir'].'/main.cf~2'); + // Make a backup copy of the main.cf file + copy($conf['postfix']['config_dir'].'/main.cf', $conf['postfix']['config_dir'].'/main.cf~2'); - // Executing the postconf commands - foreach($postconf_commands as $cmd) { - $command = "postconf -e '$cmd'"; - caselog($command." &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); - } + // Executing the postconf commands + foreach($postconf_commands as $cmd) { + $command = "postconf -e '$cmd'"; + caselog($command." &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command"); + } - $config_dir = $conf['postfix']['config_dir']; + $config_dir = $conf['postfix']['config_dir']; - // Adding amavis-services to the master.cf file if the service does not already exists -// $add_amavis = !$this->get_postfix_service('amavis','unix'); -// $add_amavis_10025 = !$this->get_postfix_service('127.0.0.1:10025','inet'); -// $add_amavis_10027 = !$this->get_postfix_service('127.0.0.1:10027','inet'); - //*TODO: check templates against existing postfix-services to make sure we use the template - - // Or just remove the old service definitions and add them again? - $add_amavis = $this->remove_postfix_service('amavis','unix'); - $add_amavis_10025 = $this->remove_postfix_service('127.0.0.1:10025','inet'); - $add_amavis_10027 = $this->remove_postfix_service('127.0.0.1:10027','inet'); - - if ($add_amavis || $add_amavis_10025 || $add_amavis_10027) { - //* backup master.cf - if(is_file($config_dir.'/master.cf')) copy($config_dir.'/master.cf', $config_dir.'/master.cf~'); - // adjust amavis-config - if($add_amavis) { - $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/master_cf_amavis.master', 'tpl/master_cf_amavis.master'); - af($config_dir.'/master.cf', $content); - unset($content); - } - if ($add_amavis_10025) { - $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/master_cf_amavis10025.master', 'tpl/master_cf_amavis10025.master'); - af($config_dir.'/master.cf', $content); - unset($content); + // Adding amavis-services to the master.cf file if the service does not already exists + // (just remove the old service definitions and add them again) + $add_amavis = $this->remove_postfix_service('amavis','unix'); + $add_amavis_10025 = $this->remove_postfix_service('127.0.0.1:10025','inet'); + $add_amavis_10027 = $this->remove_postfix_service('127.0.0.1:10027','inet'); + + if ($add_amavis || $add_amavis_10025 || $add_amavis_10027) { + //* backup master.cf + if(is_file($config_dir.'/master.cf')) copy($config_dir.'/master.cf', $config_dir.'/master.cf~'); + // adjust amavis-config + if($add_amavis) { + $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/master_cf_amavis.master', 'tpl/master_cf_amavis.master'); + af($config_dir.'/master.cf', $content); + unset($content); + } + if ($add_amavis_10025) { + $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/master_cf_amavis10025.master', 'tpl/master_cf_amavis10025.master'); + af($config_dir.'/master.cf', $content); + unset($content); + } + if ($add_amavis_10027) { + $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/master_cf_amavis10027.master', 'tpl/master_cf_amavis10027.master'); + af($config_dir.'/master.cf', $content); + unset($content); + } } - if ($add_amavis_10027) { - $content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/master_cf_amavis10027.master', 'tpl/master_cf_amavis10027.master'); - af($config_dir.'/master.cf', $content); - unset($content); - } } // Add the clamav user to the amavis group @@ -1746,14 +1774,18 @@ class installer_base { global $conf; //* These postconf commands will be executed on installation and update - $server_ini_rec = $this->db->queryOneRecord("SELECT config FROM ?? WHERE server_id = ?", $conf["mysql"]["database"] . '.server', $conf['server_id']); + $server_ini_rec = $this->db->queryOneRecord("SELECT mail_server, config FROM ?? WHERE server_id = ?", $conf["mysql"]["database"] . '.server', $conf['server_id']); $server_ini_array = ini_to_array(stripslashes($server_ini_rec['config'])); + $mail_server = ($server_ini_rec['mail_server']) ? true : false; unset($server_ini_rec); $mail_config = $server_ini_array['mail']; - if($mail_config['content_filter'] === 'rspamd') { - exec("postconf -X 'receive_override_options'"); - exec("postconf -X 'content_filter'"); + //* only change postfix config if rspamd is active filter + if($mail_server && $mail_config['content_filter'] === 'rspamd') { + exec("postconf -X receive_override_options"); + exec("postconf -X content_filter"); + exec("postconf -X address_verify_virtual_transport"); + exec("postconf -X address_verify_transport_maps"); exec("postconf -e 'smtpd_milters = inet:localhost:11332'"); exec("postconf -e 'non_smtpd_milters = inet:localhost:11332'"); @@ -1804,6 +1836,9 @@ class installer_base { if (preg_match('/check_policy_service\s+inet:127.0.0.1:10023/', $value)) { continue; } + if (preg_match("|check_recipient_access\s+proxy:mysql:${quoted_config_dir}/mysql-verify_recipients.cf|", $value)) { + continue; + } $new_options[] = $value; } exec("postconf -e 'smtpd_recipient_restrictions = ".implode(", ", $new_options)."'"); diff --git a/install/tpl/master_cf_amavis.master b/install/tpl/master_cf_amavis.master index 243f28a288dc2e5f27a54f79422a9b5f48571d76..a565f1a1bb50977d8d945e1efcf3b07b641c617d 100644 --- a/install/tpl/master_cf_amavis.master +++ b/install/tpl/master_cf_amavis.master @@ -2,5 +2,5 @@ amavis unix - - - - 2 smtp -o smtp_data_done_timeout=1200 -o smtp_send_xforward_command=yes - -o smtp_bind_address= + -o smtp_bind_address= diff --git a/install/tpl/master_cf_amavis10025.master b/install/tpl/master_cf_amavis10025.master index 6dee892264d3d6f5491fecb104a0242f079cda88..68d4561494b0568c7b4bbac4e6d51ad13c1f66f2 100644 --- a/install/tpl/master_cf_amavis10025.master +++ b/install/tpl/master_cf_amavis10025.master @@ -14,4 +14,6 @@ -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks -o smtp_send_xforward_command=yes -o disable_dns_lookups=yes + -o address_verify_virtual_transport=$virtual_transport + -o address_verify_transport_maps=$transport_maps diff --git a/install/tpl/master_cf_amavis10027.master b/install/tpl/master_cf_amavis10027.master index 640902d52e109a76d206cb72123b7cf1ea65e9d0..d3a07a8bce45d1e2c415f1a6085323faa9066261 100644 --- a/install/tpl/master_cf_amavis10027.master +++ b/install/tpl/master_cf_amavis10027.master @@ -13,7 +13,9 @@ -o strict_rfc821_envelopes=yes -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks -o smtp_send_xforward_command=yes - -o milter_default_action=accept - -o milter_macro_daemon_name=ORIGINATING -o disable_dns_lookups=yes + -o address_verify_virtual_transport=$virtual_transport + -o address_verify_transport_maps=$transport_maps + -o milter_default_action=accept + -o milter_macro_daemon_name=ORIGINATING diff --git a/interface/lib/classes/validate_mail_relay_domain.inc.php b/interface/lib/classes/validate_mail_relay_domain.inc.php index 0d6beedefb7e43cc06a2aea80f1c0ed2be855a1e..44e13998a4af1ed529c02e62ffd27dae582ccb75 100644 --- a/interface/lib/classes/validate_mail_relay_domain.inc.php +++ b/interface/lib/classes/validate_mail_relay_domain.inc.php @@ -45,9 +45,6 @@ class validate_mail_relay_domain { function validate_domain($field_name, $field_value, $validator) { global $app, $conf; - if(empty($field_value) || $field_name != 'domain') return; - - if(isset($app->remoting_lib->primary_id)) { $id = $app->remoting_lib->primary_id; } else { @@ -56,7 +53,7 @@ class validate_mail_relay_domain { // mail_relay_domain.domain must be unique per server $sql = "SELECT relay_domain_id, domain FROM mail_relay_domain WHERE domain = ? AND server_id = ? AND relay_domain_id != ?"; - $domain_check = $app->db->queryOneRecord($sql, $field_value, $conf['server_id'], $id); + $domain_check = $app->db->queryOneRecord($sql, $field_value, $app->tform_actions->dataRecord['server_id'], $id); if($domain_check) return $this->get_error('domain_error_unique'); } diff --git a/server/plugins-available/postfix_server_plugin.inc.php b/server/plugins-available/postfix_server_plugin.inc.php index 8cdb95066bde7cf78a085f9020c62e6dd2e13be0..9d94bf8982ffc6436fc1a5feee62dd1299ad99de 100644 --- a/server/plugins-available/postfix_server_plugin.inc.php +++ b/server/plugins-available/postfix_server_plugin.inc.php @@ -72,6 +72,12 @@ class postfix_server_plugin { global $app, $conf; $postfix_restart = false; + // Plugin should only run on mail servers + if(! $data['new']['mail_server']) { + $app->log("postfix_server_plugin: plugin is enabled but this server is not configured as a mail server.", LOGLEVEL_WARN); + return false; + } + // get the config $app->uses("getconf,system"); $old_ini_data = $app->ini_parser->parse_ini_string($data['old']['config']); @@ -341,6 +347,10 @@ class postfix_server_plugin { for ($i = 0; isset($new_options[$i]); $i++) { if ($new_options[$i] == 'reject_unlisted_recipient') { array_splice($new_options, $i+1, 0, array("check_recipient_access proxy:mysql:${quoted_postfix_config_dir}/mysql-verify_recipients.cf")); + + $app->system->exec_safe("postconf -e ?", 'address_verify_virtual_transport = smtp:[127.0.0.1]:10025'); + $app->system->exec_safe("postconf -e ?", 'address_verify_transport_maps = static:smtp:[127.0.0.1]:10025'); + break; } } @@ -351,62 +361,64 @@ class postfix_server_plugin { } exec("postconf -e 'smtpd_recipient_restrictions = ".implode(", ", $new_options)."'"); - if($mail_config['content_filter'] != $old_ini_data['mail']['content_filter']) { - $rslm = ($mail_config['reject_sender_login_mismatch'] == 'y') ? "reject_sender_login_mismatch," : ""; - $raslm = ($mail_config['reject_sender_login_mismatch'] == 'y') ? "reject_authenticated_sender_login_mismatch," : ""; - - if($mail_config['content_filter'] == 'rspamd'){ - exec("postconf -X 'receive_override_options'"); - exec("postconf -X 'content_filter'"); + $rslm = ($mail_config['reject_sender_login_mismatch'] == 'y') ? "reject_sender_login_mismatch," : ""; + $raslm = ($mail_config['reject_sender_login_mismatch'] == 'y') ? "reject_authenticated_sender_login_mismatch," : ""; - exec("postconf -e 'smtpd_milters = inet:localhost:11332'"); - exec("postconf -e 'non_smtpd_milters = inet:localhost:11332'"); - exec("postconf -e 'milter_protocol = 6'"); - exec("postconf -e 'milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}'"); - exec("postconf -e 'milter_default_action = accept'"); + if($mail_config['content_filter'] == 'rspamd'){ + exec("postconf -X 'receive_override_options'"); + exec("postconf -X 'content_filter'"); + exec("postconf -X address_verify_virtual_transport"); + exec("postconf -X address_verify_transport_maps"); - exec("postconf -e 'smtpd_sender_restrictions = ${raslm} permit_mynetworks, check_sender_access proxy:mysql:/etc/postfix/mysql-virtual_sender.cf, ${rslm} permit_sasl_authenticated, reject_non_fqdn_sender, reject_unlisted_sender'"); + exec("postconf -e 'smtpd_milters = inet:localhost:11332'"); + exec("postconf -e 'non_smtpd_milters = inet:localhost:11332'"); + exec("postconf -e 'milter_protocol = 6'"); + exec("postconf -e 'milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}'"); + exec("postconf -e 'milter_default_action = accept'"); + exec("postconf -e 'smtpd_sender_restrictions = ${raslm} permit_mynetworks, check_sender_access proxy:mysql:/etc/postfix/mysql-virtual_sender.cf, ${rslm} permit_sasl_authenticated, reject_non_fqdn_sender, reject_unlisted_sender'"); - $new_options = array(); - $options = preg_split("/,\s*/", exec("postconf -h smtpd_recipient_restrictions")); - foreach ($options as $key => $value) { - $value = trim($value); - if ($value == '') continue; - if (preg_match('/check_policy_service\s+inet:127.0.0.1:10023/', $value)) { - continue; - } - $new_options[] = $value; - } - exec("postconf -e 'smtpd_recipient_restrictions = ".implode(", ", $new_options)."'"); - - // get all domains that have dkim enabled - if ( substr($mail_config['dkim_path'], strlen($mail_config['dkim_path'])-1) == '/' ) { - $mail_config['dkim_path'] = substr($mail_config['dkim_path'], 0, strlen($mail_config['dkim_path'])-1); + $new_options = array(); + $options = preg_split("/,\s*/", exec("postconf -h smtpd_recipient_restrictions")); + foreach ($options as $key => $value) { + $value = trim($value); + if ($value == '') continue; + if (preg_match('/check_policy_service\s+inet:127.0.0.1:10023/', $value)) { + continue; } - $dkim_domains = $app->db->queryAllRecords('SELECT `dkim_selector`, `domain` FROM `mail_domain` WHERE `dkim` = ? ORDER BY `domain` ASC', 'y'); - $fpp = fopen('/etc/rspamd/local.d/dkim_domains.map', 'w'); - $fps = fopen('/etc/rspamd/local.d/dkim_selectors.map', 'w'); - foreach($dkim_domains as $dkim_domain) { - fwrite($fpp, $dkim_domain['domain'] . ' ' . $mail_config['dkim_path'] . '/' . $dkim_domain['domain'] . '.private' . "\n"); - fwrite($fps, $dkim_domain['domain'] . ' ' . $dkim_domain['dkim_selector'] . "\n"); + if (preg_match("|check_recipient_access\s+proxy:mysql:${quoted_postfix_config_dir}/mysql-verify_recipients.cf|", $value)) { + continue; } - fclose($fpp); - fclose($fps); - unset($dkim_domains); - } else { - exec("postconf -X 'smtpd_milters'"); - exec("postconf -X 'non_smtpd_milters'"); - exec("postconf -X 'milter_protocol'"); - exec("postconf -X 'milter_mail_macros'"); - exec("postconf -X 'milter_default_action'"); - - exec("postconf -e 'receive_override_options = no_address_mappings'"); - exec("postconf -e 'content_filter = " . ($configure_lmtp ? "lmtp" : "amavis" ) . ":[127.0.0.1]:10024'"); + $new_options[] = $value; + } + exec("postconf -e 'smtpd_recipient_restrictions = ".implode(", ", $new_options)."'"); - // fixme: should read this from conf templates - exec("postconf -e 'smtpd_sender_restrictions = ${raslm} check_sender_access regexp:/etc/postfix/tag_as_originating.re, permit_mynetworks, check_sender_access proxy:mysql:/etc/postfix/mysql-virtual_sender.cf, ${rslm} permit_sasl_authenticated, reject_non_fqdn_sender, reject_unlisted_sender, check_sender_access regexp:/etc/postfix/tag_as_foreign.re'"); + // get all domains that have dkim enabled + if ( substr($mail_config['dkim_path'], strlen($mail_config['dkim_path'])-1) == '/' ) { + $mail_config['dkim_path'] = substr($mail_config['dkim_path'], 0, strlen($mail_config['dkim_path'])-1); + } + $dkim_domains = $app->db->queryAllRecords('SELECT `dkim_selector`, `domain` FROM `mail_domain` WHERE `dkim` = ? ORDER BY `domain` ASC', 'y'); + $fpp = fopen('/etc/rspamd/local.d/dkim_domains.map', 'w'); + $fps = fopen('/etc/rspamd/local.d/dkim_selectors.map', 'w'); + foreach($dkim_domains as $dkim_domain) { + fwrite($fpp, $dkim_domain['domain'] . ' ' . $mail_config['dkim_path'] . '/' . $dkim_domain['domain'] . '.private' . "\n"); + fwrite($fps, $dkim_domain['domain'] . ' ' . $dkim_domain['dkim_selector'] . "\n"); } + fclose($fpp); + fclose($fps); + unset($dkim_domains); + } else { + exec("postconf -X 'smtpd_milters'"); + exec("postconf -X 'non_smtpd_milters'"); + exec("postconf -X 'milter_protocol'"); + exec("postconf -X 'milter_mail_macros'"); + exec("postconf -X 'milter_default_action'"); + + exec("postconf -e 'receive_override_options = no_address_mappings'"); + exec("postconf -e 'content_filter = " . ($configure_lmtp ? "lmtp" : "amavis" ) . ":[127.0.0.1]:10024'"); + + // fixme: should read this from conf templates + exec("postconf -e 'smtpd_sender_restrictions = ${raslm} check_sender_access regexp:/etc/postfix/tag_as_originating.re, permit_mynetworks, check_sender_access proxy:mysql:/etc/postfix/mysql-virtual_sender.cf, ${rslm} permit_sasl_authenticated, reject_non_fqdn_sender, reject_unlisted_sender, check_sender_access regexp:/etc/postfix/tag_as_foreign.re'"); } if($mail_config['content_filter'] == 'rspamd' && ($mail_config['rspamd_password'] != $old_ini_data['mail']['rspamd_password'] || $mail_config['content_filter'] != $old_ini_data['mail']['content_filter'])) {