Skip to content

Commit 6a95c89

Browse files
author
daniel
committed
Added initial jailkit chroot feature as a plugin
Added chroot options to the shell user form Added jailkit ini settings Added ini settings for fastcgi Fixed bug with web delete not removing parent web user unless that was intentional ? Changed name of shell user plugin so plugin order calls this first Started a change to the update script. TODO: Fix problem with jailkit chroot users logging into parent web user's directory. Fixup bash command prompt to display the correct user somehow because they all share the same id. Fixup install / update script so the fastcgi script and directory is created for the ispconfig site on setup / update. Can't work out how to get to the templating system to generate the script from.
1 parent 5a8b3e5 commit 6a95c89

File tree

11 files changed

+624
-17
lines changed

11 files changed

+624
-17
lines changed

install/existing_db.sql

Lines changed: 306 additions & 0 deletions
Large diffs are not rendered by default.

install/lib/installer_base.lib.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ public function install_ispconfig()
624624
if ($dh = opendir($dir)) {
625625
while (($file = readdir($dh)) !== false) {
626626
if($file != '.' && $file != '..') {
627-
if(!is_link($install_dir.'/server/mods-enabled/'.$file)) symlink($install_dir.'/server/mods-available/'.$file, $install_dir.'/server/mods-enabled/'.$file);
627+
if(!@is_link($install_dir.'/server/mods-enabled/'.$file)) @symlink($install_dir.'/server/mods-available/'.$file, $install_dir.'/server/mods-enabled/'.$file);
628628
}
629629
}
630630
closedir($dh);
@@ -636,7 +636,7 @@ public function install_ispconfig()
636636
if ($dh = opendir($dir)) {
637637
while (($file = readdir($dh)) !== false) {
638638
if($file != '.' && $file != '..') {
639-
if(!is_link($install_dir.'/server/plugins-enabled/'.$file)) symlink($install_dir.'/server/plugins-available/'.$file, $install_dir.'/server/plugins-enabled/'.$file);
639+
if(!@is_link($install_dir.'/server/plugins-enabled/'.$file)) @symlink($install_dir.'/server/plugins-available/'.$file, $install_dir.'/server/plugins-enabled/'.$file);
640640
}
641641
}
642642
closedir($dh);

install/tpl/server.ini.master

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,17 @@ website_path=/var/clients/client[client_id]/web[website_id]
3232
website_symlinks=/var/www/[website_domain]/:/var/clients/client[client_id]/[website_domain]/
3333
vhost_conf_dir=/etc/apache2/sites-available
3434
vhost_conf_enabled_dir=/etc/apache2/sites-enabled
35+
36+
[fastcgi]
3537
fastcgi_starter_path=/var/www/php-fcgi-scripts/[system_user]/
3638
fastcgi_starter_script=.php-fcgi-starter
3739
fastcgi_alias=/php/
3840
fastcgi_phpini_path=/etc/php5/cgi/
3941
fastcgi_children=8
4042
fastcgi_max_requests=5000
41-
fastcgi_bin=/usr/bin/php-cgi
43+
fastcgi_bin=/usr/bin/php-cgi
44+
45+
[jailkit]
46+
jailkit_chroot_home=/home/[username]
47+
jailkit_chroot_app_sections=basicshell editors extendedshell netutils ssh sftp scp groups jk_lsh
48+
jailkit_chroot_app_programs=/usr/bin/groups /usr/bin/id /usr/bin/dircolors /usr/bin/lesspipe /usr/bin/basename /usr/bin/dirname /usr/bin/nano /usr/bin/pico

install/update.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,15 @@
180180
//** TODO: Don't always ask for this somehow ?
181181
$fast_cgi = $inst->simple_query('CGI PHP Enabled Server?', array('yes','no'),'no');
182182

183+
183184
if($fast_cgi == 'yes') {
184185
$alias = $inst->free_query('Script Alias', '/php/');
185186
$path = $inst->free_query('Script Alias Path', '/path/to/cgi/bin');
186187
$inst->conf['apache']['vhost_cgi_alias'] = sprintf('ScriptAlias %s %s', $alias, $path);
188+
$inst->conf['apache']['vhost_cgi_alias_path'] = $path;
187189
} else {
188190
$inst->conf['apache']['vhost_cgi_alias'] = "";
191+
$inst->conf['apache']['vhost_cgi_alias_path'] = "";
189192
}
190193

191194

interface/web/sites/shell_user_edit.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,8 @@ function onAfterInsert() {
8080
$dir = $web["document_root"];
8181
$puser = $web["system_user"];
8282
$pgroup = $web["system_group"];
83-
$chroot = $web["chroot"];
8483

85-
$sql = "UPDATE shell_user SET server_id = $server_id, dir = '$dir', puser = '$puser', pgroup = '$pgroup' chroot='$chroot' WHERE shell_user_id = ".$this->id;
84+
$sql = "UPDATE shell_user SET server_id = $server_id, dir = '$dir', puser = '$puser', pgroup = '$pgroup' WHERE shell_user_id = ".$this->id;
8685
$app->db->query($sql);
8786

8887
}

server/plugins-available/apache2_plugin.inc.php

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -382,30 +382,38 @@ function update($event_name,$data) {
382382

383383
if ($data["new"]["php"] == "fast-cgi")
384384
{
385-
$fastcgi_starter_path = str_replace("[system_user]",$data["new"]["system_user"],$web_config["fastcgi_starter_path"]);
385+
$fastcgi_config = $app->getconf->get_server_config($conf["server_id"], 'fastcgi');
386+
387+
$fastcgi_starter_path = str_replace("[system_user]",$data["new"]["system_user"],$fastcgi_config["fastcgi_starter_path"]);
386388
if (!is_dir($fastcgi_starter_path))
387389
{
388-
exec("mkdir $fastcgi_starter_path");
390+
exec("mkdir -p $fastcgi_starter_path");
389391
exec("chown ".$data["new"]["system_user"].":".$data["new"]["system_group"]." $fastcgi_starter_path");
392+
393+
394+
$app->log("Creating fastcgi starter script directory: $fastcgi_starter_path",LOGLEVEL_DEBUG);
390395
}
391396

392397
$fcgi_tpl = new tpl();
393398
$fcgi_tpl->newTemplate("php-fcgi-starter.master");
394399

395-
$fcgi_tpl->setVar('php_ini_path',$web_config["fastcgi_phpini_path"]);
400+
$fcgi_tpl->setVar('php_ini_path',$fastcgi_config["fastcgi_phpini_path"]);
396401
$fcgi_tpl->setVar('document_root',$data["new"]["document_root"]);
397-
$fcgi_tpl->setVar('php_fcgi_children',$web_config["fastcgi_children"]);
398-
$fcgi_tpl->setVar('php_fcgi_max_requests',$web_config["fastcgi_max_requests"]);
399-
$fcgi_tpl->setVar('php_fcgi_bin',$web_config["fastcgi_bin"]);
402+
$fcgi_tpl->setVar('php_fcgi_children',$fastcgi_config["fastcgi_children"]);
403+
$fcgi_tpl->setVar('php_fcgi_max_requests',$fastcgi_config["fastcgi_max_requests"]);
404+
$fcgi_tpl->setVar('php_fcgi_bin',$fastcgi_config["fastcgi_bin"]);
400405

401-
$fcgi_starter_script = escapeshellcmd($fastcgi_starter_path."/".$web_config["fastcgi_starter_script"]);
406+
$fcgi_starter_script = escapeshellcmd($fastcgi_starter_path."/".$fastcgi_config["fastcgi_starter_script"]);
402407
file_put_contents($fcgi_starter_script,$fcgi_tpl->grab());
403408
unset($fcgi_tpl);
404409

410+
$app->log("Creating fastcgi starter script: $fcgi_starter_script",LOGLEVEL_DEBUG);
411+
412+
405413
exec("chmod 755 $fcgi_starter_script");
406414
exec("chown ".$data["new"]["system_user"].":".$data["new"]["system_group"]." $fcgi_starter_script");
407415

408-
$tpl->setVar('fastcgi_alias',$web_config["fastcgi_alias"]);
416+
$tpl->setVar('fastcgi_alias',$fastcgi_config["fastcgi_alias"]);
409417
$tpl->setVar('fastcgi_starter_path',$fastcgi_starter_path);
410418

411419
}
@@ -500,6 +508,10 @@ function delete($event_name,$data) {
500508
if($data["old"]["domain"] != '' && !stristr($vhost_logfile_dir,'..')) exec("rm -rf $vhost_logfile_dir");
501509
$app->log("Removing website logfile directory: $vhost_logfile_dir",LOGLEVEL_DEBUG);
502510

511+
//delete the web user
512+
$command = 'userdel';
513+
$command .= ' '.$data["old"]["system_user"];
514+
exec($command);
503515
}
504516

505517
//* This function is called when a IP on the server is inserted, updated or deleted

server/plugins-available/shelluser_plugin.inc.php renamed to server/plugins-available/shelluser_base_plugin.inc.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@
2828
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2929
*/
3030

31-
class shelluser_plugin {
31+
class shelluser_base_plugin {
3232

33-
var $plugin_name = 'shelluser_plugin';
34-
var $class_name = 'shelluser_plugin';
33+
var $plugin_name = 'shelluser_base_plugin';
34+
var $class_name = 'shelluser_base_plugin';
3535

3636

3737
/*
@@ -102,7 +102,6 @@ function update($event_name,$data) {
102102
} else {
103103
$app->log("UID = $uid for shelluser:".$data['new']['username']." not allowed.",LOGLEVEL_ERROR);
104104
}
105-
106105
}
107106

108107
function delete($event_name,$data) {
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
<?php
2+
3+
/*
4+
Copyright (c) 2008, Till Brehm, projektfarm Gmbh
5+
All rights reserved.
6+
7+
Redistribution and use in source and binary forms, with or without modification,
8+
are permitted provided that the following conditions are met:
9+
10+
* Redistributions of source code must retain the above copyright notice,
11+
this list of conditions and the following disclaimer.
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
* Neither the name of ISPConfig nor the names of its contributors
16+
may be used to endorse or promote products derived from this software without
17+
specific prior written permission.
18+
19+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22+
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
class shelluser_jailkit_plugin {
32+
33+
//* $plugin_name and $class_name have to be the same then the name of this class
34+
var $plugin_name = 'shelluser_jailkit_plugin';
35+
var $class_name = 'shelluser_jailkit_plugin';
36+
37+
38+
/*
39+
This function is called when the plugin is loaded
40+
*/
41+
42+
function onLoad() {
43+
global $app;
44+
45+
/*
46+
Register for the events
47+
*/
48+
49+
$app->plugins->registerEvent('shell_user_insert',$this->plugin_name,'insert');
50+
$app->plugins->registerEvent('shell_user_update',$this->plugin_name,'update');
51+
$app->plugins->registerEvent('shell_user_delete',$this->plugin_name,'delete');
52+
53+
54+
}
55+
56+
//* This function is called, when a shell user is inserted in the database
57+
function insert($event_name,$data) {
58+
global $app, $conf;
59+
60+
/**
61+
* Setup Jailkit Chroot System If Enabled
62+
*/
63+
if ($data['new']['chroot'] == "jailkit")
64+
{
65+
// load the server configuration options
66+
$app->uses("getconf");
67+
$this->data = $data;
68+
$this->app = $app;
69+
$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
70+
71+
$this->_setup_jailkit_chroot();
72+
$this->_add_jailkit_user();
73+
}
74+
75+
$app->log("Jalikit Plugin -> insert username:".$data['new']['username'],LOGLEVEL_DEBUG);
76+
77+
}
78+
79+
//* This function is called, when a shell user is updated in the database
80+
function update($event_name,$data) {
81+
global $app, $conf;
82+
83+
/**
84+
* Setup Jailkit Chroot System If Enabled
85+
*/
86+
if ($data['new']['chroot'] == "jailkit")
87+
{
88+
// load the server configuration options
89+
$app->uses("getconf");
90+
$this->data = $data;
91+
$this->app = $app;
92+
$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
93+
94+
$this->_setup_jailkit_chroot();
95+
$this->_add_jailkit_user();
96+
}
97+
98+
$app->log("Jalikit Plugin -> update username:".$data['new']['username'],LOGLEVEL_DEBUG);
99+
100+
}
101+
102+
//* This function is called, when a shell user is deleted in the database
103+
function delete($event_name,$data) {
104+
global $app, $conf;
105+
106+
if ($data['old']['chroot'] == "jailkit")
107+
{
108+
$app->uses("getconf");
109+
$this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
110+
111+
$jailkit_chroot_userhome = $this->_get_home_dir($data['old']['username']);
112+
113+
exec('rm -rf '.$data['old']['dir'].$jailkit_chroot_userhome);
114+
115+
116+
$app->log("Jalikit Plugin -> delete chroot home:".$data['old']['dir'].$jailkit_chroot_userhome,LOGLEVEL_DEBUG);
117+
}
118+
119+
$app->log("Jalikit Plugin -> delete username:".$data['old']['username'],LOGLEVEL_DEBUG);
120+
121+
122+
}
123+
124+
function _setup_jailkit_chroot()
125+
{
126+
//check if the chroot environment is created yet if not create it with a list of program sections from the config
127+
if (!is_dir($this->data['new']['dir'].'/etc/jailkit'))
128+
{
129+
$command = '/usr/local/ispconfig/server/scripts/create_jailkit_chroot.sh';
130+
$command .= ' '.escapeshellcmd($this->data['new']['dir']);
131+
$command .= ' \''.$this->jailkit_config['jailkit_chroot_app_sections'].'\'';
132+
exec($command);
133+
134+
$this->app->log("Added jailkit chroot with command: ".$command,LOGLEVEL_DEBUG);
135+
136+
$this->_add_jailkit_programs();
137+
138+
139+
}
140+
}
141+
142+
function _add_jailkit_programs()
143+
{
144+
//copy over further programs and its libraries
145+
$command = '/usr/local/ispconfig/server/scripts/create_jailkit_programs.sh';
146+
$command .= ' '.escapeshellcmd($this->data['new']['dir']);
147+
$command .= ' \''.$this->jailkit_config['jailkit_chroot_app_programs'].'\'';
148+
exec($command);
149+
150+
$this->app->log("Added programs to jailkit chroot with command: ".$command,LOGLEVEL_DEBUG);
151+
}
152+
153+
function _get_home_dir($username)
154+
{
155+
return str_replace("[username]",escapeshellcmd($username),$this->jailkit_config["jailkit_chroot_home"]);
156+
}
157+
158+
function _add_jailkit_user()
159+
{
160+
//add the user to the chroot
161+
$jailkit_chroot_userhome = $this->_get_home_dir($this->data['new']['username']);
162+
$jailkit_chroot_puserhome = $this->_get_home_dir($this->data['new']['puser']);
163+
164+
if (!is_dir($this->data['new']['dir'].$jailkit_chroot_userhome))
165+
{
166+
$command = '/usr/local/ispconfig/server/scripts/create_jailkit_user.sh';
167+
$command .= ' '.escapeshellcmd($this->data['new']['username']);
168+
$command .= ' '.escapeshellcmd($this->data['new']['dir']);
169+
$command .= ' '.$jailkit_chroot_userhome;
170+
$command .= ' '.escapeshellcmd($this->data['new']['shell']);
171+
$command .= ' '.$this->data['new']['puser'];
172+
$command .= ' '.$jailkit_chroot_puserhome;
173+
exec($command);
174+
175+
$this->app->log("Added jailkit user to chroot with command: ".$command,LOGLEVEL_DEBUG);
176+
177+
exec("mkdir -p ".$this->data['new']['dir'].$jailkit_chroot_userhome);
178+
exec("chown ".$this->data['new']['username'].":".$this->data['new']['pgroup']." ".$this->data['new']['dir'].$jailkit_chroot_userhome);
179+
180+
$this->app->log("Added created jailkit user home in : ".$this->data['new']['dir'].$jailkit_chroot_userhome,LOGLEVEL_DEBUG);
181+
182+
exec("mkdir -p ".$this->data['new']['dir'].$jailkit_chroot_puserhome);
183+
exec("chown ".$this->data['new']['puser'].":".$this->data['new']['pgroup']." ".$this->data['new']['dir'].$jailkit_chroot_puserhome);
184+
185+
$this->app->log("Added created jailkit parent user home in : ".$this->data['new']['dir'].$jailkit_chroot_puserhome,LOGLEVEL_DEBUG);
186+
}
187+
}
188+
189+
190+
191+
} // end class
192+
193+
?>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/bash
2+
3+
# Create the jailkit chroot
4+
5+
#
6+
# Usage: ./create_jailkit_chroot username 'basicshell editors'
7+
#
8+
9+
10+
# Sanity check
11+
12+
if [ "$1" = "" ]; then
13+
echo " Usage: ./create_jailkit_chroot username 'basicshell editors'"
14+
exit
15+
fi
16+
17+
CHROOT_HOMEDIR=$1
18+
CHROOT_APP_SECTIONS=$2
19+
20+
## Change ownership of the chroot directory to root
21+
chown root:root $CHROOT_HOMEDIR
22+
23+
## Initialize the chroot into the specified directory with the specified applications
24+
jk_init -f -k -j $CHROOT_HOMEDIR $CHROOT_APP_SECTIONS
25+
26+
## Create the temp directory
27+
mkdir $CHROOT_HOMEDIR/tmp
28+
chmod a+rwx $CHROOT_HOMEDIR/tmp
29+
30+
31+
# mysql needs the socket in the chrooted environment
32+
mkdir $CHROOT_HOMEDIR/var
33+
mkdir $CHROOT_HOMEDIR/var/run
34+
mkdir $CHROOT_HOMEDIR/var/run/mysqld
35+
ln /var/run/mysqld/mysqld.sock $CHROOT_HOMEDIR/var/run/mysqld/mysqld.sock
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
# Add specified programs and their libraries to the jailkit chroot
4+
5+
#
6+
# Usage: ./create_jailkit_programs /path/to/chroot '/usr/bin/program'
7+
#
8+
9+
# Sanity check
10+
11+
if [ "$1" = "" ]; then
12+
echo " Usage: ./create_jailkit_programs /path/to/chroot '/usr/bin/program'"
13+
exit
14+
fi
15+
16+
17+
CHROOT_HOMEDIR=$1
18+
CHROOT_APP_PROGRAMS=$2
19+
20+
jk_cp -k $CHROOT_HOMEDIR $CHROOT_APP_PROGRAMS

0 commit comments

Comments
 (0)