diff --git a/install/tpl/server.ini.master b/install/tpl/server.ini.master
index 49b9e3ce2677aa7a927f2a07cd5df6138f95fd00..eaeff0210af6885e84b82276a1d7ba3c114cd48b 100644
--- a/install/tpl/server.ini.master
+++ b/install/tpl/server.ini.master
@@ -76,6 +76,7 @@ set_folder_permissions_on_update=y
add_web_users_to_sshusers_group=y
connect_userid_to_webid=n
connect_userid_to_webid_start=10000
+web_folder_protection=n
[dns]
bind_user=root
diff --git a/interface/web/admin/form/server_config.tform.php b/interface/web/admin/form/server_config.tform.php
index 09334c74949d286e7f9ad3bf8c6db9fa46da4a6d..e08d1cc08ff38ed5be01f4db2f11f3f7c77942e4 100644
--- a/interface/web/admin/form/server_config.tform.php
+++ b/interface/web/admin/form/server_config.tform.php
@@ -462,6 +462,12 @@ $form["tabs"]['web'] = array(
'default' => 'y',
'value' => array(0 => 'n', 1 => 'y')
),
+ 'web_folder_protection' => array(
+ 'datatype' => 'VARCHAR',
+ 'formtype' => 'CHECKBOX',
+ 'default' => 'y',
+ 'value' => array(0 => 'n', 1 => 'y')
+ ),
'add_web_users_to_sshusers_group' => array(
'datatype' => 'VARCHAR',
'formtype' => 'CHECKBOX',
diff --git a/interface/web/admin/lib/lang/en_server_config.lng b/interface/web/admin/lib/lang/en_server_config.lng
index b14f34dd96ee824c708e4ef812fb0a2d2c842bb1..c32657b21cb758f022d9f3166beac77a6b36ce7d 100644
--- a/interface/web/admin/lib/lang/en_server_config.lng
+++ b/interface/web/admin/lib/lang/en_server_config.lng
@@ -165,4 +165,5 @@ $wb["awstats_settings_txt"] = 'AWStats Settings';
$wb["firewall_txt"] = 'Firewall';
$wb["mailbox_quota_stats_txt"] = 'Mailbox quota statistics';
$wb["enable_ip_wildcard_txt"] = 'Enable IP wildcard (*)';
+$wb["web_folder_protection_txt"] = 'Web folder protection';
?>
\ No newline at end of file
diff --git a/interface/web/admin/templates/server_config_web_edit.htm b/interface/web/admin/templates/server_config_web_edit.htm
index 40750038ba6c7f28588b3b0f6f5187c06062ba5d..349ddcdcf9607b5975dbb84b23400fafb95a5e2e 100644
--- a/interface/web/admin/templates/server_config_web_edit.htm
+++ b/interface/web/admin/templates/server_config_web_edit.htm
@@ -116,6 +116,12 @@
{tmpl_var name='set_folder_permissions_on_update'}
+
{tmpl_var name='add_web_users_to_sshusers_group_txt'}
diff --git a/server/lib/classes/system.inc.php b/server/lib/classes/system.inc.php
index c43a0ccd1d94af5e77421f83a6ffcc7018a83d7c..323ffe5046572c5f153854c233cd635864f194a3 100644
--- a/server/lib/classes/system.inc.php
+++ b/server/lib/classes/system.inc.php
@@ -1281,6 +1281,22 @@ class system{
return false;
}
}
+
+ function web_folder_protection($document_root,$protect) {
+ global $app,$conf;
+
+ //* load the server configuration options
+ $app->uses('getconf');
+ $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
+
+ if($protect == true && $web_config['web_folder_protection'] == 'y') {
+ //* Add protection
+ if($document_root != '' && $document_root != '/' && strlen($document_root) > 6 && !stristr($document_root,'..')) exec('chattr +i '.escapeshellcmd($document_root));
+ } else {
+ //* Remove protection
+ if($document_root != '' && $document_root != '/' && strlen($document_root) > 6 && !stristr($document_root,'..')) exec('chattr -i '.escapeshellcmd($document_root));
+ }
+ }
}
?>
diff --git a/server/plugins-available/apache2_plugin.inc.php b/server/plugins-available/apache2_plugin.inc.php
index a6157ada8e9e094d79c4da50cb1bc03f1ee844eb..c441a6a7c2c6d64a597fe385d3bb807f446794af 100644
--- a/server/plugins-available/apache2_plugin.inc.php
+++ b/server/plugins-available/apache2_plugin.inc.php
@@ -366,6 +366,9 @@ class apache2_plugin {
}
}
}
+
+ //* Remove protection of old folders
+ $app->system->web_folder_protection($data['old']['document_root'],false);
//* Move the site data
$tmp_docroot = explode('/',$data['new']['document_root']);
@@ -414,7 +417,7 @@ class apache2_plugin {
if(!is_dir($data['new']['document_root'].'/ssl')) exec('mkdir -p '.$data['new']['document_root'].'/ssl');
if(!is_dir($data['new']['document_root'].'/cgi-bin')) exec('mkdir -p '.$data['new']['document_root'].'/cgi-bin');
if(!is_dir($data['new']['document_root'].'/tmp')) exec('mkdir -p '.$data['new']['document_root'].'/tmp');
-
+
// Remove the symlink for the site, if site is renamed
if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) {
if(is_dir('/var/log/ispconfig/httpd/'.$data['old']['domain'])) exec('rm -rf /var/log/ispconfig/httpd/'.$data['old']['domain']);
@@ -593,10 +596,11 @@ class apache2_plugin {
}
}
-
-
//* If the security level is set to high
if(($this->action == 'insert' && $data['new']['type'] == 'vhost') or ($web_config['set_folder_permissions_on_update'] == 'y' && $data['new']['type'] == 'vhost')) {
+
+ $app->system->web_folder_protection($data['new']['document_root'],false);
+
if($web_config['security_level'] == 20) {
$this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root']));
@@ -673,6 +677,9 @@ class apache2_plugin {
$this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/web'));
}
}
+
+ //* Protect web folders
+ $app->system->web_folder_protection($data['new']['document_root'],true);
// Change the ownership of the error log to the owner of the website
if(!@is_file($data['new']['document_root'].'/log/error.log')) exec('touch '.escapeshellcmd($data['new']['document_root']).'/log/error.log');
@@ -1217,7 +1224,9 @@ class apache2_plugin {
if(!is_file($data['new']['document_root'].'/.htpasswd_stats') || $data['new']['stats_password'] != $data['old']['stats_password']) {
if(trim($data['new']['stats_password']) != '') {
$htp_file = 'admin:'.trim($data['new']['stats_password']);
+ $app->system->web_folder_protection($data['new']['document_root'],false);
file_put_contents($data['new']['document_root'].'/.htpasswd_stats',$htp_file);
+ $app->system->web_folder_protection($data['new']['document_root'],true);
chmod($data['new']['document_root'].'/.htpasswd_stats',0755);
unset($htp_file);
}
@@ -1280,6 +1289,8 @@ class apache2_plugin {
// load the server configuration options
$app->uses('getconf');
$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
+
+ $app->system->web_folder_protection($data['new']['document_root'],false);
//* Check if this is a chrooted setup
if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) {
diff --git a/server/plugins-available/cron_jailkit_plugin.inc.php b/server/plugins-available/cron_jailkit_plugin.inc.php
index 2e5f06eea5e51c60004eb45200d9beb1589f4b49..1e4713846cbe5a18a51696ad37a4e48a4c80b8cc 100644
--- a/server/plugins-available/cron_jailkit_plugin.inc.php
+++ b/server/plugins-available/cron_jailkit_plugin.inc.php
@@ -116,6 +116,8 @@ class cron_jailkit_plugin {
$this->app = $app;
$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
+ $app->system->web_folder_protection($parent_domain['document_root'],false);
+
$this->_update_website_security_level();
$this->_setup_jailkit_chroot();
@@ -126,6 +128,8 @@ class cron_jailkit_plugin {
exec($command);
$this->_update_website_security_level();
+
+ $app->system->web_folder_protection($parent_domain['document_root'],true);
}
$app->log("Jailkit Plugin (Cron) -> insert username:".$parent_domain['system_user'],LOGLEVEL_DEBUG);
@@ -182,12 +186,14 @@ class cron_jailkit_plugin {
$this->app = $app;
$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
+ $app->system->web_folder_protection($parent_domain['document_root'],false);
$this->_update_website_security_level();
$this->_setup_jailkit_chroot();
$this->_add_jailkit_user();
$this->_update_website_security_level();
+ $app->system->web_folder_protection($parent_domain['document_root'],true);
}
$app->log("Jailkit Plugin (Cron) -> update username:".$parent_domain['system_user'],LOGLEVEL_DEBUG);
diff --git a/server/plugins-available/shelluser_base_plugin.inc.php b/server/plugins-available/shelluser_base_plugin.inc.php
index 5c4186338195b0889c42e3fb6d72190f24e6e54d..a56ec6d72d3183174a308be3a6642713a219f05c 100755
--- a/server/plugins-available/shelluser_base_plugin.inc.php
+++ b/server/plugins-available/shelluser_base_plugin.inc.php
@@ -80,6 +80,10 @@ class shelluser_base_plugin {
}
if($app->system->is_user($data['new']['puser'])) {
+
+ //* Remove webfolder protection
+ $app->system->web_folder_protection($web['document_root'],false);
+
// Get the UID of the parent user
$uid = intval($app->system->getuid($data['new']['puser']));
if($uid > $this->min_uid) {
@@ -114,6 +118,9 @@ class shelluser_base_plugin {
exec($command);
$app->log("Disabling shelluser temporarily: ".$command,LOGLEVEL_DEBUG);
}
+
+ //* Add webfolder protection again
+ $app->system->web_folder_protection($web['document_root'],true);
} else {
$app->log("UID = $uid for shelluser:".$data['new']['username']." not allowed.",LOGLEVEL_ERROR);
diff --git a/server/plugins-available/shelluser_jailkit_plugin.inc.php b/server/plugins-available/shelluser_jailkit_plugin.inc.php
index 671ae62c16df0cb9e165a47744d89d63ae9fcae8..6ffe8e87a29ec0dad04a5f12166f63b110fd93b3 100755
--- a/server/plugins-available/shelluser_jailkit_plugin.inc.php
+++ b/server/plugins-available/shelluser_jailkit_plugin.inc.php
@@ -71,6 +71,7 @@ class shelluser_jailkit_plugin {
global $app, $conf;
$app->uses('system');
+ $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$this->data['new']['parent_domain_id']);
if($app->system->is_user($data['new']['username'])) {
@@ -79,6 +80,8 @@ class shelluser_jailkit_plugin {
*/
if ($data['new']['chroot'] == "jailkit")
{
+ $app->system->web_folder_protection($web['document_root'],false);
+
// load the server configuration options
$app->uses("getconf");
$this->data = $data;
@@ -98,6 +101,7 @@ class shelluser_jailkit_plugin {
exec($command);
$this->_update_website_security_level();
+ $app->system->web_folder_protection($web['document_root'],true);
}
$app->log("Jailkit Plugin -> insert username:".$data['new']['username'],LOGLEVEL_DEBUG);
@@ -113,6 +117,7 @@ class shelluser_jailkit_plugin {
global $app, $conf;
$app->uses('system');
+ $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$this->data['new']['parent_domain_id']);
if($app->system->is_user($data['new']['username'])) {
@@ -121,6 +126,8 @@ class shelluser_jailkit_plugin {
*/
if ($data['new']['chroot'] == "jailkit")
{
+ $app->system->web_folder_protection($web['document_root'],false);
+
// load the server configuration options
$app->uses("getconf");
$this->data = $data;
@@ -136,6 +143,8 @@ class shelluser_jailkit_plugin {
$this->_setup_ssh_rsa();
$this->_update_website_security_level();
+
+ $app->system->web_folder_protection($web['document_root'],true);
}
$app->log("Jailkit Plugin -> update username:".$data['new']['username'],LOGLEVEL_DEBUG);
@@ -155,6 +164,8 @@ class shelluser_jailkit_plugin {
$app->uses('system');
+ $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$this->data['old']['parent_domain_id']);
+
if ($data['old']['chroot'] == "jailkit")
{
$app->uses("getconf");
@@ -165,6 +176,8 @@ class shelluser_jailkit_plugin {
//commented out proved to be dangerous on config errors
//exec('rm -rf '.$data['old']['dir'].$jailkit_chroot_userhome);
+ $app->system->web_folder_protection($web['document_root'],false);
+
if(@is_dir($data['old']['dir'].$jailkit_chroot_userhome)) {
$command = 'userdel -f';
$command .= ' '.escapeshellcmd($data['old']['username']);
@@ -172,6 +185,8 @@ class shelluser_jailkit_plugin {
$app->log("Jailkit Plugin -> delete chroot home:".$data['old']['dir'].$jailkit_chroot_userhome,LOGLEVEL_DEBUG);
}
+ $app->system->web_folder_protection($web['document_root'],true);
+
}
$app->log("Jailkit Plugin -> delete username:".$data['old']['username'],LOGLEVEL_DEBUG);