@@ -37,6 +37,8 @@ class apache2_plugin {
3737 var $ action = '' ;
3838 var $ ssl_certificate_changed = false ;
3939 var $ update_letsencrypt = false ;
40+ var $ website = null ;
41+ var $ jailkit_config = null ;
4042
4143 //* This function is called during ispconfig installation to determine
4244 // if a symlink shall be created for this plugin.
@@ -797,6 +799,77 @@ function update($event_name, $data) {
797799 $ app ->system ->chgrp ($ data ['new ' ]['document_root ' ].'/private ' , $ groupname );
798800 }
799801
802+ // load jailkit server config
803+ $ jailkit_config = $ app ->getconf ->get_server_config ($ conf ['server_id ' ], 'jailkit ' );
804+
805+ // website overrides
806+ if (isset ($ data ['new ' ]['jailkit_chroot_app_sections ' ]) && $ data ['new ' ]['jailkit_chroot_app_sections ' ] != '' ) {
807+ $ jailkit_config ['jailkit_chroot_app_sections ' ] = $ data ['new ' ]['jailkit_chroot_app_sections ' ];
808+ }
809+ if (isset ($ data ['new ' ]['jailkit_chroot_app_programs ' ]) && $ data ['new ' ]['jailkit_chroot_app_programs ' ] != '' ) {
810+ $ jailkit_config ['jailkit_chroot_app_programs ' ] = $ data ['new ' ]['jailkit_chroot_app_programs ' ];
811+ }
812+
813+ $ last_updated = preg_split ('/[\s,]+/ ' , $ jailkit_config ['jailkit_chroot_app_sections ' ]
814+ .' ' .$ jailkit_config ['jailkit_chroot_app_programs ' ]
815+ .' ' .$ jailkit_config ['jailkit_chroot_cron_programs ' ]);
816+ $ last_updated = array_unique ($ last_updated , SORT_REGULAR );
817+ sort ($ last_updated , SORT_STRING );
818+ $ update_hash = hash ('md5 ' , implode (' ' , $ last_updated ));
819+
820+ // Create jailkit chroot when enabling php_fpm_chroot
821+ if ($ data ['new ' ]['php_fpm_chroot ' ] == 'y ' && $ data ['old ' ]['php_fpm_chroot ' ] != 'y ' ) {
822+ $ website = $ app ->db ->queryOneRecord ('SELECT * FROM web_domain WHERE domain_id = ? ' , $ data ['new ' ]['domain_id ' ]);
823+ $ this ->website = array_merge ($ website , $ data ['new ' ], array ('new_jailkit_hash ' => $ update_hash ));
824+ $ this ->jailkit_config = $ jailkit_config ;
825+ $ this ->_setup_jailkit_chroot ();
826+ $ this ->_add_jailkit_user ();
827+ $ check_for_jailkit_updates =false ;
828+ // else delete if unused
829+ } elseif ($ data ['new ' ]['delete_unused_jailkit ' ] == 'y ' && $ data ['new ' ]['php_fpm_chroot ' ] != 'y ' ) {
830+ $ check_for_jailkit_updates =false ;
831+ $ this ->_delete_jailkit_if_unused ($ data ['new ' ]['domain_id ' ]);
832+ if (is_dir ($ data ['new ' ]['document_root ' ].'/etc/jailkit ' )) {
833+ $ check_for_jailkit_updates =true ;
834+ }
835+ // else update if needed
836+ } elseif ($ data ['new ' ]['delete_unused_jailkit ' ] != 'y ' ) {
837+ $ check_for_jailkit_updates =true ;
838+ }
839+
840+ // If jail exists (and wasn't deleted), we may need to update it
841+ if ($ check_for_jailkit_updates &&
842+ ( ($ data ['old ' ]['jailkit_chroot_app_sections ' ] != $ data ['new ' ]['jailkit_chroot_app_sections ' ]) ||
843+ ($ data ['old ' ]['jailkit_chroot_app_programs ' ] != $ data ['new ' ]['jailkit_chroot_app_programs ' ]) ) )
844+ {
845+
846+ if (isset ($ jailkit_config ['jailkit_hardlinks ' ])) {
847+ if ($ jailkit_config ['jailkit_hardlinks ' ] == 'yes ' ) {
848+ $ options = array ( 'hardlink ' , );
849+ } elseif ($ jailkit_config ['jailkit_hardlinks ' ] == 'no ' ) {
850+ $ options = array ();
851+ }
852+ } else {
853+ $ options = array ( 'allow_hardlink ' , );
854+ }
855+
856+ $ options [] = 'force ' ;
857+
858+ $ sections = $ jailkit_config ['jailkit_chroot_app_sections ' ];
859+ $ programs = $ jailkit_config ['jailkit_chroot_app_programs ' ] . ' '
860+ . $ jailkit_config ['jailkit_chroot_cron_programs ' ];
861+
862+ // don't update if last_jailkit_hash is the same
863+ $ tmp = $ app ->db ->queryOneRecord ('SELECT `last_jailkit_hash` FROM web_domain WHERE domain_id = ? ' , $ data ['new ' ]['parent_domain_id ' ]);
864+ if ($ update_hash != $ tmp ['last_jailkit_hash ' ]) {
865+ $ app ->system ->update_jailkit_chroot ($ data ['new ' ]['document_root ' ], $ sections , $ programs , $ options );
866+
867+ // this gets last_jailkit_update out of sync with master db, but that is ok,
868+ // as it is only used as a timestamp to moderate the frequency of updating on the slaves
869+ $ app ->db ->query ("UPDATE `web_domain` SET `last_jailkit_update` = NOW(), `last_jailkit_hash` = ? WHERE `document_root` = ? " , $ update_hash , $ data ['new ' ]['document_root ' ]);
870+ }
871+ unset($ tmp );
872+ }
800873
801874 // Remove the symlink for the site, if site is renamed
802875 if ($ this ->action == 'update ' && $ data ['old ' ]['domain ' ] != '' && $ data ['new ' ]['domain ' ] != $ data ['old ' ]['domain ' ]) {
@@ -1176,7 +1249,6 @@ function update($event_name, $data) {
11761249 //* Create custom php.ini
11771250 if (trim ($ data ['new ' ]['custom_php_ini ' ]) != '' ) {
11781251 $ has_custom_php_ini = true ;
1179- $ custom_sendmail_path = false ;
11801252 if (!is_dir ($ custom_php_ini_dir )) $ app ->system ->mkdirpath ($ custom_php_ini_dir );
11811253
11821254 $ php_ini_content = $ this ->get_master_php_ini_content ($ data ['new ' ]);
@@ -1201,13 +1273,6 @@ function update($event_name, $data) {
12011273 }
12021274 }
12031275
1204- $ custom_sendmail_path = false ;
1205- $ line = strtok ($ php_ini_content , '\n ' );
1206- while ($ line !== false ) {
1207- if (strpos ($ line , 'sendmail_path ' ) === 0 ) $ custom_sendmail_path = true ;
1208- $ line = strtok ('\n ' );
1209- }
1210-
12111276 $ app ->system ->file_put_contents ($ custom_php_ini_dir .'/php.ini ' , $ php_ini_content );
12121277 } else {
12131278 $ has_custom_php_ini = false ;
@@ -1252,7 +1317,7 @@ function update($event_name, $data) {
12521317 $ trans = array (
12531318 '{DOCROOT} ' => $ vhost_data ['web_document_root_www ' ],
12541319 '{DOCROOT_CLIENT} ' => $ vhost_data ['web_document_root ' ],
1255- '{DOMAIN} ' => $ vhost_data ['domain ' ]
1320+ '{DOMAIN} ' => $ vhost_data ['domain ' ]
12561321 );
12571322 $ vhost_data ['apache_directives ' ] = strtr ($ vhost_data ['apache_directives ' ], $ trans );
12581323
@@ -1317,8 +1382,6 @@ function update($event_name, $data) {
13171382 $ vhost_data ['seo_redirect_enabled ' ] = 0 ;
13181383 }
13191384
1320- $ vhost_data ['custom_sendmail_path ' ] = (isset ($ custom_sendmail_path ) && $ custom_sendmail_path ) ? 'y ' : 'n ' ;
1321-
13221385 $ tpl ->setVar ($ vhost_data );
13231386 $ tpl ->setVar ('apache_version ' , $ app ->system ->getapacheversion ());
13241387
@@ -3376,7 +3439,6 @@ private function php_fpm_pool_update ($data, $web_config, $pool_dir, $pool_name,
33763439 }
33773440
33783441 $ custom_session_save_path = false ;
3379- $ custom_sendmail_path = false ;
33803442 if ($ custom_php_ini_settings != '' ){
33813443 // Make sure we only have Unix linebreaks
33823444 $ custom_php_ini_settings = str_replace ("\r\n" , "\n" , $ custom_php_ini_settings );
@@ -3394,7 +3456,6 @@ private function php_fpm_pool_update ($data, $web_config, $pool_dir, $pool_name,
33943456 if ($ value != '' ){
33953457 $ key = trim ($ key );
33963458 if ($ key == 'session.save_path ' ) $ custom_session_save_path = true ;
3397- if ($ key == 'sendmail_path ' ) $ custom_sendmail_path = true ;
33983459 switch (strtolower ($ value )) {
33993460 case '0 ' :
34003461 // PHP-FPM might complain about invalid boolean value if you use 0
@@ -3417,7 +3478,6 @@ private function php_fpm_pool_update ($data, $web_config, $pool_dir, $pool_name,
34173478 }
34183479
34193480 $ tpl ->setVar ('custom_session_save_path ' , ($ custom_session_save_path ? 'y ' : 'n ' ));
3420- $ tpl ->setVar ('custom_sendmail_path ' , ($ custom_sendmail_path ? 'y ' : 'n ' ));
34213481
34223482 $ tpl ->setLoop ('custom_php_ini_settings ' , $ final_php_ini_settings );
34233483
@@ -3632,6 +3692,154 @@ private function get_seo_redirects($web, $prefix = ''){
36323692 return $ seo_redirects ;
36333693 }
36343694
3695+ function _setup_jailkit_chroot ()
3696+ {
3697+ global $ app ;
3698+
3699+ $ app ->uses ('system ' );
3700+
3701+ if (isset ($ this ->jailkit_config ) && isset ($ this ->jailkit_config ['jailkit_hardlinks ' ])) {
3702+ if ($ this ->jailkit_config ['jailkit_hardlinks ' ] == 'yes ' ) {
3703+ $ options = array ( 'hardlink ' , );
3704+ } elseif ($ this ->jailkit_config ['jailkit_hardlinks ' ] == 'no ' ) {
3705+ $ options = array ();
3706+ }
3707+ } else {
3708+ $ options = array ( 'allow_hardlink ' , );
3709+ }
3710+
3711+ // should move return here if $this->website['new_jailkit_hash'] == $this->website['last_jailkit_hash'] ?
3712+
3713+ // check if the chroot environment is created yet if not create it with a list of program sections from the config
3714+ if (!is_dir ($ this ->website ['document_root ' ].'/etc/jailkit ' ))
3715+ {
3716+ $ app ->system ->create_jailkit_chroot ($ this ->website ['document_root ' ], $ this ->jailkit_config ['jailkit_chroot_app_sections ' ], $ options );
3717+ $ this ->app ->log ("Added jailkit chroot " , LOGLEVEL_DEBUG );
3718+
3719+ $ this ->_add_jailkit_programs ($ options );
3720+
3721+ $ this ->app ->load ('tpl ' );
3722+
3723+ $ tpl = new tpl ();
3724+ $ tpl ->newTemplate ("bash.bashrc.master " );
3725+
3726+ $ tpl ->setVar ('jailkit_chroot ' , true );
3727+ $ tpl ->setVar ('domain ' , $ this ->website ['domain ' ]);
3728+ $ tpl ->setVar ('home_dir ' , $ this ->_get_home_dir ("" ));
3729+
3730+ $ bashrc = $ this ->website ['document_root ' ].'/etc/bash.bashrc ' ;
3731+ if (@is_file ($ bashrc ) || @is_link ($ bashrc )) unlink ($ bashrc );
3732+
3733+ file_put_contents ($ bashrc , $ tpl ->grab ());
3734+ unset($ tpl );
3735+
3736+ $ this ->app ->log ("Added bashrc script: " .$ bashrc , LOGLEVEL_DEBUG );
3737+
3738+ $ tpl = new tpl ();
3739+ $ tpl ->newTemplate ("motd.master " );
3740+
3741+ $ tpl ->setVar ('domain ' , $ this ->website ['domain ' ]);
3742+
3743+ $ motd = $ this ->website ['document_root ' ].'/var/run/motd ' ;
3744+ if (@is_file ($ motd ) || @is_link ($ motd )) unlink ($ motd );
3745+
3746+ $ app ->system ->file_put_contents ($ motd , $ tpl ->grab ());
3747+
3748+ } else {
3749+ // force update existing jails
3750+ $ options [] = 'force ' ;
3751+
3752+ $ sections = $ this ->jailkit_config ['jailkit_chroot_app_sections ' ];
3753+ $ programs = $ this ->jailkit_config ['jailkit_chroot_app_programs ' ] . ' '
3754+ . $ this ->jailkit_config ['jailkit_chroot_cron_programs ' ];
3755+
3756+ if ($ this ->website ['new_jailkit_hash ' ] == $ this ->website ['last_jailkit_hash ' ]) {
3757+ return ;
3758+ }
3759+
3760+ $ app ->system ->update_jailkit_chroot ($ this ->website ['document_root ' ], $ sections , $ programs , $ options );
3761+ }
3762+
3763+ // this gets last_jailkit_update out of sync with master db, but that is ok,
3764+ // as it is only used as a timestamp to moderate the frequency of updating on the slaves
3765+ $ app ->db ->query ("UPDATE `web_domain` SET `last_jailkit_update` = NOW(), `last_jailkit_hash` = ? WHERE `document_root` = ? " , $ this ->website ['new_jailkit_hash ' ], $ this ->website ['document_root ' ]);
3766+ }
3767+
3768+ function _add_jailkit_programs ($ opts =array ())
3769+ {
3770+ global $ app ;
3771+
3772+ $ app ->uses ('system ' );
3773+
3774+ //copy over further programs and its libraries
3775+ $ app ->system ->create_jailkit_programs ($ this ->website ['document_root ' ], $ this ->jailkit_config ['jailkit_chroot_app_programs ' ], $ opts );
3776+ $ this ->app ->log ("Added app programs to jailkit chroot " , LOGLEVEL_DEBUG );
3777+
3778+ $ app ->system ->create_jailkit_programs ($ this ->website ['document_root ' ], $ this ->jailkit_config ['jailkit_chroot_cron_programs ' ], $ opts );
3779+ $ this ->app ->log ("Added cron programs to jailkit chroot " , LOGLEVEL_DEBUG );
3780+ }
3781+
3782+ function _get_home_dir ($ username )
3783+ {
3784+ return str_replace ("[username] " , $ username , $ this ->jailkit_config ['jailkit_chroot_home ' ]);
3785+ }
3786+
3787+ function _add_jailkit_user ()
3788+ {
3789+ global $ app ;
3790+
3791+ // add the user to the chroot
3792+ $ jailkit_chroot_userhome = $ this ->_get_home_dir ($ this ->website ['system_user ' ]);
3793+
3794+ if (!is_dir ($ this ->website ['document_root ' ].'/etc ' )) mkdir ($ this ->website ['document_root ' ].'/etc ' );
3795+ if (!is_file ($ this ->website ['document_root ' ].'/etc/passwd ' )) $ app ->system ->exec_safe ('touch ? ' , $ this ->website ['document_root ' ].'/etc/passwd ' );
3796+
3797+ // IMPORTANT!
3798+ // ALWAYS create the user. Even if the user was created before
3799+ // if we check if the user exists, then a update (no shell -> jailkit) will not work
3800+ // and the user has FULL ACCESS to the root of the server!
3801+ $ app ->system ->create_jailkit_user ($ this ->website ['system_user ' ], $ this ->website ['document_root ' ], $ jailkit_chroot_userhome );
3802+
3803+ $ app ->system ->mkdir ($ this ->website ['document_root ' ].$ jailkit_chroot_userhome , 0755 , true );
3804+ $ app ->system ->chown ($ this ->website ['document_root ' ].$ jailkit_chroot_userhome , $ this ->website ['system_user ' ]);
3805+ $ app ->system ->chgrp ($ this ->website ['document_root ' ].$ jailkit_chroot_userhome , $ this ->website ['system_group ' ]);
3806+
3807+ $ this ->app ->log ("Added created jailkit user home in : " .$ this ->website ['document_root ' ].$ jailkit_chroot_userhome , LOGLEVEL_DEBUG );
3808+ }
3809+
3810+ private function _delete_jailkit_if_unused ($ parent_domain_id ) {
3811+ global $ app , $ conf ;
3812+
3813+ // get jail directory
3814+ $ parent_domain = $ app ->db ->queryOneRecord ("SELECT * FROM `web_domain` WHERE `domain_id` = ? OR `parent_domain_id` = ? AND `document_root` IS NOT NULL " , $ parent_domain_id , $ parent_domain_id );
3815+ if (!is_dir ($ parent_domain ['document_root ' ])) {
3816+ return ;
3817+ }
3818+
3819+ // chroot is used by php-fpm
3820+ if (isset ($ parent_domain ['php_fpm_chroot ' ]) && $ parent_domain ['php_fpm_chroot ' ] == 'y ' ) {
3821+ return ;
3822+ }
3823+
3824+ // check for any shell_user using this jail
3825+ $ inuse = $ app ->db ->queryOneRecord ('SELECT shell_user_id FROM `shell_user` WHERE `parent_domain_id` = ? AND `chroot` = ? ' , $ parent_domain_id , 'jailkit ' );
3826+ if ($ inuse ) {
3827+ return ;
3828+ }
3829+
3830+ // check for any cron job using this jail
3831+ $ inuse = $ app ->db ->queryOneRecord ('SELECT id FROM `cron` WHERE `parent_domain_id` = ? AND `type` = ? ' , $ parent_domain_id , 'chrooted ' );
3832+ if ($ inuse ) {
3833+ return ;
3834+ }
3835+
3836+ $ app ->system ->delete_jailkit_chroot ($ parent_domain ['document_root ' ]);
3837+
3838+ // this gets last_jailkit_update out of sync with master db, but that is ok,
3839+ // as it is only used as a timestamp to moderate the frequency of updating on the slaves
3840+ $ app ->db ->query ("UPDATE `web_domain` SET `last_jailkit_update` = NOW(), `last_jailkit_hash` = NULL WHERE `document_root` = ? " , $ parent_domain ['document_root ' ]);
3841+ }
3842+
36353843} // end class
36363844
36373845?>
0 commit comments