Skip to content
......@@ -408,6 +408,13 @@
</tmpl_if>
<tmpl_if name='use_tcp'>
#ProxyPassMatch ^/(.*\.php[345]?(/.*)?)$ fcgi://127.0.0.1:<tmpl_var name='fpm_port'><tmpl_var name='web_document_root'>/$1
<Directory {tmpl_var name='web_document_root_www'}>
<FilesMatch "\.php[345]?$">
<If "-f '%{REQUEST_FILENAME}'">
SetHandler "proxy:fcgi://127.0.0.1:<tmpl_var name='fpm_port'>"
</If>
</FilesMatch>
</Directory>
<Directory {tmpl_var name='web_document_root'}>
<FilesMatch "\.php[345]?$">
<If "-f '%{REQUEST_FILENAME}'">
......@@ -418,6 +425,13 @@
</tmpl_if>
<tmpl_if name='use_socket'>
#ProxyPassMatch ^/(.*\.php[345]?(/.*)?)$ unix://<tmpl_var name='fpm_socket'>|fcgi://localhost/<tmpl_var name='web_document_root'>/$1
<Directory {tmpl_var name='web_document_root_www'}>
<FilesMatch "\.php[345]?$">
<If "-f '%{REQUEST_FILENAME}'">
SetHandler "proxy:unix:<tmpl_var name='fpm_socket'>|fcgi://localhost"
</If>
</FilesMatch>
</Directory>
<Directory {tmpl_var name='web_document_root'}>
<FilesMatch "\.php[345]?$">
<If "-f '%{REQUEST_FILENAME}'">
......
......@@ -32,7 +32,17 @@ class cronjob_ftplogfiles extends cronjob {
// Make the ftp logfiles directories world readable to enable ftp access
//######################################################################################################
if(is_dir('/var/log/pure-ftpd/')) exec('chmod +r /var/log/pure-ftpd/*');
$logfile = null;
if(is_dir('/var/log/pure-ftpd/')) {
exec('chmod +r /var/log/pure-ftpd/*');
$logfile="/var/log/pure-ftpd/transfer.log.1";
} elseif(is_file('/var/log/pureftpd.log')) {
$logfile="/var/log/pureftpd.log";
} else {
$app->log("The pure-ftpd log file could not be found.", LOGLEVEL_DEBUG);
return false;
}
//######################################################################################################
// Manage and compress ftp logfiles and create traffic statistics
......@@ -71,7 +81,7 @@ class cronjob_ftplogfiles extends cronjob {
}
}
$fp = @fopen('/var/log/pure-ftpd/transfer.log.1', 'r');
$fp = @fopen($logfile, 'r');
$ftp_traffic = array();
if ($fp) {
......
......@@ -57,6 +57,13 @@ class cronjob_quota_notify extends cronjob {
$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
// Get client email and eventual reseller email
$client_group_id = $rec["sys_groupid"];
$client = $app->db->queryOneRecord("SELECT client.email, client.parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['parent_client_id'] > 0) {
$reseller = $app->db->queryOneRecord("SELECT email FROM client WHERE client_id = ?", $client['parent_client_id']);
}
//######################################################################################################
// enforce traffic quota (run only on the "master-server")
//######################################################################################################
......@@ -107,11 +114,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to reseller
if($web_config['overtraffic_notify_reseller'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['parent_client_id'] > 0) {
$reseller = $app->db->queryOneRecord("SELECT email FROM client WHERE client_id = ?", $client['parent_client_id']);
}
if($reseller['email'] != '') {
$recipients[] = $reseller['email'];
}
......@@ -119,8 +121,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to client
if($web_config['overtraffic_notify_client'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['email'] != '') {
$recipients[] = $client['email'];
}
......@@ -245,11 +245,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to reseller
if($web_config['overquota_notify_reseller'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['parent_client_id'] > 0) {
$reseller = $app->db->queryOneRecord("SELECT email FROM client WHERE client_id = ?", $client['parent_client_id']);
}
if($reseller['email'] != '') {
$recipients[] = $reseller['email'];
}
......@@ -257,8 +252,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to client
if($web_config['overquota_notify_client'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['email'] != '') {
$recipients[] = $client['email'];
}
......@@ -292,11 +285,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to reseller
if($web_config['overquota_notify_reseller'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['parent_client_id'] > 0) {
$reseller = $app->db->queryOneRecord("SELECT email FROM client WHERE client_id = ?", $client['parent_client_id']);
}
if($reseller['email'] != '') {
$recipients[] = $reseller['email'];
}
......@@ -304,8 +292,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to client
if($web_config['overquota_notify_client'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['email'] != '') {
$recipients[] = $client['email'];
}
......@@ -397,11 +383,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to reseller
if($web_config['overquota_notify_reseller'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['parent_client_id'] > 0) {
$reseller = $app->db->queryOneRecord("SELECT email FROM client WHERE client_id = ?", $client['parent_client_id']);
}
if($reseller['email'] != '') {
$recipients[] = $reseller['email'];
}
......@@ -409,8 +390,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to client
if($mail_config['overquota_notify_client'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['email'] != '') {
$recipients[] = $client['email'];
}
......@@ -444,11 +423,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to reseller
if($web_config['overquota_notify_reseller'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['parent_client_id'] > 0) {
$reseller = $app->db->queryOneRecord("SELECT email FROM client WHERE client_id = ?", $client['parent_client_id']);
}
if($reseller['email'] != '') {
$recipients[] = $reseller['email'];
}
......@@ -456,8 +430,6 @@ class cronjob_quota_notify extends cronjob {
//* Send email to client
if($mail_config['overquota_notify_client'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['email'] != '') {
$recipients[] = $client['email'];
}
......@@ -508,9 +480,6 @@ class cronjob_quota_notify extends cronjob {
foreach($cid as $monitor) {
if ($monitor['database_name'] == $database) {
//* get the client
$client = $app->db->queryOneRecord("SELECT client.username, client.email FROM web_database, sys_group, client WHERE web_database.sys_groupid = sys_group.groupid AND sys_group.client_id = client.client_id AND web_database.database_name=?", $database);
//* check quota
if ($quota > 0) $used_ratio = $monitor['size'] / $quota;
else $used_ratio = 0;
......@@ -543,20 +512,17 @@ class cronjob_quota_notify extends cronjob {
//* Send email to reseller
if($web_config['overquota_db_notify_reseller'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['parent_client_id'] > 0) {
$reseller = $app->db->queryOneRecord("SELECT email FROM client WHERE client_id = ?", $client['parent_client_id']);
}
if($reseller['email'] != '') {
$recipients[] = $reseller['email'];
}
}
//* Send email to client
if($web_config['overquota_db_notify_client'] == 'y' && $client['email'] != '')
$recipients[] = $client['email'];
if($web_config['overquota_db_notify_client'] == 'y') {
if($client['email'] != '') {
$recipients[] = $client['email'];
}
}
$this->_tools->send_notification_email('db_quota_notification', $placeholders, $recipients);
}
......@@ -578,24 +544,24 @@ class cronjob_quota_notify extends cronjob {
$recipients = array();
//* send email to admin
if($global_config['admin_mail'] != '' && $web_config['overquota_db_notify_admin'] == 'y')
if($global_config['admin_mail'] != '' && $web_config['overquota_db_notify_admin'] == 'y') {
$recipients[] = $global_config['admin_mail'];
}
//* Send email to reseller
if($web_config['overquota_db_notify_reseller'] == 'y') {
$client_group_id = $rec["sys_groupid"];
$app->db->queryOneRecord("SELECT parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $client_group_id);
if($client['parent_client_id'] > 0) {
$reseller = $app->db->queryOneRecord("SELECT email FROM client WHERE client_id = ?", $client['parent_client_id']);
}
if($reseller['email'] != '') {
$recipients[] = $reseller['email'];
}
}
//* Send email to client
if($web_config['overquota_db_notify_client'] == 'y' && $client['email'] != '')
$recipients[] = $client['email'];
if($mail_config['overquota_notify_client'] == 'y') {
if($client['email'] != '') {
$recipients[] = $client['email'];
}
}
$this->_tools->send_notification_email('db_quota_ok_notification', $placeholders, $recipients);
......
......@@ -77,7 +77,7 @@ class db
$this->dbPort = $port ? $port : $conf['db_port'];
$this->dbName = $database ? $database : $conf['db_database'];
$this->dbUser = $user ? $user : $conf['db_user'];
$this->dbPass = $pass ? $pass : $conf['db_password'];
$this->dbPass = ( $pass !== NULL ) ? $pass : $conf['db_password'];
$this->dbCharset = $conf['db_charset'];
$this->dbClientFlags = ($flags !== NULL) ? $flags : $conf['db_client_flags'];
$this->_iConnId = mysqli_init();
......
......@@ -44,7 +44,7 @@ class letsencrypt {
}
public function get_acme_script() {
$acme = explode("\n", shell_exec('which acme.sh /usr/local/ispconfig/server/scripts/acme.sh /root/.acme.sh/acme.sh'));
$acme = explode("\n", shell_exec('which acme.sh /usr/local/ispconfig/server/scripts/acme.sh /root/.acme.sh/acme.sh 2> /dev/null'));
$acme = reset($acme);
if(is_executable($acme)) {
return $acme;
......
......@@ -470,16 +470,21 @@ class monitor_tools {
}
}
/* Monitor MySQL Server */
$data['mysqlserver'] = -1; // unknown - not needed
if ($services['db_server'] == 1) {
if ($this->_checkTcp($conf['db_host'], $conf['db_port'])) {
$data['mysqlserver'] = 1;
} else {
$data['mysqlserver'] = 0;
$state = 'error'; // because service is down
}
}
/* Monitor MySQL Server */
$data['mysqlserver'] = -1; // unknown - not needed
if ($services['db_server'] == 1) {
// hail MySQL server:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$ispcDB = mysqli_connect($conf['db_host'], $conf['db_user'], $conf['db_password'], $conf['db_database'], $conf['db_port']);
if ($ispcDB !== false) {
$data['mysqlserver'] = 1;
} else {
$data['mysqlserver'] = 0;
$state = 'error'; // because service is down
}
mysqli_close($ispcDB); // we can ignore the result (gwyneth 20220605)
}
/*
$data['mongodbserver'] = -1;
if ($this->_checkTcp('localhost', 27017)) {
......
......@@ -90,7 +90,7 @@ class bind_plugin {
if (!file_exists($dns_config['bind_zonefiles_dir'].'/'.$this->zone_file_prefix().$domain)) return false;
//* Check Entropy
if (file_get_contents('/proc/sys/kernel/random/entropy_avail') < 400) {
if (file_get_contents('/proc/sys/kernel/random/entropy_avail') < 200) {
$app->log('DNSSEC ERROR: We are low on entropy. Not generating new Keys for '.$domain.'. Please consider installing package haveged.', LOGLEVEL_WARN);
echo "DNSSEC ERROR: We are low on entropy. Not generating new Keys for $domain. Please consider installing package haveged.\n";
return false;
......@@ -98,11 +98,11 @@ class bind_plugin {
//* Verify that we do not already have keys (overwriting-protection)
if($data['old']['dnssec_algo'] == $data['new']['dnssec_algo']) {
if (file_exists($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.')) {
if (file_exists($dns_config['bind_keyfiles_dir'].'/dsset-'.$domain.'.')) {
return $this->soa_dnssec_update($data);
} else if ($data['new']['dnssec_initialized'] == 'Y') { //In case that we generated keys but the dsset-file was not generated
$keycount=0;
foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'*.key') as $keyfile) {
foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'*.key') as $keyfile) {
$keycount++;
}
if ($keycount > 0) {
......@@ -116,11 +116,11 @@ class bind_plugin {
$dnssec_algo = explode(',',$data['new']['dnssec_algo']);
//* Create the Zone Signing and Key Signing Keys
if(in_array('ECDSAP256SHA256',$dnssec_algo) && count(glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+013*.key')) == 0) {
$app->system->exec_safe('cd ?; dnssec-keygen -3 -a ECDSAP256SHA256 -n ZONE ?; dnssec-keygen -f KSK -3 -a ECDSAP256SHA256 -n ZONE ?', $dns_config['bind_zonefiles_dir'], $domain, $domain);
if(in_array('ECDSAP256SHA256',$dnssec_algo) && count(glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+013*.key')) == 0) {
$app->system->exec_safe('cd ?; dnssec-keygen -3 -a ECDSAP256SHA256 -n ZONE ?; dnssec-keygen -f KSK -3 -a ECDSAP256SHA256 -n ZONE ?', $dns_config['bind_keyfiles_dir'], $domain, $domain);
}
if(in_array('NSEC3RSASHA1',$dnssec_algo) && count(glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+007*.key')) == 0) {
$app->system->exec_safe('cd ?; dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE ?; dnssec-keygen -f KSK -a NSEC3RSASHA1 -b 4096 -n ZONE ?', $dns_config['bind_zonefiles_dir'], $domain, $domain);
if(in_array('NSEC3RSASHA1',$dnssec_algo) && count(glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+007*.key')) == 0) {
$app->system->exec_safe('cd ?; dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE ?; dnssec-keygen -f KSK -a NSEC3RSASHA1 -b 4096 -n ZONE ?', $dns_config['bind_keyfiles_dir'], $domain, $domain);
}
$this->soa_dnssec_sign($data); //Now sign the zone for the first time
......@@ -149,8 +149,8 @@ class bind_plugin {
//* Include ECDSAP256SHA256 keys in zone
if(in_array('ECDSAP256SHA256',$dnssec_algo)) {
foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+013*.key') as $keyfile) {
$includeline = '$INCLUDE '.basename($keyfile);
foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+013*.key') as $keyfile) {
$includeline = '$INCLUDE ' . $keyfile;
if (!preg_match('@'.preg_quote($includeline).'@', $zonefile)) $zonefile .= "\n".$includeline."\n";
$keycount++;
}
......@@ -158,8 +158,8 @@ class bind_plugin {
//* Include NSEC3RSASHA1 keys in zone
if(in_array('NSEC3RSASHA1',$dnssec_algo)) {
foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+007*.key') as $keyfile) {
$includeline = '$INCLUDE '.basename($keyfile);
foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+007*.key') as $keyfile) {
$includeline = '$INCLUDE ' . $keyfile;
if (!preg_match('@'.preg_quote($includeline).'@', $zonefile)) $zonefile .= "\n".$includeline."\n";
$keycount++;
}
......@@ -171,20 +171,20 @@ class bind_plugin {
file_put_contents($dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain, $zonefile);
//* Sign the zone and set it valid for max. 16 days
$app->system->exec_safe('cd ?; dnssec-signzone -A -e +1382400 -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N increment -o ? -t ?', $dns_config['bind_zonefiles_dir'], $domain, $filespre.$domain);
$app->system->exec_safe('cd ?; dnssec-signzone -A -e +1382400 -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N increment -o ? -K ? -t ?', $dns_config['bind_zonefiles_dir'], $domain, $dns_config['bind_keyfiles_dir'], $dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain);
//* Write Data back ino DB
$dnssecdata = "DS-Records:\n".file_get_contents($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.');
$dnssecdata = "DS-Records:\n".file_get_contents($dns_config['bind_keyfiles_dir'].'/dsset-'.$domain.'.');
$dnssecdata .= "\n------------------------------------\n\nDNSKEY-Records:\n";
if(in_array('ECDSAP256SHA256',$dnssec_algo)) {
foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+013*.key') as $keyfile) {
foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+013*.key') as $keyfile) {
$dnssecdata .= file_get_contents($keyfile)."\n\n";
}
}
if(in_array('NSEC3RSASHA1',$dnssec_algo)) {
foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+007*.key') as $keyfile) {
foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+007*.key') as $keyfile) {
$dnssecdata .= file_get_contents($keyfile)."\n\n";
}
}
......@@ -213,7 +213,7 @@ class bind_plugin {
return false;
}
if (!$new && !file_exists($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.')) $this->soa_dnssec_create($data);
if (!$new && !file_exists($dns_config['bind_keyfiles_dir'].'/dsset-'.$domain.'.')) $this->soa_dnssec_create($data);
$dbdata = $app->db->queryOneRecord('SELECT id,serial FROM dns_soa WHERE id=?', intval($data['new']['id']));
$app->system->exec_safe('cd ?; named-checkzone ? ? | egrep -ho \'[0-9]{10}\'', $dns_config['bind_zonefiles_dir'], $domain, $dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain);
......@@ -237,12 +237,12 @@ class bind_plugin {
$domain = substr($data['new']['origin'], 0, strlen($data['new']['origin'])-1);
$key_files = glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+*');
$key_files = glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+*');
foreach($key_files as $file) {
unlink($file);
}
unlink($dns_config['bind_zonefiles_dir'].'/'.$this->zone_file_prefix().$domain.'.signed');
unlink($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.');
unlink($dns_config['bind_keyfiles_dir'].'/dsset-'.$domain.'.');
if ($app->dbmaster !== $app->db) $app->dbmaster->query('UPDATE dns_soa SET dnssec_info=\'\', dnssec_initialized=\'N\' WHERE id=?', intval($data['new']['id']));
$app->db->query('UPDATE dns_soa SET dnssec_info=\'\', dnssec_initialized=\'N\' WHERE id=?', intval($data['new']['id']));
......@@ -323,6 +323,10 @@ class bind_plugin {
}
}
}
else {
$app->log("DNS zone[".$zone['origin']."] has no records yet, skip...", LOGLEVEL_DEBUG);
return;
}
$tpl->setLoop('zones', $records);
$filename = $dns_config['bind_zonefiles_dir'].'/' . $this->zone_file_prefix() . str_replace("/", "_", substr($zone['origin'], 0, -1));
......
......@@ -429,8 +429,19 @@ class mail_plugin {
$maildir_path_deleted = false;
$old_maildir_path = $data['old']['maildir'];
if($old_maildir_path != $mail_config['homedir_path'] && strlen($old_maildir_path) > strlen($mail_config['homedir_path']) && !stristr($old_maildir_path, '//') && !stristr($old_maildir_path, '..') && !stristr($old_maildir_path, '*') && strlen($old_maildir_path) >= 10) {
$app->system->exec_safe('rm -rf ?', $old_maildir_path);
$app->log('Deleted the Maildir: '.$data['old']['maildir'], LOGLEVEL_DEBUG);
if ($mail_config['mailbox_soft_delete'] == 'y') {
// Move it, adding a date based suffix. A cronjob should purge or archive.
$thrash_maildir_path = $old_maildir_path . '-deleted-' . date("YmdHis");
$app->system->exec_safe('mv ? ?', $old_maildir_path, $thrash_maildir_path);
// Update the dir's timestamp to make filtering on age easier in any cleanup cronjob.
$app->system->exec_safe('touch ?', $thrash_maildir_path);
$app->log('Renamed the Maildir: ' . $data['old']['maildir'] . ' to ' . $thrash_maildir_path, LOGLEVEL_DEBUG);
} else {
$app->system->exec_safe('rm -rf ?', $old_maildir_path);
$app->log('Deleted the Maildir: '.$data['old']['maildir'], LOGLEVEL_DEBUG);
}
$maildir_path_deleted = true;
} else {
$app->log('Possible security violation when deleting the maildir: '.$data['old']['maildir'], LOGLEVEL_ERROR);
......@@ -473,8 +484,19 @@ class mail_plugin {
//* Delete maildomain path
$old_maildomain_path = $mail_config['homedir_path'].'/'.$data['old']['domain'];
if($old_maildomain_path != $mail_config['homedir_path'] && !stristr($old_maildomain_path, '//') && !stristr($old_maildomain_path, '..') && !stristr($old_maildomain_path, '*') && !stristr($old_maildomain_path, '&') && strlen($old_maildomain_path) >= 10 && !empty($data['old']['domain'])) {
$app->system->exec_safe('rm -rf ?', $old_maildomain_path);
$app->log('Deleted the mail domain directory: '.$old_maildomain_path, LOGLEVEL_DEBUG);
if ($mail_config['mailbox_soft_delete'] == 'y') {
// Move it, adding a date based suffix. A cronjob should purge or archive.
$thrash_maildomain_path = $old_maildomain_path . '-deleted-' . date("YmdHis");
$app->system->exec_safe('mv ? ?', $old_maildomain_path, $thrash_maildomain_path);
// Update the dir's timestamp to make filtering on age easier in any cleanup cronjob.
$app->system->exec_safe('touch ?', $thrash_maildomain_path);
$app->log('Renamed the mail domain directory: ' . $old_maildomain_path . ' to ' . $thrash_maildomain_path, LOGLEVEL_DEBUG);
} else {
$app->system->exec_safe('rm -rf ?', $old_maildomain_path);
$app->log('Deleted the mail domain directory: '.$old_maildomain_path, LOGLEVEL_DEBUG);
}
$maildomain_path_deleted = true;
} else {
$app->log('Possible security violation when deleting the mail domain directory: '.$old_maildomain_path, LOGLEVEL_ERROR);
......
#!/bin/bash
# Archive directories for deleted mailboxes.
delay_days=7
# Test if there is something to do... to avoid 'No such file or directory' from find later.
ls /var/vmail/*/[a-z0-9.-]*-deleted-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] >/dev/null 2>&1
if [ $? != 0 ]; then
exit 0;
fi
function remove_soft_deleted_mailbox {
dir=$1
echo "Purging $dir"
rm -r "$dir"
}
function compress_soft_deleted_mailbox {
dir=$1
backupfile="${dir}.tar.bz2"
# Test if backup file already exists
if [ -f $backupfile ]; then
# Skip
echo "ERROR: Backupfile($backupfile) exists!" >&2
continue
fi
echo "Compressing for $dir"
tar cvfj "$backupfile" --remove-files "$dir" 2> >( grep -v "tar: Removing leading" >&2)
}
# List deleted mailboxs to archive
# -mtime +7 ===> Only mailboxes deleted more then 7 days ago
# Test that the last dir component matches e.g. xxx-deleted-20220101094242 (14 digits)
# command: xxx-`date "+%Y%m%d%H%M%S"`
find /var/vmail/*/[a-z0-9.-]*-deleted-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] -maxdepth 0 -type d -mtime +$delay_days | while read line; do
# example $line: "/var/vmail/example.com/info-20220101094242"
dir=$line
# Uncomment the desired cleanup method below, or be creative and create your own.
remove_soft_deleted_mailbox $dir
#compress_soft_deleted_mailbox $dir
done