From 4b9329a0f204c190f9cae6c072c9827d05d269e6 Mon Sep 17 00:00:00 2001
From: tbrehm <t.brehm@ispconfig.org>
Date: Fri, 8 Jun 2012 12:06:41 +0000
Subject: [PATCH] Implemented: FS#2112 - Set u / i attributes on system web
 folders This option can be enabled under System > Server config and is named
 "Web folder protection".

---
 install/tpl/server.ini.master                   |  1 +
 .../web/admin/form/server_config.tform.php      |  6 ++++++
 .../web/admin/lib/lang/en_server_config.lng     |  1 +
 .../admin/templates/server_config_web_edit.htm  |  6 ++++++
 server/lib/classes/system.inc.php               | 16 ++++++++++++++++
 server/plugins-available/apache2_plugin.inc.php | 17 ++++++++++++++---
 .../cron_jailkit_plugin.inc.php                 |  6 ++++++
 .../shelluser_base_plugin.inc.php               |  7 +++++++
 .../shelluser_jailkit_plugin.inc.php            | 15 +++++++++++++++
 9 files changed, 72 insertions(+), 3 deletions(-)

diff --git a/install/tpl/server.ini.master b/install/tpl/server.ini.master
index 49b9e3ce26..eaeff0210a 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 09334c7494..e08d1cc08f 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 b14f34dd96..c32657b21c 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 40750038ba..349ddcdcf9 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'}
 					</div>
 			</div>
+	  <div class="ctrlHolder">
+				<p class="label">{tmpl_var name='web_folder_protection_txt'}</p>
+					<div class="multiField">
+						{tmpl_var name='web_folder_protection'}
+					</div>
+			</div>
 	  <div class="ctrlHolder">
 				<p class="label">{tmpl_var name='add_web_users_to_sshusers_group_txt'}</p>
 					<div class="multiField">
diff --git a/server/lib/classes/system.inc.php b/server/lib/classes/system.inc.php
index c43a0ccd1d..323ffe5046 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 a6157ada8e..c441a6a7c2 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 2e5f06eea5..1e4713846c 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 5c41863381..a56ec6d72d 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 671ae62c16..6ffe8e87a2 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);
-- 
GitLab