Commit e2a6024b authored by Marius Burkard's avatar Marius Burkard

Implement a more secure way to use exec, system and shell_exec, fixes #5355

parent 2b60a7a9
......@@ -65,6 +65,10 @@ class system {
public function exec_safe($cmd) {
$arg_count = func_num_args();
if($arg_count != substr_count($cmd, '?') + 1) {
trigger_error('Placeholder count not matching argument list.', E_USER_WARNING);
return false;
}
if($arg_count > 1) {
$args = func_get_args();
......
......@@ -544,7 +544,6 @@ class ApsInstaller extends ApsBase
chmod($this->local_installpath.'install_scripts/'.$cfgscript, 0755);
// Change to the install folder (import for the exec() below!)
//exec('chown -R '.$this->file_owner_user.':'.$this->file_owner_group.' '.escapeshellarg($this->local_installpath));
chdir($this->local_installpath.'install_scripts/');
// Set the enviroment variables
......
......@@ -94,9 +94,9 @@ class cronjob_webalizer extends cronjob {
$log_folder .= '/' . $subdomain_host;
unset($tmp);
}
$logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log');
$logfile = $rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log';
if(!@is_file($logfile)) {
$logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log.gz');
$logfile = $rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log.gz';
if(!@is_file($logfile)) {
continue;
}
......
......@@ -147,7 +147,7 @@ class cronjob_logfiles extends cronjob {
}
// rotate and compress the error.log
$error_logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/error.log');
$error_logfile = $rec['document_root'].'/' . $log_folder . '/error.log';
// rename older files (move up by one)
$num = $log_retention;
while($num >= 1) {
......@@ -187,7 +187,7 @@ class cronjob_logfiles extends cronjob {
$ispconfig_logfiles = array('ispconfig.log', 'cron.log', 'auth.log');
foreach($ispconfig_logfiles as $ispconfig_logfile) {
$num = $max_syslog;
$ispconfig_logfile = escapeshellcmd($conf['ispconfig_log_dir'].'/'.$ispconfig_logfile);
$ispconfig_logfile = $conf['ispconfig_log_dir'].'/'.$ispconfig_logfile;
// rename older files (move up by one)
while($num >= 1) {
if(is_file($ispconfig_logfile . '.' . $num . '.gz')) rename($ispconfig_logfile . '.' . $num . '.gz', $ispconfig_logfile . '.' . ($num + 1) . '.gz');
......
......@@ -69,9 +69,9 @@ class cronjob_backup_mail extends cronjob {
$records = $app->db->queryAllRecords("SELECT * FROM mail_user WHERE server_id = ? AND maildir != ''", intval($conf['server_id']));
if(is_array($records) && $run_backups) {
if(!is_dir($backup_dir)) {
mkdir(escapeshellcmd($backup_dir), $backup_dir_permissions, true);
mkdir($backup_dir, $backup_dir_permissions, true);
} else {
chmod(escapeshellcmd($backup_dir), $backup_dir_permissions);
chmod($backup_dir, $backup_dir_permissions);
}
system('which pigz > /dev/null', $ret);
if($ret === 0) {
......@@ -122,7 +122,7 @@ class cronjob_backup_mail extends cronjob {
if ($rec['maildir_format'] == 'mdbox') {
if (empty($this->tmp_backup_dir)) $this->tmp_backup_dir = $rec['maildir'];
// Create temporary backup-mailbox
exec("su -c ?", 'dsync backup -u "'.$rec["email"].'" mdbox:' . $this->tmp_backup_dir . '/backup');
$app->system->exec_safe("su -c ?", 'dsync backup -u "'.$rec["email"].'" mdbox:' . $this->tmp_backup_dir . '/backup');
if($backup_mode == 'userzip') {
$mail_backup_file.='.zip';
......
......@@ -1601,22 +1601,20 @@ class system{
$mail_config = $app->getconf->get_server_config($conf["server_id"], 'mail');
if($subfolder != '') {
$dir = escapeshellcmd($maildir_path.'/.'.$subfolder);
$dir = $maildir_path.'/.'.$subfolder;
} else {
$dir = escapeshellcmd($maildir_path);
$dir = $maildir_path;
}
if(!is_dir($dir)) mkdir($dir, 0700, true);
if($user != '' && $user != 'root' && $this->is_user($user)) {
$user = escapeshellcmd($user);
if(is_dir($dir)) $this->chown($dir, $user);
$chown_mdsub = true;
}
if($group != '' && $group != 'root' && $this->is_group($group)) {
$group = escapeshellcmd($group);
if(is_dir($dir)) $this->chgrp($dir, $group);
$chgrp_mdsub = true;
......@@ -1638,7 +1636,7 @@ class system{
// Courier
if($mail_config['pop3_imap_daemon'] == 'courier') {
if(!is_file($maildir_path.'/courierimapsubscribed')) {
$tmp_file = escapeshellcmd($maildir_path.'/courierimapsubscribed');
$tmp_file = $maildir_path.'/courierimapsubscribed';
touch($tmp_file);
chmod($tmp_file, 0744);
chown($tmp_file, 'vmail');
......@@ -1650,7 +1648,7 @@ class system{
// Dovecot
if($mail_config['pop3_imap_daemon'] == 'dovecot') {
if(!is_file($maildir_path.'/subscriptions')) {
$tmp_file = escapeshellcmd($maildir_path.'/subscriptions');
$tmp_file = $maildir_path.'/subscriptions';
touch($tmp_file);
chmod($tmp_file, 0744);
chown($tmp_file, 'vmail');
......@@ -2059,6 +2057,10 @@ class system{
public function exec_safe($cmd) {
$arg_count = func_num_args();
if($arg_count != substr_count($cmd, '?') + 1) {
trigger_error('Placeholder count not matching argument list.', E_USER_WARNING);
return false;
}
if($arg_count > 1) {
$args = func_get_args();
......
......@@ -150,7 +150,7 @@ class remoteaction_core_module {
$parts = explode(':', $action['action_param']);
$veid = intval($parts[0]);
$template_cache_dir = '/vz/template/cache/';
$template_name = escapeshellcmd($parts[1]);
$template_name = $parts[1];
if($veid > 0 && $template_name != '' && is_dir($template_cache_dir)) {
$command = "vzdump --suspend --compress --stdexcludes --dumpdir ? ?";
$app->system->exec_safe($command, $template_cache_dir, $veid);
......
......@@ -121,7 +121,7 @@ class apps_vhost_plugin {
$app->system->file_put_contents("$vhost_conf_dir/apps.vhost", $content);
// enabled / disable apps-vhost
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/000-apps.vhost');
$vhost_symlink = $web_config['vhost_conf_enabled_dir'].'/000-apps.vhost';
if(is_link($vhost_symlink) && $web_config['apps_vhost_enabled'] == 'n') {
$app->system->unlink($vhost_symlink);
}
......@@ -207,7 +207,7 @@ class apps_vhost_plugin {
file_put_contents("$vhost_conf_dir/apps.vhost", $content);
// enabled / disable apps-vhost
$vhost_symlink = escapeshellcmd($web_config['vhost_conf_enabled_dir'].'/000-apps.vhost');
$vhost_symlink = $web_config['vhost_conf_enabled_dir'].'/000-apps.vhost';
if(is_link($vhost_symlink) && $web_config['apps_vhost_enabled'] == 'n') {
$app->system->unlink($vhost_symlink);
}
......
......@@ -104,13 +104,13 @@ class backup_plugin {
// extract tar.gz archive
$dump_directory = str_replace(".tar.gz", "", $backup['filename']);
$extracted = "/usr/local/ispconfig/server/temp";
exec("tar -xzvf ".escapeshellarg($backup_dir.'/'.$backup['filename'])." --directory=".escapeshellarg($extracted));
$app->system->exec_safe("tar -xzvf ? --directory=?", $backup_dir.'/'.$backup['filename'], $extracted);
$restore_directory = $extracted."/".$dump_directory."/".$db_name;
// mongorestore -h 127.0.0.1 -u root -p 123456 --authenticationDatabase admin -d c1debug --drop ./toRestore
$command = "mongorestore -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d ".$db_name." --drop ".escapeshellarg($restore_directory);
exec($command);
exec("rm -rf ".escapeshellarg($extracted."/".$dump_directory));
$command = "mongorestore -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d ? --drop ?";
$app->system->exec_safe($command, $db_name, $restore_directory);
$app->system->exec_safe("rm -rf ?", $extracted."/".$dump_directory);
}
unset($clientdb_host);
......@@ -129,8 +129,8 @@ class backup_plugin {
//$db_name = $parts[1];
preg_match('@^db_(.+)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.sql\.gz$@', $backup['filename'], $matches);
$db_name = $matches[1];
$command = "gunzip --stdout ".escapeshellarg($backup_dir.'/'.$backup['filename'])." | mysql -h ".escapeshellarg($clientdb_host)." -u ".escapeshellarg($clientdb_user)." -p".escapeshellarg($clientdb_password)." ".escapeshellarg($db_name);
exec($command);
$command = "gunzip --stdout ? | mysql -h ? -u ? -p? ?";
$app->system->exec_safe($command, $backup_dir.'/'.$backup['filename'], $clientdb_host, $clientdb_user, $clientdb_password, $db_name);
}
unset($clientdb_host);
unset($clientdb_user);
......@@ -147,8 +147,8 @@ class backup_plugin {
copy($backup_dir.'/'.$backup['filename'], $web['document_root'].'/backup/'.$backup['filename']);
chgrp($web['document_root'].'/backup/'.$backup['filename'], $web['system_group']);
//chown($web['document_root'].'/backup/'.$backup['filename'],$web['system_user']);
$command = 'sudo -u '.escapeshellarg($web['system_user']).' unzip -qq -o '.escapeshellarg($web['document_root'].'/backup/'.$backup['filename']).' -d '.escapeshellarg($web['document_root']).' 2> /dev/null';
exec($command);
$command = 'sudo -u ? unzip -qq -o ? -d ? 2> /dev/null';
$app->system->exec_safe($command, $web['system_user'], $web['document_root'].'/backup/'.$backup['filename'], $web['document_root']);
unlink($web['document_root'].'/backup/'.$backup['filename']);
if(file_exists($web['document_root'].'/backup/'.$backup['filename'].'.bak')) rename($web['document_root'].'/backup/'.$backup['filename'].'.bak', $web['document_root'].'/backup/'.$backup['filename']);
$app->log('Restored Web backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
......@@ -156,8 +156,8 @@ class backup_plugin {
}
if($backup['backup_mode'] == 'rootgz') {
if(file_exists($backup_dir.'/'.$backup['filename']) && $web['document_root'] != '' && $web['document_root'] != '/' && !stristr($backup_dir.'/'.$backup['filename'], '..') && !stristr($backup_dir.'/'.$backup['filename'], 'etc')) {
$command = 'tar xzf '.escapeshellarg($backup_dir.'/'.$backup['filename']).' --directory '.escapeshellarg($web['document_root']);
exec($command);
$command = 'tar xzf ? --directory ?';
$app->system->exec_safe($command, $backup_dir.'/'.$backup['filename'], $web['document_root']);
$app->log('Restored Web backup '.$backup_dir.'/'.$backup['filename'], LOGLEVEL_DEBUG);
}
}
......@@ -237,22 +237,24 @@ class backup_plugin {
if($mail_backup['backup_mode'] == 'userzip') {
copy($mail_backup_file, $record['maildir'].'/'.$mail_backup['filename']);
chgrp($record['maildir'].'/'.$mail_backup['filename'], $mail_config['mailuser_group']);
$command = 'sudo -u '.$mail_config['mailuser_name'].' unzip -qq -o '.escapeshellarg($record['maildir'].'/'.$mail_backup['filename']).' -d '.escapeshellarg($record['maildir']).' 2> /dev/null';
exec($command,$tmp_output, $retval);
$command = 'sudo -u ? unzip -qq -o ? -d ? 2> /dev/null';
$app->system->exec_safe($command, $mail_config['mailuser_name'], $record['maildir'].'/'.$mail_backup['filename'], $record['maildir']);
$retval = $app->system->last_exec_retcode();
unlink($record['maildir'].'/'.$mail_backup['filename']);
}
if($mail_backup['backup_mode'] == 'rootgz') {
$command='tar xfz '.escapeshellarg($mail_backup_file).' --directory '.escapeshellarg($record['maildir']);
exec($command,$tmp_output, $retval);
} elseif($mail_backup['backup_mode'] == 'rootgz') {
$command='tar xfz ? --directory ?';
$app->system->exec_safe($command, $mail_backup_file, $record['maildir']);
$retval = $app->system->last_exec_retcode();
}
if($retval == 0) {
// Now import backup-mailbox into special backup-folder
$backupname = "backup-".date("Y-m-d", $mail_backup['tstamp']);
exec("doveadm mailbox create -u \"".$record["email"]."\" $backupname");
exec("doveadm import -u \"".$record["email"]."\" mdbox:".$record['maildir']."/backup $backupname all", $tmp_output, $retval);
exec("for f in `doveadm mailbox list -u \"".$record["email"]."\" $backupname*`; do doveadm mailbox subscribe -u \"".$record["email"]."\" \$f; done", $tmp_output, $retval);
exec('rm -rf '.$record['maildir'].'/backup');
$app->system->exec_safe("doveadm mailbox create -u ? ?", $record["email"], $backupname);
$app->system->exec_safe("doveadm import -u ? mdbox:? ? all", $record["email"], $record['maildir']."/backup", $backupname);
$app->system->exec_safe("for f in `doveadm mailbox list -u ? ?*`; do doveadm mailbox subscribe -u ? \$f; done", $record["email"], $backupname, $record["email"]);
$retval = $app->system->last_exec_retcode();
$app->system->exec_safe('rm -rf ?', $record['maildir'].'/backup');
}
if($retval == 0){
......@@ -260,7 +262,7 @@ class backup_plugin {
} else {
// cleanup
if (file_exists($record['maildir'].'/'.$mail_backup['filename'])) unlink($record['maildir'].'/'.$mail_backup['filename']);
if (file_exists($record['maildir']."/backup")) exec('rm -rf '.$record['maildir']."/backup");
if (file_exists($record['maildir']."/backup")) $app->system->exec_safe('rm -rf ?', $record['maildir']."/backup");
$app->log('Unable to restore Mail backup '.$mail_backup_file.' '.$tmp_output,LOGLEVEL_ERROR);
}
......@@ -269,8 +271,10 @@ class backup_plugin {
if($mail_backup['backup_mode'] == 'userzip') {
copy($mail_backup_file, $domain_dir.'/'.$mail_backup['filename']);
chgrp($domain_dir.'/'.$mail_backup['filename'], $mail_config['mailuser_group']);
$command = 'sudo -u '.$mail_config['mailuser_name'].' unzip -qq -o '.escapeshellarg($domain_dir.'/'.$mail_backup['filename']).' -d '.escapeshellarg($domain_dir).' 2> /dev/null';
exec($command,$tmp_output, $retval);
$command = 'sudo -u ? unzip -qq -o ? -d ? 2> /dev/null';
$app->system->exec_safe($command, $mail_config['mailuser_name'], $domain_dir.'/'.$mail_backup['filename'], $domain_dir);
$retval = $app->system->last_exec_retcode();
$tmp_output = $app->system->last_exec_out();
unlink($domain_dir.'/'.$mail_backup['filename']);
if($retval == 0){
$app->log('Restored Mail backup '.$mail_backup_file,LOGLEVEL_DEBUG);
......@@ -279,8 +283,10 @@ class backup_plugin {
}
}
if($mail_backup['backup_mode'] == 'rootgz') {
$command='tar xfz '.escapeshellarg($mail_backup_file).' --directory '.escapeshellarg($domain_dir);
exec($command,$tmp_output, $retval);
$command='tar xfz ? --directory ?';
$app->system->exec_safe($command, $mail_backup_file, $domain_dir);
$retval = $app->system->last_exec_retcode();
$tmp_output = $app->system->last_exec_out();
if($retval == 0){
$app->log('Restored Mail backup '.$mail_backup_file,LOGLEVEL_DEBUG);
} else {
......
......@@ -114,9 +114,7 @@ class bind_plugin {
}
//Do some magic...
exec('cd '.escapeshellcmd($dns_config['bind_zonefiles_dir']).';'.
'dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE '.escapeshellcmd($domain).';'.
'dnssec-keygen -f KSK -a NSEC3RSASHA1 -b 4096 -n ZONE '.escapeshellcmd($domain));
$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);
$this->soa_dnssec_sign($data); //Now sign the zone for the first time
$data['new']['dnssec_initialized']='Y';
......@@ -148,8 +146,7 @@ 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
exec('cd '.escapeshellcmd($dns_config['bind_zonefiles_dir']).';'.
'dnssec-signzone -A -e +1382400 -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N increment -o '.escapeshellcmd($domain).' -t '.$filespre.escapeshellcmd($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 ? -t ?', $dns_config['bind_zonefiles_dir'], $domain, $filespre.$domain);
//Write Data back ino DB
$dnssecdata = "DS-Records:\n".file_get_contents($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.');
......@@ -187,8 +184,8 @@ class bind_plugin {
if (!$new && !file_exists($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.')) $this->soa_dnssec_create($data);
$dbdata = $app->db->queryOneRecord('SELECT id,serial FROM dns_soa WHERE id=?', intval($data['new']['id']));
exec('cd '.escapeshellcmd($dns_config['bind_zonefiles_dir']).';'.
'named-checkzone '.escapeshellcmd($domain).' '.escapeshellcmd($dns_config['bind_zonefiles_dir']).'/'.$filespre.escapeshellcmd($domain).' | egrep -ho \'[0-9]{10}\'', $serial, $retState);
$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);
$retState = $app->system->last_exec_retcode();
if ($retState != 0) {
$app->log('DNSSEC Error: Error in Zonefile for '.$domain, LOGLEVEL_ERR);
return false;
......@@ -283,20 +280,22 @@ class bind_plugin {
//TODO : change this when distribution information has been integrated into server record
if (file_exists('/etc/gentoo-release')) {
$filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/pri/'.str_replace("/", "_", substr($zone['origin'], 0, -1)));
$filename = $dns_config['bind_zonefiles_dir'].'/pri/'.str_replace("/", "_", substr($zone['origin'], 0, -1));
}
else {
$filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($zone['origin'], 0, -1)));
$filename = $dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($zone['origin'], 0, -1));
}
$old_zonefile = @file_get_contents($filename);
file_put_contents($filename, $tpl->grab());
chown($filename, escapeshellcmd($dns_config['bind_user']));
chgrp($filename, escapeshellcmd($dns_config['bind_group']));
chown($filename, $dns_config['bind_user']);
chgrp($filename, $dns_config['bind_group']);
//* Check the zonefile
if(is_file($filename.'.err')) unlink($filename.'.err');
exec('named-checkzone '.escapeshellarg($zone['origin']).' '.escapeshellarg($filename), $out, $return_status);
$app->system->exec_safe('named-checkzone ? ?', $zone['origin'], $filename);
$out = $app->system->last_exec_out();
$return_status = $app->system->last_exec_retcode();
if($return_status === 0) {
$app->log("Writing BIND domain file: ".$filename, LOGLEVEL_DEBUG);
} else {
......@@ -309,8 +308,8 @@ class bind_plugin {
if ($old_zonefile != '') {
rename($filename, $filename.'.err');
file_put_contents($filename, $old_zonefile);
chown($filename, escapeshellcmd($dns_config['bind_user']));
chgrp($filename, escapeshellcmd($dns_config['bind_group']));
chown($filename, $dns_config['bind_user']);
chgrp($filename, $dns_config['bind_group']);
} else {
rename($filename, $filename.'.err');
}
......@@ -392,7 +391,10 @@ class bind_plugin {
$app->log("Deleting BIND domain file: ".$zone_file_name, LOGLEVEL_DEBUG);
//* DNSSEC-Implementation
if ($data['old']['dnssec_initialized'] == 'Y') exec('/usr/local/ispconfig/server/scripts/dnssec-delete.sh '.$data['old']['origin']); //delete keys
if($data['old']['dnssec_initialized'] == 'Y') {
//delete keys
$app->system->exec_safe('/usr/local/ispconfig/server/scripts/dnssec-delete.sh ?', $data['old']['origin']);
}
//* Reload bind nameserver
$app->services->restartServiceDelayed('bind', 'reload');
......@@ -582,11 +584,6 @@ class bind_plugin {
'zonefile_path' => $sec_zonefiles_path.str_replace("/", "_", substr($tmp['origin'], 0, -1)),
'options' => $options
);
// $filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/slave/sec.'.substr($tmp['origin'],0,-1));
// $app->log("Writing BIND domain file: ".$filename,LOGLEVEL_DEBUG);
}
$tpl_sec = new tpl();
......
......@@ -103,20 +103,6 @@ class cron_jailkit_plugin {
if ($data['new']['type'] == "chrooted")
{
// load the server configuration options
/*
$app->uses("getconf");
$this->data = $data;
$this->app = $app;
$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
$this->parent_domain = $parent_domain;
$this->_setup_jailkit_chroot();
//$command .= 'usermod -U '.escapeshellcmd($parent_domain['system_user']);
//exec($command);
$this->_add_jailkit_user();
*/
$app->uses("getconf");
$this->data = $data;
$this->app = $app;
......@@ -130,8 +116,8 @@ class cron_jailkit_plugin {
$this->_add_jailkit_user();
$command .= 'usermod -U '.escapeshellcmd($parent_domain["system_user"]).' 2>/dev/null';
exec($command);
$command .= 'usermod -U ? 2>/dev/null';
$app->system->exec_safe($command, $parent_domain["system_user"]);
$this->_update_website_security_level();
......@@ -231,14 +217,12 @@ class cron_jailkit_plugin {
if (!is_dir($this->parent_domain['document_root'].'/etc/jailkit'))
{
$command = '/usr/local/ispconfig/server/scripts/create_jailkit_chroot.sh';
$command .= ' '.escapeshellcmd($this->parent_domain['document_root']);
$command .= ' \''.$this->jailkit_config['jailkit_chroot_app_sections'].'\'';
exec($command.' 2>/dev/null');
$command .= ' ?';
$command .= ' ?';
$app->system->exec_safe($command.' 2>/dev/null', $this->parent_domain['document_root'], $this->jailkit_config['jailkit_chroot_app_sections']);
$this->app->log("Added jailkit chroot with command: ".$command, LOGLEVEL_DEBUG);
//$this->_add_jailkit_programs(); // done later on
$this->app->load('tpl');
$tpl = new tpl();
......@@ -248,7 +232,7 @@ class cron_jailkit_plugin {
$tpl->setVar('domain', $this->parent_domain['domain']);
$tpl->setVar('home_dir', $this->_get_home_dir(""));
$bashrc = escapeshellcmd($this->parent_domain['document_root']).'/etc/bash.bashrc';
$bashrc = $this->parent_domain['document_root'].'/etc/bash.bashrc';
if(@is_file($bashrc) || @is_link($bashrc)) unlink($bashrc);
$app->system->file_put_contents($bashrc, $tpl->grab());
......@@ -261,7 +245,7 @@ class cron_jailkit_plugin {
$tpl->setVar('domain', $this->parent_domain['domain']);
$motd = escapeshellcmd($this->parent_domain['document_root']).'/var/run/motd';
$motd = $this->parent_domain['document_root'].'/var/run/motd';
if(@is_file($motd) || @is_link($motd)) unlink($motd);
$app->system->file_put_contents($motd, $tpl->grab());
......@@ -276,16 +260,16 @@ class cron_jailkit_plugin {
//copy over further programs and its libraries
$command = '/usr/local/ispconfig/server/scripts/create_jailkit_programs.sh';
$command .= ' '.escapeshellcmd($this->parent_domain['document_root']);
$command .= ' \''.$this->jailkit_config['jailkit_chroot_app_programs'].'\'';
exec($command.' 2>/dev/null');
$command .= ' ?';
$command .= ' ?';
$app->system->exec_safe($command.' 2>/dev/null', $this->parent_domain['document_root'], $this->jailkit_config['jailkit_chroot_app_programs']);
$this->app->log("Added programs to jailkit chroot with command: ".$command, LOGLEVEL_DEBUG);
$command = '/usr/local/ispconfig/server/scripts/create_jailkit_programs.sh';
$command .= ' '.escapeshellcmd($this->parent_domain['document_root']);
$command .= ' \''.$this->jailkit_config['jailkit_chroot_cron_programs'].'\'';
exec($command.' 2>/dev/null');
$command .= ' ?';
$command .= ' ?';
$app->system->exec_safe($command.' 2>/dev/null', $this->parent_domain['document_root'], $this->jailkit_config['jailkit_chroot_cron_programs']);
$this->app->log("Added cron programs to jailkit chroot with command: ".$command, LOGLEVEL_DEBUG);
}
......@@ -298,30 +282,30 @@ class cron_jailkit_plugin {
$jailkit_chroot_userhome = $this->_get_home_dir($this->parent_domain['system_user']);
if(!is_dir($this->parent_domain['document_root'].'/etc')) mkdir($this->parent_domain['document_root'].'/etc');
if(!is_file($this->parent_domain['document_root'].'/etc/passwd')) exec('touch '.$this->parent_domain['document_root'].'/etc/passwd');
if(!is_file($this->parent_domain['document_root'].'/etc/passwd')) $app->system->exec_safe('touch ?', $this->parent_domain['document_root'].'/etc/passwd');
// IMPORTANT!
// ALWAYS create the user. Even if the user was created before
// if we check if the user exists, then a update (no shell -> jailkit) will not work
// and the user has FULL ACCESS to the root of the server!
$command = '/usr/local/ispconfig/server/scripts/create_jailkit_user.sh';
$command .= ' '.escapeshellcmd($this->parent_domain['system_user']);
$command .= ' '.escapeshellcmd($this->parent_domain['document_root']);
$command .= ' '.$jailkit_chroot_userhome;
$command .= ' '.escapeshellcmd("/bin/bash");
exec($command.' 2>/dev/null');
$command .= ' ?';
$command .= ' ?';
$command .= ' ?';
$command .= ' /bin/bash';
$app->system->exec_safe($command.' 2>/dev/null', $this->parent_domain['system_user'], $this->parent_domain['document_root'], $jailkit_chroot_userhome);
$this->app->log("Added jailkit user to chroot with command: ".$command, LOGLEVEL_DEBUG);
$app->system->mkdir(escapeshellcmd($this->parent_domain['document_root'].$jailkit_chroot_userhome), 0755, true);
$app->system->chown(escapeshellcmd($this->parent_domain['document_root'].$jailkit_chroot_userhome), escapeshellcmd($this->parent_domain['system_user']));
$app->system->chgrp(escapeshellcmd($this->parent_domain['document_root'].$jailkit_chroot_userhome), escapeshellcmd($this->parent_domain['system_group']));
$app->system->mkdir($this->parent_domain['document_root'].$jailkit_chroot_userhome, 0755, true);
$app->system->chown($this->parent_domain['document_root'].$jailkit_chroot_userhome, $this->parent_domain['system_user']);
$app->system->chgrp($this->parent_domain['document_root'].$jailkit_chroot_userhome, $this->parent_domain['system_group']);
}
function _get_home_dir($username)
{
return str_replace("[username]", escapeshellcmd($username), $this->jailkit_config["jailkit_chroot_home"]);
return str_replace("[username]", $username, $this->jailkit_config["jailkit_chroot_home"]);
}
//* Update the website root directory permissions depending on the security level
......@@ -345,15 +329,5 @@ class cron_jailkit_plugin {
}
}
//* Wrapper for exec function for easier debugging
private function _exec($command) {
global $app;
$app->log('exec: '.$command, LOGLEVEL_DEBUG);
exec($command);
}
} // end class
?>
......@@ -112,15 +112,15 @@ class cron_plugin {
// Create group and user, if not exist
$app->uses("system");
$groupname = escapeshellcmd($parent_domain["system_group"]);
$groupname = $parent_domain["system_group"];
if($parent_domain["system_group"] != '' && !$app->system->is_group($parent_domain["system_group"])) {
exec("groupadd $groupname");
$app->system->exec_safe("groupadd ?", $groupname);
$app->log("Adding the group: $groupname", LOGLEVEL_DEBUG);
}
$username = escapeshellcmd($parent_domain["system_user"]);
$username = $parent_domain["system_user"];
if($parent_domain["system_user"] != '' && !$app->system->is_user($parent_domain["system_user"])) {
exec("useradd -d ".escapeshellcmd($parent_domain["document_root"])." -g $groupname $username -s /bin/false");
$app->system->exec_safe("useradd -d ? -g ? ? -s /bin/false", $parent_domain["document_root"], $groupname, $username);
$app->log("Adding the user: $username", LOGLEVEL_DEBUG);
}
......@@ -136,19 +136,19 @@ class cron_plugin {
}
// get the primitive folder for document_root and the filesystem, will need it later.
$df_output=explode(" ", exec("df -T " . escapeshellarg($parent_domain["document_root"]) . "|awk 'END{print \$2,\$NF}'"));
$df_output=explode(" ", $app->system->exec_safe("df -T ?|awk 'END{print \$2,\$NF}'", $parent_domain["document_root"]));
$file_system = $df_output[0];
$primitive_root = $df_output[1];
if ( in_array($file_system , array('ext2','ext3','ext4'),true) ) {
exec('setquota -u '. $username . ' ' . $blocks_soft . ' ' . $blocks_hard . ' 0 0 -a &> /dev/null');
exec('setquota -T -u '.$username.' 604800 604800 -a &> /dev/null');
$app->system->exec_safe('setquota -u ? ? ? 0 0 -a &> /dev/null', $username, $blocks_soft, $blocks_hard);
$app->system->exec_safe('setquota -T -u ? 604800 604800 -a &> /dev/null', $username);
} elseif ($file_system == 'xfs') {
exec("xfs_quota -x -c 'limit -u bsoft=$mb_soft" . 'm'. " bhard=$mb_hard" . 'm'. " $username' $primitive_root");
$app->system->exec_safe("xfs_quota -x -c ? ?", "limit -u bsoft=$mb_soft" . 'm'. " bhard=$mb_hard" . 'm'. " $username", $primitive_root);
// xfs only supports timers globally, not per user.
exec("xfs_quota -x -c 'timer -bir -i 604800' $primitive_root");
$app->system->exec_safe("xfs_quota -x -c 'timer -bir -i 604800' ?", $primitive_root);
unset($project_uid, $username_position, $xfs_projects);
unset($primitive_root, $df_output, $mb_hard, $mb_soft);
......@@ -164,7 +164,7 @@ class cron_plugin {
}
// make temp directory writable for the apache and website users
$app->system->chmod(escapeshellcmd($parent_domain["document_root"].'/tmp'), 0777);
$app->system->chmod($parent_domain["document_root"].'/tmp', 0777);
/** TODO READ CRON MASTER **/
......@@ -272,7 +272,7 @@ class cron_plugin {
}
}
$cron_file = escapeshellcmd($cron_config["crontab_dir"].'/ispc_'.$this->parent_domain["system_user"]);
$cron_file = $cron_config["crontab_dir"].'/ispc_'.$this->parent_domain["system_user"];
//TODO : change this when distribution information has been integrated into server record
//* Gentoo vixie-cron requires files to end with .cron in the cron.d directory
if (file_exists('/etc/gentoo-release')) {
......@@ -287,7 +287,7 @@ class cron_plugin {
$app->log("Deleted Cron file $cron_file", LOGLEVEL_DEBUG);
}
$cron_file = escapeshellcmd($cron_config["crontab_dir"].'/ispc_chrooted_'.$this->parent_domain["system_user"]);
$cron_file = $cron_config["crontab_dir"].'/ispc_chrooted_'.$this->parent_domain["system_user"];
if($chr_cmd_count > 0) {
$app->system->file_put_contents($cron_file, $chr_cron_content);
$app->log("Wrote Cron file $cron_file with content:\n$chr_cron_content", LOGLEVEL_DEBUG);
......
......@@ -145,7 +145,7 @@ class firewall_plugin {
//* add tcp ports
foreach($tcp_ports_new_array as $port) {
if(!in_array($port, $tcp_ports_old_array) && $port > 0) {
exec('ufw allow '.$port.'/tcp');
$app->system->exec_safe('ufw allow ?', $port.'/tcp');
$app->log('ufw allow '.$port.'/tcp', LOGLEVEL_DEBUG);
sleep(1);
}
......@@ -154,7 +154,7 @@ class firewall_plugin {
//* remove tcp ports
foreach($tcp_ports_old_array as $port) {
if(!in_array($port, $tcp_ports_new_array) && $port > 0) {
exec('ufw delete allow '.$port.'/tcp');
$app->system->exec_safe('ufw delete allow ?', $port.'/tcp');
$app->log('ufw delete allow '.$port.'/tcp', LOGLEVEL_DEBUG);
sleep(1);
}
......@@ -163,7 +163,7 @@ class firewall_plugin {
//* add udp ports
foreach($udp_ports_new_array as $port) {
if(!in_array($port, $udp_ports_old_array) && $port > 0) {
exec('ufw allow '.$port.'/udp');
$app->system->exec_safe('ufw allow ?', $port.'/udp');
$app->log('ufw allow '.$port.'/udp', LOGLEVEL_DEBUG);
sleep(1);
}
......@@ -172,32 +172,12 @@ class firewall_plugin {
//* remove udp ports
foreach($udp_ports_old_array as $port) {
if(!in_array($port, $udp_ports_new_array) && $port > 0) {
exec('ufw delete allow '.$port.'/udp');
$app->system->exec_safe('ufw delete allow ?', $port.'/udp');
$app->log('ufw delete allow '.$port.'/udp', LOGLEVEL_DEBUG);
sleep(1);
}
}
/*
if($tcp_ports_new != $tcp_ports_old) {
exec('ufw allow to any proto tcp port '.$tcp_ports_new);
$app->log('ufw allow to any proto tcp port '.$tcp_ports_new,LOGLEVEL_DEBUG);
if($event_name == 'firewall_update') {
exec('ufw delete allow to any proto tcp port '.$tcp_ports_old);
$app->log('ufw delete allow to any proto tcp port '.$tcp_ports_old,LOGLEVEL_DEBUG);
}
}
if($udp_ports_new != $udp_ports_old) {
exec('ufw allow to any proto udp port '.$udp_ports_new);
$app->log('ufw allow to any proto udp port '.$udp_ports_new,LOGLEVEL_DEBUG);
if($event_name == 'firewall_update') {
exec('ufw delete allow to any proto udp port '.$udp_ports_old);
$app->log('ufw delete allow to any proto udp port '.$udp_ports_old,LOGLEVEL_DEBUG);
}
}
*/