diff --git a/server/lib/classes/cron.d/600-jailkit_maintenance.inc.php b/server/lib/classes/cron.d/600-jailkit_maintenance.inc.php index 645004ff5253047e42c3e3a5748049a8da3e20da..06a278fa424381d82dd89027a270f3461ef98587 100644 --- a/server/lib/classes/cron.d/600-jailkit_maintenance.inc.php +++ b/server/lib/classes/cron.d/600-jailkit_maintenance.inc.php @@ -61,15 +61,15 @@ class cronjob_jailkit_maintenance extends cronjob { print "Migration mode active, not running Jailkit updates.\n"; } - $update_options = array( 'allow_hardlink', ); - $jailkit_config = $app->getconf->get_server_config($conf['server_id'], 'jailkit'); if (isset($this->jailkit_config) && isset($this->jailkit_config['jailkit_hardlinks'])) { if ($this->jailkit_config['jailkit_hardlinks'] == 'yes') { $update_options = array( 'hardlink', ); } elseif ($this->jailkit_config['jailkit_hardlinks'] == 'no') { - unset($update_options['allow_hardlink']); + $update_optiosn = array(); } + } else { + $update_options = array( 'allow_hardlink', ); } // limit the number of jails we update at one time according to time of day diff --git a/server/lib/classes/functions.inc.php b/server/lib/classes/functions.inc.php index 1d9dd67569448a2cee200ec71281685fd568517a..5da1f3d713029b069b3a89c954dc001a541e1271 100644 --- a/server/lib/classes/functions.inc.php +++ b/server/lib/classes/functions.inc.php @@ -118,6 +118,26 @@ class functions { return $out; } + public function array_unset_by_value($array, $value) { + if (!is_array($array)) { + return $array; + } + if (is_array($value)) { + foreach ($array as $key => $val){ + if (in_array($val, $value)) { + unset($array[$key]); + } + } + } else { + foreach ($array as $key => $val){ + if ($val == $value) { + unset($array[$key]); + } + } + } + return $array; + } + public function currency_format($number, $view = '') { global $app; if($view != '') $number_format_decimals = (int)$app->lng('number_format_decimals_'.$view); diff --git a/server/lib/classes/system.inc.php b/server/lib/classes/system.inc.php index 25d8b8fb82fe632991a05f05cc4f08620eff4d39..c0dd80e3b4f9fa339a0960f656b8d9f4ec472247 100644 --- a/server/lib/classes/system.inc.php +++ b/server/lib/classes/system.inc.php @@ -949,15 +949,17 @@ class system{ } $path = rtrim($path, '/'); - if (is_dir($path)) { + if (is_dir($path) && !is_link($path)) { $objects = array_diff(scandir($path), array('.', '..')); foreach ($objects as $object) { if ($recursive) { - if (is_dir("$path/$object")) { + if (is_dir("$path/$object") && !is_link("$path/$object")) { $this->rmdir("$path/$object", $recursive); } else { unlink ("$path/$object"); } + } else { + $app->log("rmdir: invoked non-recursive, not removing $path (expect rmdir failure)", LOGLEVEL_DEBUG); } } return rmdir($path); @@ -1011,16 +1013,18 @@ class system{ if ($path != '/') { $path = rtrim($path, '/'); } +global $app; +#$app->log("remove_broken_symlinks: checking path: $path", LOGLEVEL_DEBUG); if (is_dir($path)) { +#$app->log("remove_broken_symlinks: $path is dir, running scandir", LOGLEVEL_DEBUG); $objects = array_diff(scandir($path), array('.', '..')); foreach ($objects as $object) { - if ($recursive) { - if (is_dir("$path/$object")) { - $this->remove_broken_symlinks("$path/$object", $recursive); - } elseif (is_link("$path/$object") && !file_exists("$path/$object")) { +#$app->log("remove_broken_symlinks: scandir found $object", LOGLEVEL_DEBUG); + if (is_dir("$path/$object") && $recursive) { + $this->remove_broken_symlinks("$path/$object", $recursive); + } elseif (is_link("$path/$object") && !file_exists("$path/$object")) { $app->log("removing broken symlink $path/$object", LOGLEVEL_DEBUG); - unlink ("$path/$object"); - } + unlink ("$path/$object"); } } } elseif (is_link("$path") && !file_exists("$path")) { @@ -2299,10 +2303,12 @@ $app->log("removing broken symlink $path", LOGLEVEL_DEBUG); $program_args = ''; foreach ($options as $opt) { switch ($opt) { - case '-k|hardlink': + case '-k': + case 'hardlink': $program_args .= ' -k'; break; - case '-f|force': + case '-f': + case 'force': $program_args .= ' -f'; break; } @@ -2365,10 +2371,12 @@ $app->log("removing broken symlink $path", LOGLEVEL_DEBUG); $program_args = ''; foreach ($options as $opt) { switch ($opt) { - case '-k|hardlink': + case '-k': + case 'hardlink': $program_args .= ' -k'; break; - case '-f|force': + case '-f': + case 'force': $program_args .= ' -f'; break; } @@ -2400,6 +2408,7 @@ $app->log("removing broken symlink $path", LOGLEVEL_DEBUG); public function update_jailkit_chroot($home_dir, $sections = array(), $programs = array(), $options = array()) { global $app; +$app->log("update_jailkit_chroot called for $home_dir with options ".print_r($options, true), LOGLEVEL_DEBUG); $app->uses('ini_parser'); // Disallow operating on root directory @@ -2416,10 +2425,12 @@ $app->log("removing broken symlink $path", LOGLEVEL_DEBUG); $opts = array(); foreach ($options as $opt) { switch ($opt) { - case '-k|hardlink': + case '-k': + case 'hardlink': $opts[] = 'hardlink'; break; - case '-f|force': + case '-f': + case 'force': $opts[] = 'force'; break; } @@ -2460,13 +2471,14 @@ $app->log("removing broken symlink $path", LOGLEVEL_DEBUG); continue; } - $this->remove_broken_symlinks($dir, true); + $this->remove_broken_symlinks($jail_dir, true); // save list of hardlinked files - if (!in_array('hardlink', $opts) && !in_array('allow_hardlink', $options)) { + if (!(in_array('hardlink', $opts) || in_array('allow_hardlink', $options))) { +$app->log("update_jailkit_chroot: searching for hardlinks in $jail_dir", LOGLEVEL_DEBUG); $find_multiple_links = function ( $path ) use ( &$find_multiple_links ) { $found = array(); - if (is_dir($path)) { + if (is_dir($path) && !is_link($path)) { $objects = array_diff(scandir($path), array('.', '..')); foreach ($objects as $object) { $ret = $find_multiple_links( "$path/$object" ); @@ -2474,8 +2486,8 @@ $app->log("removing broken symlink $path", LOGLEVEL_DEBUG); $found = array_merge($found, $ret); } } - } else { - $stat = stat($path); + } elseif (is_file($path)) { + $stat = lstat($path); if ($stat['nlink'] > 1) { $found[$path] = $path; } @@ -2483,34 +2495,42 @@ $app->log("removing broken symlink $path", LOGLEVEL_DEBUG); return $found; }; - $ret = $find_multiple_links( $jail_dir ); + $ret = $find_multiple_links($jail_dir); if (count($ret) > 0) { $multiple_links = array_merge($multiple_links, $ret); } - } - // remove broken symlinks a second time after hardlink cleanup - $this->remove_broken_symlinks($dir, true); + // remove broken symlinks a second time after hardlink cleanup + $this->remove_broken_symlinks($jail_dir, true); + } +else { $app->log("update_jailkit_chroot: NOT searching for hardlinks in $jail_dir, options: ".print_r($options, true), LOGLEVEL_DEBUG); } } + foreach ($multiple_links as $file) { + $app->log("update_jailkit_chroot: removing hardlinked file: $file", LOGLEVEL_DEBUG); + unlink($file); + } - $cmd = 'jk_update --jail='.escapeshellarg($home_dir) . $skips; - exec($cmd, $out, $ret); - foreach ($out as $line) { + $cmd = 'jk_update --jail=?' . $skips; + $this->exec_safe($cmd, $home_dir); +$app->log('jk_update returned: '.print_r($this->_last_exec_out, true), LOGLEVEL_DEBUG); + foreach ($this->_last_exec_out as $line) { if (substr( $line, 0, 4 ) === "skip") { continue; } - if (preg_match('@^(? [^ ]+){6}(.+)'.preg_quote($home_dir, '@').'$@', $line, $matches)) { + if (preg_match('@^(?: [^ ]+){6}(.+)'.preg_quote($home_dir, '@').'$@', $line, $matches)) { # remove deprecated files that jk_update failed to remove if (is_file($matches[1])) { -$app->log("removing deprecated file which jk_update failed to remove: ".$matches[1], LOGLEVEL_DEBUG); +$app->log("update_jailkit_chroot: removing deprecated file which jk_update failed to remove: ".$matches[1], LOGLEVEL_DEBUG); unlink($matches[1]); } elseif (is_dir($matches[1])) { -$app->log("removing deprecated directory which jk_update failed to remove: ".$matches[1], LOGLEVEL_DEBUG); +$app->log("update_jailkit_chroot: removing deprecated directory which jk_update failed to remove: ".$matches[1], LOGLEVEL_DEBUG); $this->rmdir($matches[1], true); } # unhandled error - $app->log("jk_update error for jail $home_dir: ".$matches[1], LOGLEVEL_DEBUG); + //$app->log("jk_update error for jail $home_dir: ".$matches[1], LOGLEVEL_DEBUG); + // at least for 3.2 beta, lets gather some of this info: + $app->log("jk_update error for jail $home_dir, feel free to pass to ispconfig developers: ".print_r( $matches, true), LOGLEVEL_DEBUG); } } @@ -2528,20 +2548,20 @@ $app->log("removing deprecated directory which jk_update failed to remove: ".$m } // search for any hardlinked files which are now missing - if (!in_array('hardlink', $opts) && !in_array('allow_hardlink', $options)) { + if (!(in_array('hardlink', $opts) || in_array('allow_hardlink', $options))) { foreach ($multiple_links as $file) { if (!is_file($file)) { // strip $home_dir from $file - if (substr($file, 0, strlen(rtrim($home_dir, '/'))) == strlen(rtrim($home_dir, '/'))) { + if (substr($file, 0, strlen(rtrim($home_dir, '/'))) == rtrim($home_dir, '/')) { $file = substr($file, strlen(rtrim($home_dir, '/'))); } if (is_file($file)) { // file exists in root -$app->log("file with multiple links still missing, running jk_cp to restore: $file", LOGLEVEL_DEBUG); + $app->log("update_jailkit_chroot: previously hardlinked file still missing, running jk_cp to restore: $file", LOGLEVEL_DEBUG); $cmd = 'jk_cp -j ? ' . escapeshellarg($file); $this->exec_safe($cmd, $home_dir); } else { // not necessarily an error - $app->log("previously hardlinked file was not found to restore: $file", LOGLEVEL_DEBUG); + $app->log("update_jailkit_chroot: previously hardlinked file was not restored and is no longer present in system: $file", LOGLEVEL_DEBUG); } } } @@ -2597,13 +2617,17 @@ $app->log("file with multiple links still missing, running jk_cp to restore: $fi 'sys', 'usr', 'var', + 'run', # not used by jailkit, but added for cleanup ); $removed = ''; foreach ($jailkit_directories as $dir) { $jail_dir = rtrim($home_dir, '/') . '/'.$dir; - if (is_dir($jail_dir)) { + if (is_link($jail_dir)) { + unlink($jail_dir); + $removed .= ' /'.$dir; + } elseif (is_dir($jail_dir)) { $this->rmdir($jail_dir, true); $removed .= ' /'.$dir; } @@ -2612,10 +2636,11 @@ $app->log("file with multiple links still missing, running jk_cp to restore: $fi $app->log("delete_jailkit_chroot: removed from jail $home_dir: $removed", LOGLEVEL_DEBUG); - // handle etc and home special + // remove /home if empty $home = rtrim($home_dir, '/') . '/home'; @rmdir($home); # ok to fail if non-empty + // otherwise archive under /private $private = rtrim($home_dir, '/') . '/private'; if (is_dir($home) && is_dir($private)) { $archive = $private.'/home-'.date('c'); diff --git a/server/plugins-available/cron_jailkit_plugin.inc.php b/server/plugins-available/cron_jailkit_plugin.inc.php index 2836ae0bdecbf3566fb71438265bd5437f3f2930..da17bdf38e281ee76a7ae0fac69f5b01f5f2f308 100644 --- a/server/plugins-available/cron_jailkit_plugin.inc.php +++ b/server/plugins-available/cron_jailkit_plugin.inc.php @@ -232,10 +232,20 @@ class cron_jailkit_plugin { { global $app; + if (isset($this->jailkit_config) && isset($this->jailkit_config['jailkit_hardlinks'])) { + if ($this->jailkit_config['jailkit_hardlinks'] == 'yes') { + $options = array( 'hardlink', ); + } elseif ($this->jailkit_config['jailkit_hardlinks'] == 'no') { + $options = array(); + } + } else { + $options = array( 'allow_hardlink', ); + } + //check if the chroot environment is created yet if not create it with a list of program sections from the config if (!is_dir($this->parent_domain['document_root'].'/etc/jailkit')) { - $app->system->create_jailkit_chroot($this->parent_domain['document_root'], $this->jailkit_config['jailkit_chroot_app_sections']); + $app->system->create_jailkit_chroot($this->parent_domain['document_root'], $this->jailkit_config['jailkit_chroot_app_sections'], $options); $this->app->log("Added jailkit chroot", LOGLEVEL_DEBUG); @@ -267,34 +277,26 @@ class cron_jailkit_plugin { $app->system->file_put_contents($motd, $tpl->grab()); } else { - $options = array( 'allow_hardlink', ); - if (isset($this->jailkit_config) && isset($this->jailkit_config['jailkit_hardlinks'])) { - if ($this->jailkit_config['jailkit_hardlinks'] == 'yes') { - $options = array( 'hardlink', ); - } elseif ($this->jailkit_config['jailkit_hardlinks'] == 'no') { - unset($options['allow_hardlink']); - } - } // force update existing jails $options[] = 'force'; $sections = $this->jailkit_config['jailkit_chroot_app_sections']; $programs = $this->jailkit_config['jailkit_chroot_app_programs']; - $app->system->update_jailkit_chroot($this->data['new']['dir'], $sections, $programs, $options); + $app->system->update_jailkit_chroot($this->parent_domain['document_root'], $sections, $programs, $options); } - $this->_add_jailkit_programs(); - // might need to update master db here? checking.... + $this->_add_jailkit_programs($options); + + // this gets last_jailkit_update out of sync with master db, but that is ok, + // as it is only used as a timestamp to moderate the frequency of updating on the slaves $app->db->query("UPDATE `web_domain` SET `last_jailkit_update` = NOW() WHERE `document_root` = ?", $this->data['new']['dir']); } - function _add_jailkit_programs() + function _add_jailkit_programs($opts=array()) { global $app; - $opts = array('force'); - //copy over further programs and its libraries $app->system->create_jailkit_programs($this->parent_domain['document_root'], $this->jailkit_config['jailkit_chroot_app_programs'], $opts); $this->app->log("Added app programs to jailkit chroot", LOGLEVEL_DEBUG); diff --git a/server/plugins-available/shelluser_jailkit_plugin.inc.php b/server/plugins-available/shelluser_jailkit_plugin.inc.php index 7d581c5f08f15f8db2efba999537445f9f6537fb..5a9f97f90423b7e2c08a39ce4f5494708820157d 100755 --- a/server/plugins-available/shelluser_jailkit_plugin.inc.php +++ b/server/plugins-available/shelluser_jailkit_plugin.inc.php @@ -290,13 +290,23 @@ class shelluser_jailkit_plugin { { global $app; + if (isset($this->jailkit_config) && isset($this->jailkit_config['jailkit_hardlinks'])) { + if ($this->jailkit_config['jailkit_hardlinks'] == 'yes') { + $options = array( 'hardlink', ); + } elseif ($this->jailkit_config['jailkit_hardlinks'] == 'no') { + $options = array(); + } + } else { + $options = array( 'allow_hardlink', ); + } + //check if the chroot environment is created yet if not create it with a list of program sections from the config if (!is_dir($this->data['new']['dir'].'/etc/jailkit')) { - $app->system->create_jailkit_chroot($this->data['new']['dir'], $this->jailkit_config['jailkit_chroot_app_sections']); + $app->system->create_jailkit_chroot($this->data['new']['dir'], $this->jailkit_config['jailkit_chroot_app_sections'], $options); $this->app->log("Added jailkit chroot", LOGLEVEL_DEBUG); - $this->_add_jailkit_programs(); + $this->_add_jailkit_programs($options); //add bash.bashrc script //we need to collect the domain name to be used as the HOSTNAME in the bashrc script @@ -330,14 +340,6 @@ class shelluser_jailkit_plugin { $app->system->file_put_contents($motd, $tpl->grab()); } else { - $options = array( 'allow_hardlink', ); - if (isset($this->jailkit_config) && isset($this->jailkit_config['jailkit_hardlinks'])) { - if ($this->jailkit_config['jailkit_hardlinks'] == 'yes') { - $options = array( 'hardlink', ); - } elseif ($this->jailkit_config['jailkit_hardlinks'] == 'no') { - unset($options['allow_hardlink']); - } - } // force update existing jails $options[] = 'force'; @@ -347,11 +349,12 @@ class shelluser_jailkit_plugin { $app->system->update_jailkit_chroot($this->data['new']['dir'], $sections, $programs, $options); } - // might need to update master db here? checking.... + // this gets last_jailkit_update out of sync with master db, but that is ok, + // as it is only used as a timestamp to moderate the frequency of updating on the slaves $app->db->query("UPDATE `web_domain` SET `last_jailkit_update` = NOW() WHERE `document_root` = ?", $this->data['new']['dir']); } - function _add_jailkit_programs() + function _add_jailkit_programs($opts=array()) { global $app; $jailkit_chroot_app_programs = preg_split("/[\s,]+/", $this->jailkit_config['jailkit_chroot_app_programs']); @@ -360,7 +363,7 @@ class shelluser_jailkit_plugin { $jailkit_chroot_app_program = trim($jailkit_chroot_app_program); if(is_file($jailkit_chroot_app_program) || is_dir($jailkit_chroot_app_program)){ //copy over further programs and its libraries - $app->system->create_jailkit_programs($this->data['new']['dir'], $jailkit_chroot_app_program); + $app->system->create_jailkit_programs($this->data['new']['dir'], $jailkit_chroot_app_program, $opts); $this->app->log("Added programs to jailkit chroot", LOGLEVEL_DEBUG); } }