Commit 2b60a7a9 authored by Marius Burkard's avatar Marius Burkard

WIP: change system exec calls to safe variant

parent 2d6d9eb4
......@@ -78,7 +78,7 @@ class app {
$this->uses($prop);
if(property_exists($this, $prop)) return $this->{$prop};
else return null;
else trigger_error('Undefined property ' . $name . ' of class app', E_USER_WARNING);
}
public function __destruct() {
......
......@@ -451,9 +451,9 @@ class functions {
if(file_exists($id_rsa_file)) unset($id_rsa_file);
if(file_exists($id_rsa_pub_file)) unset($id_rsa_pub_file);
if(!file_exists($id_rsa_file) && !file_exists($id_rsa_pub_file)) {
exec('ssh-keygen -t rsa -C '.$username.'-rsa-key-'.time().' -f '.$id_rsa_file.' -N ""');
$app->system->exec_safe('ssh-keygen -t rsa -C ? -f ? -N ""', $username.'-rsa-key-'.time(), $id_rsa_file);
$app->db->query("UPDATE client SET created_at = UNIX_TIMESTAMP(), id_rsa = ?, ssh_rsa = ? WHERE client_id = ?", @file_get_contents($id_rsa_file), @file_get_contents($id_rsa_pub_file), $client_id);
exec('rm -f '.$id_rsa_file.' '.$id_rsa_pub_file);
$app->system->exec_safe('rm -f ? ?', $id_rsa_file, $id_rsa_pub_file);
} else {
$app->log("Failed to create SSH keypair for ".$username, LOGLEVEL_WARN);
}
......
......@@ -31,6 +31,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class system {
var $client_service = null;
private $_last_exec_out = null;
private $_last_exec_retcode = null;
public function has_service($userid, $service) {
global $app;
......@@ -52,8 +54,43 @@ class system {
return false;
}
}
} //* End Class
?>
public function last_exec_out() {
return $this->_last_exec_out;
}
public function last_exec_retcode() {
return $this->_last_exec_retcode;
}
public function exec_safe($cmd) {
$arg_count = func_num_args();
if($arg_count > 1) {
$args = func_get_args();
$pos = 0;
$a = 0;
foreach($args as $value) {
$a++;
$pos = strpos($cmd, '?', $pos);
if($pos === false) {
break;
}
$value = escapeshellarg($value);
$cmd = substr_replace($cmd, $value, $pos, 1);
$pos += strlen($value);
}
}
$this->_last_exec_out = null;
$this->_last_exec_retcode = null;
return exec($cmd, $this->_last_exec_out, $this->_last_exec_retcode);
}
public function system_safe($cmd) {
call_user_func_array(array($this, 'exec_safe'), func_get_args());
return implode("\n", $this->_last_exec_out);
}
} //* End Class
......@@ -49,10 +49,13 @@ class validate_dkim {
* Validator function for private DKIM-Key
*/
function check_private_key($field_name, $field_value, $validator) {
global $app;
$dkim_enabled=$_POST['dkim'];
if ($dkim_enabled == 'y') {
if (empty($field_value)) return $this->get_error($validator['errmsg']);
exec('echo '.escapeshellarg($field_value).'|openssl rsa -check', $output, $result);
$app->system->exec_safe('echo ?|openssl rsa -check', $field_value);
$result = $app->system->last_exec_retcode();
if($result != 0) return $this->get_error($validator['errmsg']);
}
}
......
......@@ -54,8 +54,8 @@ if($type == 'create_dkim' && $domain_id != ''){
if ($dkim_strength=='') $dkim_strength = 2048;
$rnd_val = $dkim_strength * 10;
exec('openssl rand -out ../../temp/random-data.bin '.$rnd_val.' 2> /dev/null', $output, $result);
exec('openssl genrsa -rand ../../temp/random-data.bin '.$dkim_strength.' 2> /dev/null', $privkey, $result);
$app->system->exec_safe('openssl rand -out ../../temp/random-data.bin '.$rnd_val.' 2> /dev/null', $output, $result);
$app->system->exec_safe('openssl genrsa -rand ../../temp/random-data.bin '.$dkim_strength.' 2> /dev/null', $privkey, $result);
unlink("../../temp/random-data.bin");
$dkim_private='';
foreach($privkey as $values) $dkim_private=$dkim_private.$values."\n";
......@@ -79,12 +79,14 @@ if($type == 'create_dkim' && $domain_id != ''){
$selector = 'invalid domain or selector';
}
unset($dkim_public);
exec('echo '.escapeshellarg($dkim_private).'|openssl rsa -pubout -outform PEM 2> /dev/null',$pubkey,$result);
$app->system->exec_safe('echo ?|openssl rsa -pubout -outform PEM 2> /dev/null', $dkim_private);
$pubkey = $app->system->last_exec_out();
foreach($pubkey as $values) $dkim_public=$dkim_public.$values."\n";
$selector = $dkim_selector;
} else {
unset($dkim_public);
exec('echo '.escapeshellarg($dkim_private).'|openssl rsa -pubout -outform PEM 2> /dev/null',$pubkey,$result);
$app->system->exec_safe('echo ?|openssl rsa -pubout -outform PEM 2> /dev/null', $dkim_private);
$pubkey = $app->system->last_exec_out();
foreach($pubkey as $values) $dkim_public=$dkim_public.$values."\n";
$selector = $dkim_selector;
}
......
......@@ -69,6 +69,22 @@ class app {
}
public function __get($name) {
$valid_names = array('functions', 'getconf', 'letsencrypt', 'modules', 'plugins', 'services', 'system');
if(!in_array($name, $valid_names)) {
trigger_error('Undefined property ' . $name . ' of class app', E_USER_WARNING);
}
if(property_exists($this, $name)) {
return $this->{$name};
}
$this->uses($name);
if(property_exists($this, $name)) {
return $this->{$name};
} else {
trigger_error('Undefined property ' . $name . ' of class app', E_USER_WARNING);
}
}
function setCaller($caller) {
$this->_calling_script = $caller;
}
......
......@@ -395,7 +395,7 @@ class ApsInstaller extends ApsBase
mkdir($this->document_root, 0777, true);
}
} else {
exec("rm -Rf ".escapeshellarg($this->local_installpath).'*');
$app->system->exec_safe("rm -Rf ?*", $this->local_installpath);
}
} else {
mkdir($this->local_installpath, 0777, true);
......@@ -412,7 +412,7 @@ class ApsInstaller extends ApsBase
|| ($this->extractZip($this->packages_dir.'/'.$task['path'], 'scripts', $this->local_installpath.'install_scripts/') === false) )
{
// Clean already extracted data
exec("rm -Rf ".escapeshellarg($this->local_installpath).'*');
$app->system->exec_safe("rm -Rf ?*", $this->local_installpath);
throw new Exception('Unable to extract the package '.$task['path']);
}
......@@ -423,11 +423,11 @@ class ApsInstaller extends ApsBase
$owner_res = $app->db->queryOneRecord("SELECT system_user, system_group FROM web_domain WHERE domain = ?", $main_domain['value']);
$this->file_owner_user = $owner_res['system_user'];
$this->file_owner_group = $owner_res['system_group'];
exec('chown -R '.$this->file_owner_user.':'.$this->file_owner_group.' '.escapeshellarg($this->local_installpath));
$app->system->exec_safe('chown -R ?:? ?', $this->file_owner_user, $this->file_owner_group, $this->local_installpath);
//* Chown stats directory back
if(is_dir($this->local_installpath.'stats')) {
exec('chown -R root:root '.escapeshellarg($this->local_installpath.'stats'));
$app->system->exec_safe('chown -R root:root ?', $this->local_installpath.'stats');
}
}
}
......@@ -554,7 +554,9 @@ class ApsInstaller extends ApsBase
$shell_retcode = true;
$shell_ret = array();
exec('php '.escapeshellarg($this->local_installpath.'install_scripts/'.$cfgscript).' install 2>&1', $shell_ret, $shell_retcode);
$app->system->exec_safe('php ? install 2>&1', $this->local_installpath.'install_scripts/'.$cfgscript);
$shell_ret = $app->system->last_exec_out();
$shell_retcode = $app->system->last_exec_retcode();
$shell_ret = array_filter($shell_ret);
$shell_ret_str = implode("\n", $shell_ret);
......@@ -566,11 +568,11 @@ class ApsInstaller extends ApsBase
else
{
// The install succeeded, chown newly created files too
exec('chown -R '.$this->file_owner_user.':'.$this->file_owner_group.' '.escapeshellarg($this->local_installpath));
$app->system->exec_safe('chown -R ?:? ?', $this->file_owner_user, $this->file_owner_group, $this->local_installpath);
//* Chown stats directory back
if(is_dir($this->local_installpath.'stats')) {
exec('chown -R root:root '.escapeshellarg($this->local_installpath.'stats'));
$app->system->exec_safe('chown -R root:root ?', $this->local_installpath.'stats');
}
$app->dbmaster->query('UPDATE aps_instances SET instance_status = ? WHERE id = ?', INSTANCE_SUCCESS, $task['instance_id']);
......@@ -597,8 +599,9 @@ class ApsInstaller extends ApsBase
*/
private function cleanup($task, $sxe)
{
global $app;
chdir($this->local_installpath);
exec("rm -Rf ".escapeshellarg($this->local_installpath).'install_scripts');
$app->system->exec_safe("rm -Rf ?", $this->local_installpath.'install_scripts');
}
......
......@@ -90,7 +90,7 @@ class cronjob_monitor_email_quota extends cronjob {
$email_parts = explode('@', $mb['email']);
$filename = $mb['maildir'].'/.quotausage';
if(!file_exists($filename) && $dovecot) {
exec('doveadm quota recalc -u '.$email);
$app->system->exec_safe('doveadm quota recalc -u ?', $email);
}
if(file_exists($filename) && !is_link($filename)) {
$quotafile = file($filename);
......@@ -99,7 +99,8 @@ class cronjob_monitor_email_quota extends cronjob {
$app->log("Mail storage $email: " . $storage_value[1], LOGLEVEL_DEBUG);
unset($quotafile);
} else {
exec('du -s '.escapeshellcmd($mb['maildir']), $out);
$app->system->exec_safe('du -s ?', $mb['maildir']);
$out = $app->system->last_exec_out();
$parts = explode(' ', $out[0]);
$data[$email]['used'] = intval($parts[0])*1024;
unset($out);
......
......@@ -71,16 +71,16 @@ class cronjob_awstats 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;
}
}
$web_folder = (($rec['type'] == 'vhostsubdomain' || $rec['type'] == 'vhostalias') ? $rec['web_folder'] : 'web');
$domain = escapeshellcmd($rec['domain']);
$statsdir = escapeshellcmd($rec['document_root'].'/'.$web_folder.'/stats');
$domain = $rec['domain'];
$statsdir = $rec['document_root'].'/'.$web_folder.'/stats';
$awstats_pl = $web_config['awstats_pl'];
$awstats_buildstaticpages_pl = $web_config['awstats_buildstaticpages_pl'];
......@@ -117,8 +117,8 @@ class cronjob_awstats extends cronjob {
}
if(!@is_dir($statsdir)) mkdir($statsdir);
$username = escapeshellcmd($rec['system_user']);
$groupname = escapeshellcmd($rec['system_group']);
$username = $rec['system_user'];
$groupname = $rec['system_group'];
chown($statsdir, $username);
chgrp($statsdir, $groupname);
if(is_link('/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log')) unlink('/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log');
......@@ -138,7 +138,7 @@ class cronjob_awstats extends cronjob {
// awstats_buildstaticpages.pl -update -config=mydomain.com -lang=en -dir=/var/www/domain.com/'.$web_folder.'/stats -awstatsprog=/path/to/awstats.pl
// $command = "$awstats_buildstaticpages_pl -update -config='$domain' -lang=".$conf['language']." -dir='$statsdir' -awstatsprog='$awstats_pl'";
$command = "$awstats_buildstaticpages_pl -month='$awmonth' -year='$awyear' -update -config='$domain' -lang=".$conf['language']." -dir='$statsdir' -awstatsprog='$awstats_pl'";
$command = escapeshellcmd($awstats_buildstaticpages_pl) . ' -month=' . escapeshellarg($awmonth) . ' -year=' . escapeshellarg($awyear) . ' -update -config=' . escapeshellarg($domain) . ' -lang=' . escapeshellarg($conf['language']) . ' -dir=' . escapeshellarg($statsdir) . ' -awstatsprog=' . escapeshellarg($awstats_pl);
if (date("d") == 2) {
$awmonth = date("m")-1;
......@@ -178,7 +178,7 @@ class cronjob_awstats extends cronjob {
chgrp($rec['document_root']."/".$web_folder."/stats/index.php", $rec['system_group']);
}
exec('chown -R '.$username.':'.$groupname.' '.$statsdir);
$app->system->exec_safe('chown -R ?:? ?', $username, $groupname, $statsdir);
}
......
......@@ -102,11 +102,11 @@ class cronjob_webalizer extends cronjob {
}
}
$domain = escapeshellcmd($rec['domain']);
$statsdir = escapeshellcmd($rec['document_root'].'/'.(($rec['type'] == 'vhostsubdomain' || $rec['type'] == 'vhostalias') ? $rec['web_folder'] : 'web').'/stats');
$domain = $rec['domain'];
$statsdir = $rec['document_root'].'/'.(($rec['type'] == 'vhostsubdomain' || $rec['type'] == 'vhostalias') ? $rec['web_folder'] : 'web').'/stats';
$webalizer = '/usr/bin/webalizer';
$webalizer_conf_main = '/etc/webalizer/webalizer.conf';
$webalizer_conf = escapeshellcmd($rec['document_root'].'/log/webalizer.conf');
$webalizer_conf = $rec['document_root'].'/log/webalizer.conf';
if(is_file($statsdir.'/index.php')) unlink($statsdir.'/index.php');
......@@ -122,13 +122,13 @@ class cronjob_webalizer extends cronjob {
if(!@is_dir($statsdir)) mkdir($statsdir);
$username = escapeshellcmd($rec['system_user']);
$groupname = escapeshellcmd($rec['system_group']);
$username = $rec['system_user'];
$groupname = $rec['system_group'];
chown($statsdir, $username);
chgrp($statsdir, $groupname);
exec("$webalizer -c $webalizer_conf -n $domain -s $domain -r $domain -q -T -p -o $statsdir $logfile");
$app->system->exec_safe("$webalizer -c ? -n ? -s ? -r ? -q -T -p -o ? ?", $webalizer_conf, $domain, $domain, $domain, $statsdir, $logfile);
exec('chown -R '.$username.':'.$groupname.' '.$statsdir);
exec('chown -R ?:? ?', $username, $groupname, $statsdir);
}
......
......@@ -54,7 +54,7 @@ class cronjob_logfiles extends cronjob {
$server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
if($server_config['log_retention'] > 0) {
$max_syslog = $server_config['log_retention'];
$max_syslog = $app->functions->intval($server_config['log_retention']);
} else {
$max_syslog = 10;
}
......@@ -113,18 +113,18 @@ class cronjob_logfiles extends cronjob {
}
$yesterday2 = date('Ymd', time() - 86400*2);
$logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday2.'-access.log');
$logfile = $rec['document_root'].'/' . $log_folder . '/'.$yesterday2.'-access.log';
//* Compress logfile
if(@is_file($logfile)) {
// Compress yesterdays logfile
exec("gzip -c $logfile > $logfile.gz");
$app->system->exec_safe("gzip -c ? > ?", $logfile, $logfile . '.gz');
unlink($logfile);
}
$cron_logfiles = array('cron.log', 'cron_error.log', 'cron_wget.log');
foreach($cron_logfiles as $cron_logfile) {
$cron_logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/' . $cron_logfile);
$cron_logfile = $rec['document_root'].'/' . $log_folder . '/' . $cron_logfile;
// rename older files (move up by one)
$num = $log_retention;
......@@ -135,8 +135,8 @@ class cronjob_logfiles extends cronjob {
// compress current logfile
if(is_file($cron_logfile)) {
exec("gzip -c $cron_logfile > $cron_logfile.1.gz");
exec("cat /dev/null > $cron_logfile");
$app->system->exec_safe("gzip -c ? > ?", $cron_logfile, $cron_logfile . '.1.gz');
$app->system->exec_safe("cat /dev/null > ?", $cron_logfile);
}
// remove older logs
$num = $log_retention;
......@@ -156,8 +156,8 @@ class cronjob_logfiles extends cronjob {
}
// compress current logfile
if(is_file($error_logfile)) {
exec("gzip -c $error_logfile > $error_logfile.1.gz");
exec("cat /dev/null > $error_logfile");
$app->system->exec_safe("gzip -c ? > ?", $error_logfile, $error_logfile . '.1.gz');
$app->system->exec_safe("cat /dev/null > ?", $error_logfile);
}
// delete logfiles after x days (default 10)
......@@ -175,7 +175,7 @@ class cronjob_logfiles extends cronjob {
//* Delete old logfiles in /var/log/ispconfig/httpd/ that were created by vlogger for the hostname of the server
exec('hostname -f', $tmp_hostname);
if($tmp_hostname[0] != '' && is_dir('/var/log/ispconfig/httpd/'.$tmp_hostname[0])) {
exec('cd /var/log/ispconfig/httpd/'.$tmp_hostname[0]."; find . -mtime +$max_syslog -name '*.log' | xargs rm > /dev/null 2> /dev/null");
$app->system->exec_safe("cd ?; find . -mtime +$max_syslog -name '*.log' | xargs rm > /dev/null 2> /dev/null", '/var/log/ispconfig/httpd/'.$tmp_hostname[0]);
}
unset($tmp_hostname);
......@@ -195,8 +195,8 @@ class cronjob_logfiles extends cronjob {
}
// compress current logfile
if(is_file($ispconfig_logfile)) {
exec("gzip -c $ispconfig_logfile > $ispconfig_logfile.1.gz");
exec("cat /dev/null > $ispconfig_logfile");
$app->system->exec_safe("gzip -c ? > ?", $ispconfig_logfile, $ispconfig_logfile . '.1.gz');
$app->system->exec_safe("cat /dev/null > ?", $ispconfig_logfile);
}
// remove older logs
$num = $max_syslog;
......@@ -215,9 +215,9 @@ class cronjob_logfiles extends cronjob {
$app->uses('system');
if(is_array($records)) {
foreach($records as $rec){
$tmp_path = realpath(escapeshellcmd($rec['document_root'].'/tmp'));
$tmp_path = realpath($rec['document_root'].'/tmp');
if($tmp_path != '' && strlen($tmp_path) > 10 && is_dir($tmp_path) && $app->system->is_user($rec['system_user'])){
exec('cd '.$tmp_path."; find . -mtime +1 -name 'sess_*' | grep -v -w .no_delete | xargs rm > /dev/null 2> /dev/null");
exec("cd ?; find . -mtime +1 -name 'sess_*' | grep -v -w .no_delete | xargs rm > /dev/null 2> /dev/null", $tmp_path);
}
}
}
......
......@@ -69,9 +69,9 @@ class cronjob_backup extends cronjob {
}
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);
}
$run_backups = true;
//* mount backup directory, if necessary
......@@ -127,16 +127,20 @@ class cronjob_backup extends cronjob {
if($backup_mode == 'userzip') {
//* Create a .zip backup as web user and include also files owned by apache / nginx user
$web_backup_file = 'web'.$web_id.'_'.date('Y-m-d_H-i').'.zip';
exec('cd '.escapeshellarg($web_path).' && sudo -u '.escapeshellarg($web_user).' find . -group '.escapeshellarg($web_group).' -print 2> /dev/null | zip -b '.escapeshellarg($backup_tmp).' --exclude=./backup\*'.$backup_excludes.' --symlinks '.escapeshellarg($web_backup_dir.'/'.$web_backup_file).' -@', $tmp_output, $retval);
if($retval == 0 || $retval == 12) exec('cd '.escapeshellarg($web_path).' && sudo -u '.escapeshellarg($web_user).' find . -user '.escapeshellarg($http_server_user).' -print 2> /dev/null | zip -b '.escapeshellarg($backup_tmp).' --exclude=./backup\*'.$backup_excludes.' --update --symlinks '.escapeshellarg($web_backup_dir.'/'.$web_backup_file).' -@', $tmp_output, $retval);
$app->system->exec_safe('cd ? && sudo -u ? find . -group ? -print 2> /dev/null | zip -b ? --exclude=./backup\*'.$backup_excludes.' --symlinks ? -@', $web_path, $web_user, $web_group, $backup_tmp, $web_backup_dir.'/'.$web_backup_file);
$retval = $app->system->last_exec_retcode();
if($retval == 0 || $retval == 12) $app->system->exec_safe('cd ? && sudo -u ? find . -user ? -print 2> /dev/null | zip -b ? --exclude=./backup\*'.$backup_excludes.' --update --symlinks ? -@', $web_path, $web_user, $http_server_user, $backup_tmp, $web_backup_dir.'/'.$web_backup_file);
$retval = $app->system->last_exec_retcode();
} else {
//* Create a tar.gz backup as root user
$web_backup_file = 'web'.$web_id.'_'.date('Y-m-d_H-i').'.tar.gz';
if ($use_pigz) {
exec('tar pcf - --directory '.escapeshellarg($web_path).' . --exclude=./backup\*'.$backup_excludes.' | pigz > '.escapeshellarg($web_backup_dir.'/'.$web_backup_file), $tmp_output, $retval);
$app->system->exec_safe('tar pcf - --directory ? . --exclude=./backup\*'.$backup_excludes.' | pigz > ?', $web_path, $web_backup_dir.'/'.$web_backup_file);
$retval = $app->system->last_exec_retcode();
} else {
exec('tar pczf '.escapeshellarg($web_backup_dir.'/'.$web_backup_file).' --exclude=./backup\*'.$backup_excludes.' --directory '.escapeshellarg($web_path).' .', $tmp_output, $retval);
}
$app->system->exec_safe('tar pczf ? --exclude=./backup\*'.$backup_excludes.' --directory ? .', $web_backup_dir.'/'.$web_backup_file, $web_path);
$retval = $app->system->last_exec_retcode();
}
}
if($retval == 0 || ($backup_mode != 'userzip' && $retval == 1) || ($backup_mode == 'userzip' && $retval == 12)) { // tar can return 1, zip can return 12(due to harmless warings) and still create valid backups
if(is_file($web_backup_dir.'/'.$web_backup_file)){
......@@ -256,13 +260,16 @@ class cronjob_backup extends cronjob {
$db_id = $rec['database_id'];
$db_name = $rec['database_name'];
$db_backup_file = 'db_'.$db_name.'_'.date('Y-m-d_H-i').'.sql';
//$command = "mysqldump -h '".escapeshellcmd($clientdb_host)."' -u '".escapeshellcmd($clientdb_user)."' -p'".escapeshellcmd($clientdb_password)."' -c --add-drop-table --create-options --quick --result-file='".$db_backup_dir.'/'.$db_backup_file."' '".$db_name."'";
$command = "mysqldump -h ".escapeshellarg($clientdb_host)." -u ".escapeshellarg($clientdb_user)." -p".escapeshellarg($clientdb_password)." -c --add-drop-table --create-options --quick --max_allowed_packet=512M ".$mysqldump_routines." --result-file='".$db_backup_dir.'/'.$db_backup_file."' '".$db_name."'";
exec($command, $tmp_output, $retval);
$command = "mysqldump -h ? -u ? -p? -c --add-drop-table --create-options --quick --max_allowed_packet=512M ".$mysqldump_routines." --result-file=? ?";
$app->system->exec_safe($command, $clientdb_host, $clientdb_user, $clientdb_password, $db_backup_dir.'/'.$db_backup_file, $db_name);
$retval = $app->system->last_exec_retcode();
//* Compress the backup with gzip / pigz
if($retval == 0) exec("$zip_cmd -c '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file)."' > '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file).".gz'", $tmp_output, $retval);
if($retval == 0) {
$app->system->exec_safe("$zip_cmd -c ? > ?", $db_backup_dir.'/'.$db_backup_file, $db_backup_dir.'/'.$db_backup_file . '.gz');
$retval = $app->system->last_exec_retcode();
}
if($retval == 0){
if(is_file($db_backup_dir.'/'.$db_backup_file.'.gz')){
chmod($db_backup_dir.'/'.$db_backup_file.'.gz', 0750);
......
......@@ -122,24 +122,28 @@ 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'", $tmp_output, $retval);
exec("su -c ?", 'dsync backup -u "'.$rec["email"].'" mdbox:' . $this->tmp_backup_dir . '/backup');
if($backup_mode == 'userzip') {
$mail_backup_file.='.zip';
exec('cd '.$this->tmp_backup_dir.' && zip '.$mail_backup_dir.'/'.$mail_backup_file.' -b '.escapeshellarg($backup_tmp).' -r backup > /dev/null && rm -rf backup', $tmp_output, $retval);
}
else {
$app->system->exec_safe('cd ? && zip ? -b ? -r backup > /dev/null && rm -rf backup', $this->tmp_backup_dir, $mail_backup_dir.'/'.$mail_backup_file, $backup_tmp);
$retval = $app->system->last_exec_retcode();
} else {
$mail_backup_file.='.tar.gz';
if ($use_pigz) {
exec('tar pcf - --directory '.escapeshellarg($this->tmp_backup_dir).' backup | pigz > '.$mail_backup_dir.'/'.$mail_backup_file.' && rm -rf '.$this->tmp_backup_dir.'/backup', $tmp_output, $retval);
$app->system->exec_safe('tar pcf - --directory ? backup | pigz > ? && rm -rf ?', $this->tmp_backup_dir, $mail_backup_dir.'/'.$mail_backup_file, $this->tmp_backup_dir.'/backup');
$retval = $app->system->last_exec_retcode();
} else {
exec(escapeshellcmd('tar pczf '.$mail_backup_dir.'/'.$mail_backup_file.' --directory '.$this->tmp_backup_dir.' backup && rm -rf '.$this->tmp_backup_dir.'/backup'), $tmp_output, $retval);
$app->system->exec_safe('tar pczf ? --directory ? backup && rm -rf ?', $mail_backup_dir.'/'.$mail_backup_file, $this->tmp_backup_dir, $this->tmp_backup_dir.'/backup');
$retval = $app->system->last_exec_retcode();
}
}
if ($retval != 0) {
// Cleanup
if (file_exists($this->tmp_backup_dir.'/backup')) exec('rm -rf '.$this->tmp_backup_dir.'/backup');
if(file_exists($this->tmp_backup_dir . '/backup')) {
$app->system->exec_safe('rm -rf ?', $this->tmp_backup_dir . '/backup');
}
}
}
else {
......@@ -154,15 +158,17 @@ class cronjob_backup_mail extends cronjob {
//* create archives
if($backup_mode == 'userzip') {
$mail_backup_file.='.zip';
exec('cd '.$domain_dir.' && zip '.$mail_backup_dir.'/'.$mail_backup_file.' -b '.escapeshellarg($backup_tmp).' -r '.$source_dir.' > /dev/null', $tmp_output, $retval);
$app->system->exec_safe('cd ? && zip ? -b ? -r ? > /dev/null', $domain_dir, $mail_backup_dir.'/'.$mail_backup_file, $backup_tmp, $source_dir);
$retval = $app->system->last_exec_retcode();
} else {
/* Create a tar.gz backup */
$mail_backup_file.='.tar.gz';
if ($use_pigz) {
exec('tar pcf - --directory '.escapeshellarg($domain_dir).' '.escapeshellarg($source_dir).' | pigz > '.$mail_backup_dir.'/'.$mail_backup_file, $tmp_output, $retval);
$app->system->exec_safe('tar pcf - --directory ? ? | pigz > ?', $domain_dir, $source_dir, $mail_backup_dir.'/'.$mail_backup_file);
} else {
exec(escapeshellcmd('tar pczf '.$mail_backup_dir.'/'.$mail_backup_file.' --directory '.$domain_dir.' '.$source_dir), $tmp_output, $retval);
$app->system->exec_safe('tar pczf ? --directory ? ?', $mail_backup_dir.'/'.$mail_backup_file, $domain_dir, $source_dir);
}
$retval = $app->system->last_exec_retcode();
}
}
......@@ -181,7 +187,9 @@ class cronjob_backup_mail extends cronjob {
if(is_file($mail_backup_dir.'/'.$mail_backup_file)) unlink($mail_backup_dir.'/'.$mail_backup_file);
// And remove backup-mdbox
if ($rec['maildir_format'] == 'mdbox') {
if(file_exists($rec['maildir'].'/backup')) exec("su -c 'rm -rf ".$rec['maildir']."/backup'");
if(file_exists($rec['maildir'] . '/backup')) {
$app->system->exec_safe('rm -rf ?', $rec['maildir'] . '/backup');
}
}
$app->log($mail_backup_file.' NOK:'.implode('',$tmp_output), LOGLEVEL_WARN);
}
......
......@@ -58,7 +58,7 @@ class cronjob_purge_mailboxes extends cronjob {
if(is_array($records)) {
foreach($records as $rec){
exec("su -c 'doveadm purge -u \"".$rec["email"]."\"'");
$app->system->exec_safe("su -c ?", 'doveadm purge -u "' . $rec["email"] . '"');
}
}
......
......@@ -66,7 +66,7 @@ class cronjob_letsencrypt extends cronjob {
} else {
$marker_file = '/usr/local/ispconfig/server/le.restart';
$cmd = "echo '1' > " . $marker_file;
exec($letsencrypt . ' -n renew --post-hook ' . escapeshellarg($cmd));
$app->system->exec_safe($letsencrypt . ' -n renew --post-hook ?', $cmd);
if(file_exists($marker_file) && trim(file_get_contents($marker_file)) == '1') {
unlink($marker_file);
$app->services->restartServiceDelayed('httpd', 'force-reload');
......
......@@ -425,9 +425,9 @@ class functions {
if(file_exists($id_rsa_file)) unset($id_rsa_file);
if(file_exists($id_rsa_pub_file)) unset($id_rsa_pub_file);
if(!file_exists($id_rsa_file) && !file_exists($id_rsa_pub_file)) {
exec('ssh-keygen -t rsa -C '.$username.'-rsa-key-'.time().' -f '.$id_rsa_file.' -N ""');
$app->system->exec_safe('ssh-keygen -t rsa -C ? -f ? -N ""', $username.'-rsa-key-'.time(), $id_rsa_file);
$app->db->query("UPDATE client SET created_at = UNIX_TIMESTAMP(), id_rsa = ?, ssh_rsa = ? WHERE client_id = ?", $app->system->file_get_contents($id_rsa_file), $app->system->file_get_contents($id_rsa_pub_file), $client_id);
exec('rm -f '.$id_rsa_file.' '.$id_rsa_pub_file);
$app->system->exec_safe('rm -f ? ?', $id_rsa_file, $id_rsa_pub_file);
} else {
$app->log("Failed to create SSH keypair for ".$username, LOGLEVEL_WARN);
}
......
......@@ -389,7 +389,7 @@ class letsencrypt {
}
if(@is_link($key_file)) $app->system->unlink($key_file);
if(@file_exists($key_tmp_file)) exec("ln -s ".escapeshellcmd($key_tmp_file)." ".escapeshellcmd($key_file));
if(@file_exists($key_tmp_file)) $app->system->exec_safe("ln -s ? ?", $key_tmp_file, $key_file);
if(is_file($crt_file)) {
$app->system->copy($crt_file, $crt_file.'.old.'.$date);
......@@ -398,7 +398,7 @@ class letsencrypt {
}
if(@is_link($crt_file)) $app->system->unlink($crt_file);
if(@file_exists($crt_tmp_file))exec("ln -s ".escapeshellcmd($crt_tmp_file)." ".escapeshellcmd($crt_file));
if(@file_exists($crt_tmp_file))$app->system->exec_safe("ln -s ? ?", $crt_tmp_file, $crt_file);
if(is_file($bundle_file)) {
$app->system->copy($bundle_file, $bundle_file.'.old.'.$date);
......@@ -407,7 +407,7 @@ class letsencrypt {
}
if(@is_link($bundle_file)) $app->system->unlink($bundle_file);
if(@file_exists($bundle_tmp_file)) exec("ln -s ".escapeshellcmd($bundle_tmp_file)." ".escapeshellcmd($bundle_file));
if(@file_exists($bundle_tmp_file)) $app->system->exec_safe("ln -s ? ?", $bundle_tmp_file, $bundle_file);
return true;
} else {
......
......@@ -593,13 +593,12 @@ class monitor_tools {
// Getting the logfile content
if ($logfile != '') {
$logfile = escapeshellcmd($logfile);
if (stristr($logfile, ';') or substr($logfile, 0, 9) != '/var/log/' or stristr($logfile, '..')) {
$log = 'Logfile path error.';
} else {
$log = '';
if (is_readable($logfile)) {
$fd = popen('tail -n 100 ' . $logfile, 'r');
$fd = popen('tail -n 100 ' . escapeshellarg($logfile), 'r');
if ($fd) {
while (!feof($fd)) {
$log .= fgets($fd, 4096);
......
......@@ -37,6 +37,9 @@ class system{
var $min_uid = 500;
var $min_gid = 500;
private $_last_exec_out = null;
private $_last_exec_retcode = null;
/**
* Construct for this class
*
......@@ -716,8 +719,10 @@ class system{
function posix_getgrnam($group) {
if(!function_exists('posix_getgrnam')){
$group_datei = $this->server_conf['group_datei'];
$cmd = 'grep -m 1 "^'.$group.':" '.$group_datei;
exec($cmd, $output, $return_var);
$cmd = 'grep -m 1 ? ?';
$this->exec_safe($cmd, '^'.$group.':', $group_datei);
$output = $this->last_exec_out();
$return_var = $this->last_exec_retcode();
if($return_var != 0 || !$output[0]) return false;
list($f1, $f2, $f3, $f4) = explode(':', $output[0]);
$f2 = trim($f2);
......@@ -1073,10 +1078,10 @@ class system{
} else { // Linux
if(substr($dist, 0, 4) == 'suse'){
if($action == 'on'){
exec("chkconfig --add $service &> /dev/null");
$this->exec_safe("chkconfig --add ? &> /dev/null", $service);
}
if($action == 'off'){
exec("chkconfig --del $service &> /dev/null");
$this->exec_safe("chkconfig --del ? &> /dev/null", $service);
}
} else {
$runlevels = explode(',', $rl);
......@@ -1375,7 +1380,7 @@ class system{
if(!empty($ifconfig['IP'])){
foreach($ifconfig['IP'] as $key => $val){
if(!strstr($val, 'lo') && !strstr($val, 'lp') && strstr($val, $main_interface)){
exec('ifconfig '.$val.' down &> /dev/null');
$this->exec_safe('ifconfig ? down &> /dev/null', $val);
unset($ifconfig['INTERFACE'][$val]);
}
}
......@@ -1391,7 +1396,7 @@ class system{
$i = -1;
}