Till Brehm
2016-06-14 a95251e2b49c0c2cb8b81addc3a1afc2300ee650
commit | author | age
0b0dc9 1 <?php
M 2
3 /*
4 Copyright (c) 2007, Till Brehm, projektfarm Gmbh
5 Modified 2009, Marius Cramer, pixcept KG
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10
11     * Redistributions of source code must retain the above copyright notice,
12       this list of conditions and the following disclaimer.
13     * Redistributions in binary form must reproduce the above copyright notice,
14       this list of conditions and the following disclaimer in the documentation
15       and/or other materials provided with the distribution.
16     * Neither the name of ISPConfig nor the names of its contributors
17       may be used to endorse or promote products derived from this software without
18       specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
27 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 class cron_jailkit_plugin {
7fe908 33
0b0dc9 34     //* $plugin_name and $class_name have to be the same then the name of this class
M 35     var $plugin_name = 'cron_jailkit_plugin';
36     var $class_name = 'cron_jailkit_plugin';
7fe908 37
0b0dc9 38     //* This function is called during ispconfig installation to determine
M 39     //  if a symlink shall be created for this plugin.
40     function onInstall() {
41         global $conf;
7fe908 42
0b0dc9 43         if($conf['services']['web'] == true) {
M 44             return true;
45         } else {
46             return false;
47         }
7fe908 48
0b0dc9 49     }
7fe908 50
MC 51
0b0dc9 52     /*
M 53          This function is called when the plugin is loaded
54     */
7fe908 55
0b0dc9 56     function onLoad() {
M 57         global $app;
7fe908 58
0b0dc9 59         /*
M 60         Register for the events
61         */
7fe908 62
MC 63         $app->plugins->registerEvent('cron_insert', $this->plugin_name, 'insert');
64         $app->plugins->registerEvent('cron_update', $this->plugin_name, 'update');
65         $app->plugins->registerEvent('cron_delete', $this->plugin_name, 'delete');
66
0b0dc9 67     }
7fe908 68
0b0dc9 69     //* This function is called, when a cron job is inserted in the database
7fe908 70     function insert($event_name, $data) {
0b0dc9 71         global $app, $conf;
7fe908 72
MC 73         if($data["new"]["parent_domain_id"] == '') {
74             $app->log("Parent domain not set", LOGLEVEL_WARN);
75             return 0;
76         }
77
78         //* get data from web
cc7a82 79         $parent_domain = $app->db->queryOneRecord("SELECT `domain_id`, `system_user`, `system_group`, `document_root`, `domain` FROM `web_domain` WHERE `domain_id` = ?", $data["new"]["parent_domain_id"]);
7fe908 80         if(!$parent_domain["domain_id"]) {
MC 81             $app->log("Parent domain not found", LOGLEVEL_WARN);
82             return 0;
83         }
64ea56 84
MC 85         if(!$app->system->is_allowed_user($parent_domain['system_user'], true, true)
86             || !$app->system->is_allowed_group($parent_domain['system_group'], true, true)) {
87             $app->log("Websites (and Crons) cannot be owned by the root user or group.", LOGLEVEL_WARN);
88             return false;
89         }
90
7fe908 91
e23d19 92         $this->parent_domain = $parent_domain;
7fe908 93
MC 94         $app->uses('system');
95
0b0dc9 96         if($app->system->is_user($parent_domain['system_user'])) {
7fe908 97
0b0dc9 98             /**
7fe908 99              * Setup Jailkit Chroot System If Enabled
MC 100              */
101
102
0b0dc9 103             if ($data['new']['type'] == "chrooted")
M 104             {
105                 // load the server configuration options
e23d19 106                 /*
0b0dc9 107                 $app->uses("getconf");
M 108                 $this->data = $data;
109                 $this->app = $app;
110                 $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
111                 $this->parent_domain = $parent_domain;
7fe908 112
0b0dc9 113                 $this->_setup_jailkit_chroot();
7fe908 114
0b0dc9 115                 //$command .= 'usermod -U '.escapeshellcmd($parent_domain['system_user']);
M 116                 //exec($command);
7fe908 117
0b0dc9 118                 $this->_add_jailkit_user();
e23d19 119                 */
T 120                 $app->uses("getconf");
121                 $this->data = $data;
122                 $this->app = $app;
123                 $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
7fe908 124
e23d19 125                 $this->_update_website_security_level();
7fe908 126
MC 127                 $app->system->web_folder_protection($parent_domain['document_root'], false);
128
e23d19 129                 $this->_setup_jailkit_chroot();
7fe908 130
e23d19 131                 $this->_add_jailkit_user();
7fe908 132
526b99 133                 $command .= 'usermod -U '.escapeshellcmd($parent_domain["system_user"]).' 2>/dev/null';
e23d19 134                 exec($command);
7fe908 135
e23d19 136                 $this->_update_website_security_level();
7fe908 137
MC 138                 $app->system->web_folder_protection($parent_domain['document_root'], true);
0b0dc9 139             }
7fe908 140
MC 141             $app->log("Jailkit Plugin (Cron) -> insert username:".$parent_domain['system_user'], LOGLEVEL_DEBUG);
142
0b0dc9 143         } else {
7fe908 144             $app->log("Jailkit Plugin (Cron) -> insert username:".$parent_domain['system_user']." skipped, the user does not exist.", LOGLEVEL_WARN);
0b0dc9 145         }
7fe908 146
0b0dc9 147     }
7fe908 148
0b0dc9 149     //* This function is called, when a cron job is updated in the database
7fe908 150     function update($event_name, $data) {
0b0dc9 151         global $app, $conf;
7fe908 152
MC 153         if($data["new"]["parent_domain_id"] == '') {
154             $app->log("Parent domain not set", LOGLEVEL_WARN);
155             return 0;
156         }
157         //* get data from web
cc7a82 158         $parent_domain = $app->db->queryOneRecord("SELECT `domain_id`, `system_user`, `system_group`, `document_root`, `domain` FROM `web_domain` WHERE `domain_id` = ?", $data["new"]["parent_domain_id"]);
7fe908 159         if(!$parent_domain["domain_id"]) {
MC 160             $app->log("Parent domain not found", LOGLEVEL_WARN);
161             return 0;
64ea56 162         }
MC 163         if(!$app->system->is_allowed_user($parent_domain['system_user'], true, true)
164             || !$app->system->is_allowed_group($parent_domain['system_group'], true, true)) {
7fe908 165             $app->log("Websites (and Crons) cannot be owned by the root user or group.", LOGLEVEL_WARN);
64ea56 166             return false;
7fe908 167         }
MC 168
169         $app->uses('system');
170
e23d19 171         $this->parent_domain = $parent_domain;
7fe908 172
0b0dc9 173         if($app->system->is_user($parent_domain['system_user'])) {
7fe908 174
MC 175
176
0b0dc9 177             /**
7fe908 178              * Setup Jailkit Chroot System If Enabled
MC 179              */
0b0dc9 180             if ($data['new']['type'] == "chrooted")
M 181             {
7fe908 182                 $app->log("Jailkit Plugin (Cron) -> setting up jail", LOGLEVEL_DEBUG);
0b0dc9 183                 // load the server configuration options
e23d19 184                 /*
0b0dc9 185                 $app->uses("getconf");
M 186                 $this->data = $data;
187                 $this->app = $app;
188                 $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
189                 $this->parent_domain = $parent_domain;
7fe908 190
0b0dc9 191                 $this->_setup_jailkit_chroot();
M 192                 $this->_add_jailkit_user();
e23d19 193                 */
T 194                 $app->uses("getconf");
195                 $this->data = $data;
196                 $this->app = $app;
197                 $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
4bd960 198
T 199                 $this->_update_website_security_level();
7fe908 200
MC 201                 $app->system->web_folder_protection($parent_domain['document_root'], false);
202
e23d19 203                 $this->_setup_jailkit_chroot();
T 204                 $this->_add_jailkit_user();
7fe908 205
e23d19 206                 $this->_update_website_security_level();
7fe908 207                 $app->system->web_folder_protection($parent_domain['document_root'], true);
0b0dc9 208             }
7fe908 209
MC 210             $app->log("Jailkit Plugin (Cron) -> update username:".$parent_domain['system_user'], LOGLEVEL_DEBUG);
211
0b0dc9 212         } else {
7fe908 213             $app->log("Jailkit Plugin (Cron) -> update username:".$parent_domain['system_user']." skipped, the user does not exist.", LOGLEVEL_WARN);
0b0dc9 214         }
7fe908 215
0b0dc9 216     }
7fe908 217
0b0dc9 218     //* This function is called, when a cron job is deleted in the database
7fe908 219     function delete($event_name, $data) {
0b0dc9 220         global $app, $conf;
7fe908 221
0b0dc9 222         //* nothing to do here!
7fe908 223
0b0dc9 224     }
7fe908 225
0b0dc9 226     function _setup_jailkit_chroot()
M 227     {
7fe908 228         global $app;
MC 229
230         //check if the chroot environment is created yet if not create it with a list of program sections from the config
231         if (!is_dir($this->parent_domain['document_root'].'/etc/jailkit'))
232         {
233             $command = '/usr/local/ispconfig/server/scripts/create_jailkit_chroot.sh';
234             $command .= ' '.escapeshellcmd($this->parent_domain['document_root']);
235             $command .= ' \''.$this->jailkit_config['jailkit_chroot_app_sections'].'\'';
236             exec($command.' 2>/dev/null');
237
238             $this->app->log("Added jailkit chroot with command: ".$command, LOGLEVEL_DEBUG);
239
240             //$this->_add_jailkit_programs(); // done later on
241
242             $this->app->load('tpl');
243
244             $tpl = new tpl();
245             $tpl->newTemplate("bash.bashrc.master");
246
247             $tpl->setVar('jailkit_chroot', true);
248             $tpl->setVar('domain', $this->parent_domain['domain']);
249             $tpl->setVar('home_dir', $this->_get_home_dir(""));
250
251             $bashrc = escapeshellcmd($this->parent_domain['document_root']).'/etc/bash.bashrc';
252             if(@is_file($bashrc) || @is_link($bashrc)) unlink($bashrc);
253
254             $app->system->file_put_contents($bashrc, $tpl->grab());
255             unset($tpl);
256
257             $this->app->log('Added bashrc script: '.$bashrc, LOGLEVEL_DEBUG);
258
259             $tpl = new tpl();
260             $tpl->newTemplate('motd.master');
261
262             $tpl->setVar('domain', $this->parent_domain['domain']);
263
264             $motd = escapeshellcmd($this->parent_domain['document_root']).'/var/run/motd';
265             if(@is_file($motd) || @is_link($motd)) unlink($motd);
266
267             $app->system->file_put_contents($motd, $tpl->grab());
268
269         }
270         $this->_add_jailkit_programs();
0b0dc9 271     }
7fe908 272
0b0dc9 273     function _add_jailkit_programs()
M 274     {
43b345 275         global $app;
7fe908 276
0b0dc9 277         //copy over further programs and its libraries
M 278         $command = '/usr/local/ispconfig/server/scripts/create_jailkit_programs.sh';
279         $command .= ' '.escapeshellcmd($this->parent_domain['document_root']);
280         $command .= ' \''.$this->jailkit_config['jailkit_chroot_app_programs'].'\'';
526b99 281         exec($command.' 2>/dev/null');
7fe908 282
MC 283         $this->app->log("Added programs to jailkit chroot with command: ".$command, LOGLEVEL_DEBUG);
284
285         $command = '/usr/local/ispconfig/server/scripts/create_jailkit_programs.sh';
286         $command .= ' '.escapeshellcmd($this->parent_domain['document_root']);
287         $command .= ' \''.$this->jailkit_config['jailkit_chroot_cron_programs'].'\'';
288         exec($command.' 2>/dev/null');
289
290         $this->app->log("Added cron programs to jailkit chroot with command: ".$command, LOGLEVEL_DEBUG);
0b0dc9 291     }
7fe908 292
0b0dc9 293     function _add_jailkit_user()
M 294     {
7fe908 295         global $app;
MC 296
297         //add the user to the chroot
298         $jailkit_chroot_userhome = $this->_get_home_dir($this->parent_domain['system_user']);
299
300         if(!is_dir($this->parent_domain['document_root'].'/etc')) mkdir($this->parent_domain['document_root'].'/etc');
301         if(!is_file($this->parent_domain['document_root'].'/etc/passwd')) exec('touch '.$this->parent_domain['document_root'].'/etc/passwd');
302
303         // IMPORTANT!
304         // ALWAYS create the user. Even if the user was created before
305         // if we check if the user exists, then a update (no shell -> jailkit) will not work
306         // and the user has FULL ACCESS to the root of the server!
307         $command = '/usr/local/ispconfig/server/scripts/create_jailkit_user.sh';
308         $command .= ' '.escapeshellcmd($this->parent_domain['system_user']);
309         $command .= ' '.escapeshellcmd($this->parent_domain['document_root']);
310         $command .= ' '.$jailkit_chroot_userhome;
311         $command .= ' '.escapeshellcmd("/bin/bash");
312         exec($command.' 2>/dev/null');
313
314         $this->app->log("Added jailkit user to chroot with command: ".$command, LOGLEVEL_DEBUG);
315
316         $app->system->mkdir(escapeshellcmd($this->parent_domain['document_root'].$jailkit_chroot_userhome), 0755, true);
317         $app->system->chown(escapeshellcmd($this->parent_domain['document_root'].$jailkit_chroot_userhome), escapeshellcmd($this->parent_domain['system_user']));
318         $app->system->chgrp(escapeshellcmd($this->parent_domain['document_root'].$jailkit_chroot_userhome), escapeshellcmd($this->parent_domain['system_group']));
319
0b0dc9 320     }
7fe908 321
MC 322     function _get_home_dir($username)
323     {
324         return str_replace("[username]", escapeshellcmd($username), $this->jailkit_config["jailkit_chroot_home"]);
325     }
326
e23d19 327     //* Update the website root directory permissions depending on the security level
T 328     function _update_website_security_level() {
7fe908 329         global $app, $conf;
MC 330
e23d19 331         // load the server configuration options
T 332         $app->uses("getconf");
333         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
7fe908 334
4bd960 335         // Get the parent website of this shell user
cc7a82 336         $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ?", $this->data['new']['parent_domain_id']);
7fe908 337
4bd960 338         //* If the security level is set to high
T 339         if($web_config['security_level'] == 20 && is_array($web)) {
7fe908 340             $app->system->web_folder_protection($web["document_root"], false);
MC 341             $app->system->chmod($web["document_root"], 0755);
342             $app->system->chown($web["document_root"], 'root');
343             $app->system->chgrp($web["document_root"], 'root');
344             $app->system->web_folder_protection($web["document_root"], true);
4bd960 345         }
e23d19 346     }
7fe908 347
e23d19 348     //* Wrapper for exec function for easier debugging
T 349     private function _exec($command) {
350         global $app;
7fe908 351         $app->log('exec: '.$command, LOGLEVEL_DEBUG);
e23d19 352         exec($command);
T 353     }
7fe908 354
MC 355
0b0dc9 356
M 357 } // end class
358
c128b1 359 ?>