Marius Cramer
2014-08-13 31230cb7cda673db7a96fb14d93dfaf9262c74cf
commit | author | age
396f0e 1 <?php
T 2
3 /*
4 Copyright (c) 2007, 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 {
7fe908 32
396f0e 33     //* $plugin_name and $class_name have to be the same then the name of this class
T 34     var $plugin_name = 'shelluser_jailkit_plugin';
35     var $class_name = 'shelluser_jailkit_plugin';
b79d24 36     var $min_uid = 499;
7fe908 37
396f0e 38     //* This function is called during ispconfig installation to determine
T 39     //  if a symlink shall be created for this plugin.
40     function onInstall() {
41         global $conf;
7fe908 42
396f0e 43         if($conf['services']['web'] == true) {
T 44             return true;
45         } else {
46             return false;
47         }
7fe908 48
396f0e 49     }
7fe908 50
MC 51
396f0e 52     /*
T 53          This function is called when the plugin is loaded
54     */
7fe908 55
396f0e 56     function onLoad() {
T 57         global $app;
7fe908 58
396f0e 59         /*
T 60         Register for the events
61         */
62
7fe908 63         $app->plugins->registerEvent('shell_user_insert', $this->plugin_name, 'insert');
MC 64         $app->plugins->registerEvent('shell_user_update', $this->plugin_name, 'update');
65         $app->plugins->registerEvent('shell_user_delete', $this->plugin_name, 'delete');
66
67
396f0e 68     }
7fe908 69
396f0e 70     //* This function is called, when a shell user is inserted in the database
7fe908 71     function insert($event_name, $data) {
396f0e 72         global $app, $conf;
7fe908 73
396f0e 74         $app->uses('system');
ff6a68 75         $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$data['new']['parent_domain_id']);
7fe908 76
b79d24 77         if($app->system->is_user($data['new']['puser'])) {
FT 78             // Get the UID of the parent user
79             $uid = intval($app->system->getuid($data['new']['puser']));
80             if($uid > $this->min_uid) {
81             
82                 if($app->system->is_user($data['new']['username'])) {
7fe908 83
b79d24 84                     /**
FT 85                     * Setup Jailkit Chroot System If Enabled
86                     */
87
88                     if ($data['new']['chroot'] == "jailkit")
89                     {
7fe908 90
MC 91
b79d24 92                         // load the server configuration options
FT 93                         $app->uses("getconf");
94                         $this->data = $data;
95                         $this->app = $app;
96                         $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
7fe908 97
b79d24 98                         $this->_update_website_security_level();
7fe908 99
b79d24 100                         $app->system->web_folder_protection($web['document_root'], false);
7fe908 101
b79d24 102                         $this->_setup_jailkit_chroot();
7fe908 103
b79d24 104                         $this->_add_jailkit_user();
7fe908 105
b79d24 106                         //* call the ssh-rsa update function
FT 107                         $this->_setup_ssh_rsa();
7fe908 108
b79d24 109                         //$command .= 'usermod -s /usr/sbin/jk_chrootsh -U '.escapeshellcmd($data['new']['username']);
FT 110                         //exec($command);
111                         $app->system->usermod($data['new']['username'], 0, 0, '', '/usr/sbin/jk_chrootsh', '', '');
7fe908 112
b79d24 113                         //* Unlock user
FT 114                         $command = 'usermod -U '.escapeshellcmd($data['new']['username']).' 2>/dev/null';
115                         exec($command);
7fe908 116
b79d24 117                         $this->_update_website_security_level();
FT 118                         $app->system->web_folder_protection($web['document_root'], true);
119                     }
7fe908 120
b79d24 121                     $app->log("Jailkit Plugin -> insert username:".$data['new']['username'], LOGLEVEL_DEBUG);
7fe908 122
b79d24 123                 } else {
FT 124                     $app->log("Jailkit Plugin -> insert username:".$data['new']['username']." skipped, the user does not exist.", LOGLEVEL_WARN);
125                 }
126             } else {
127                 $app->log("UID = $uid for shelluser:".$data['new']['username']." not allowed.", LOGLEVEL_ERROR);
396f0e 128             }
T 129         } else {
b79d24 130             $app->log("Skipping insertion of user:".$data['new']['username'].", parent user ".$data['new']['puser']." does not exist.", LOGLEVEL_WARN);
396f0e 131         }
7fe908 132
396f0e 133     }
7fe908 134
396f0e 135     //* This function is called, when a shell user is updated in the database
7fe908 136     function update($event_name, $data) {
396f0e 137         global $app, $conf;
7fe908 138
396f0e 139         $app->uses('system');
ff6a68 140         $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$data['new']['parent_domain_id']);
7fe908 141
b79d24 142         if($app->system->is_user($data['new']['puser'])) {
FT 143             // Get the UID of the parent user
144             $uid = intval($app->system->getuid($data['new']['puser']));
145             if($uid > $this->min_uid) {
146             
147             
148                 if($app->system->is_user($data['new']['username'])) {
7fe908 149
b79d24 150                     /**
FT 151                     * Setup Jailkit Chroot System If Enabled
152                     */
153                     if ($data['new']['chroot'] == "jailkit")
154                     {
7fe908 155
b79d24 156                         // load the server configuration options
FT 157                         $app->uses("getconf");
158                         $this->data = $data;
159                         $this->app = $app;
160                         $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
7fe908 161
b79d24 162                         $this->_update_website_security_level();
7fe908 163
b79d24 164                         $app->system->web_folder_protection($web['document_root'], false);
7fe908 165
b79d24 166                         $this->_setup_jailkit_chroot();
FT 167                         $this->_add_jailkit_user();
7fe908 168
b79d24 169                         //* call the ssh-rsa update function
FT 170                         $this->_setup_ssh_rsa();
7fe908 171
b79d24 172                         $this->_update_website_security_level();
7fe908 173
b79d24 174                         $app->system->web_folder_protection($web['document_root'], true);
FT 175                     }
7fe908 176
b79d24 177                     $app->log("Jailkit Plugin -> update username:".$data['new']['username'], LOGLEVEL_DEBUG);
7fe908 178
b79d24 179                 } else {
FT 180                     $app->log("Jailkit Plugin -> update username:".$data['new']['username']." skipped, the user does not exist.", LOGLEVEL_WARN);
181                 }
182             } else {
183                 $app->log("UID = $uid for shelluser:".$data['new']['username']." not allowed.", LOGLEVEL_ERROR);
396f0e 184             }
T 185         } else {
b79d24 186             $app->log("Skipping update for user:".$data['new']['username'].", parent user ".$data['new']['puser']." does not exist.", LOGLEVEL_WARN);
396f0e 187         }
7fe908 188
396f0e 189     }
7fe908 190
396f0e 191     //* This function is called, when a shell user is deleted in the database
T 192     /**
193      * TODO: Remove chroot user home and from the chroot passwd file
7fe908 194      */
MC 195     function delete($event_name, $data) {
396f0e 196         global $app, $conf;
7fe908 197
396f0e 198         $app->uses('system');
7fe908 199
ff6a68 200         $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$data['old']['parent_domain_id']);
7fe908 201
396f0e 202         if ($data['old']['chroot'] == "jailkit")
T 203         {
204             $app->uses("getconf");
205             $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit');
7fe908 206
396f0e 207             $jailkit_chroot_userhome = $this->_get_home_dir($data['old']['username']);
7fe908 208
396f0e 209             //commented out proved to be dangerous on config errors
T 210             //exec('rm -rf '.$data['old']['dir'].$jailkit_chroot_userhome);
7fe908 211
MC 212             $app->system->web_folder_protection($web['document_root'], false);
213
396f0e 214             if(@is_dir($data['old']['dir'].$jailkit_chroot_userhome)) {
8cf78b 215                 $command = 'userdel -f';
526b99 216                 $command .= ' '.escapeshellcmd($data['old']['username']).' &> /dev/null';
396f0e 217                 exec($command);
7fe908 218                 $app->log("Jailkit Plugin -> delete chroot home:".$data['old']['dir'].$jailkit_chroot_userhome, LOGLEVEL_DEBUG);
396f0e 219             }
7fe908 220
MC 221             $app->system->web_folder_protection($web['document_root'], true);
222
396f0e 223         }
7fe908 224
MC 225         $app->log("Jailkit Plugin -> delete username:".$data['old']['username'], LOGLEVEL_DEBUG);
226
227
396f0e 228     }
7fe908 229
396f0e 230     function _setup_jailkit_chroot()
T 231     {
7fe908 232         global $app;
MC 233
234         //check if the chroot environment is created yet if not create it with a list of program sections from the config
235         if (!is_dir($this->data['new']['dir'].'/etc/jailkit'))
236         {
237             $command = '/usr/local/ispconfig/server/scripts/create_jailkit_chroot.sh';
238             $command .= ' '.escapeshellcmd($this->data['new']['dir']);
239             $command .= ' \''.$this->jailkit_config['jailkit_chroot_app_sections'].'\'';
240             exec($command.' 2>/dev/null');
241
242             $this->app->log("Added jailkit chroot with command: ".$command, LOGLEVEL_DEBUG);
243
244             $this->_add_jailkit_programs();
245
246             //add bash.bashrc script
247             //we need to collect the domain name to be used as the HOSTNAME in the bashrc script
248             $web = $this->app->db->queryOneRecord("SELECT domain FROM web_domain WHERE domain_id = ".intval($this->data['new']["parent_domain_id"]));
249
250             $this->app->load('tpl');
251
252             $tpl = new tpl();
253             $tpl->newTemplate("bash.bashrc.master");
254
255             $tpl->setVar('jailkit_chroot', true);
256             $tpl->setVar('domain', $web['domain']);
257             $tpl->setVar('home_dir', $this->_get_home_dir(""));
258
259             $bashrc = escapeshellcmd($this->data['new']['dir']).'/etc/bash.bashrc';
260             if(@is_file($bashrc) || @is_link($bashrc)) unlink($bashrc);
261
262             file_put_contents($bashrc, $tpl->grab());
263             unset($tpl);
264
265             $this->app->log("Added bashrc script : ".$bashrc, LOGLEVEL_DEBUG);
266
267             $tpl = new tpl();
268             $tpl->newTemplate("motd.master");
269
270             $tpl->setVar('domain', $web['domain']);
271
272             $motd = escapeshellcmd($this->data['new']['dir']).'/var/run/motd';
273             if(@is_file($motd) || @is_link($motd)) unlink($motd);
274
275             $app->system->file_put_contents($motd, $tpl->grab());
276
277         }
396f0e 278     }
7fe908 279
396f0e 280     function _add_jailkit_programs()
T 281     {
282         //copy over further programs and its libraries
283         $command = '/usr/local/ispconfig/server/scripts/create_jailkit_programs.sh';
284         $command .= ' '.escapeshellcmd($this->data['new']['dir']);
285         $command .= ' \''.$this->jailkit_config['jailkit_chroot_app_programs'].'\'';
526b99 286         exec($command.' 2>/dev/null');
7fe908 287
MC 288         $this->app->log("Added programs to jailkit chroot with command: ".$command, LOGLEVEL_DEBUG);
396f0e 289     }
7fe908 290
396f0e 291     function _get_home_dir($username)
T 292     {
7fe908 293         return str_replace("[username]", escapeshellcmd($username), $this->jailkit_config['jailkit_chroot_home']);
396f0e 294     }
7fe908 295
396f0e 296     function _add_jailkit_user()
T 297     {
7fe908 298         global $app;
MC 299
300         //add the user to the chroot
301         $jailkit_chroot_userhome = $this->_get_home_dir($this->data['new']['username']);
302         $jailkit_chroot_puserhome = $this->_get_home_dir($this->data['new']['puser']);
303
304         if(!is_dir($this->data['new']['dir'].'/etc')) mkdir($this->data['new']['dir'].'/etc', 0755);
305         if(!is_file($this->data['new']['dir'].'/etc/passwd')) touch($this->data['new']['dir'].'/etc/passwd', 0755);
306
307         // IMPORTANT!
308         // ALWAYS create the user. Even if the user was created before
309         // if we check if the user exists, then a update (no shell -> jailkit) will not work
310         // and the user has FULL ACCESS to the root of the server!
311         $command = '/usr/local/ispconfig/server/scripts/create_jailkit_user.sh';
312         $command .= ' '.escapeshellcmd($this->data['new']['username']);
313         $command .= ' '.escapeshellcmd($this->data['new']['dir']);
314         $command .= ' '.$jailkit_chroot_userhome;
315         $command .= ' '.escapeshellcmd($this->data['new']['shell']);
316         $command .= ' '.$this->data['new']['puser'];
317         $command .= ' '.$jailkit_chroot_puserhome;
318         exec($command.' 2>/dev/null');
319
320         //* Change the homedir of the shell user and parent user
321         //* We have to do this manually as the usermod command fails
322         //* when the user is logged in or a command is running under that user
323         /*
8cf78b 324             $passwd_file_array = file('/etc/passwd');
T 325             $passwd_out = '';
326             if(is_array($passwd_file_array)) {
327                 foreach($passwd_file_array as $line) {
328                     $line = trim($line);
329                     $parts = explode(':',$line);
330                     if($parts[0] == $this->data['new']['username']) {
331                         $parts[5] = escapeshellcmd($this->data['new']['dir'].'/.'.$jailkit_chroot_userhome);
332                         $parts[6] = escapeshellcmd('/usr/sbin/jk_chrootsh');
333                         $new_line = implode(':',$parts);
334                         copy('/etc/passwd','/etc/passwd~');
335                         chmod('/etc/passwd~',0600);
336                         $app->uses('system');
337                         $app->system->replaceLine('/etc/passwd',$line,$new_line,1,0);
338                     }
339                 }
ff6a68 340             }*/
7fe908 341
MC 342         $app->system->usermod($this->data['new']['username'], 0, 0, $this->data['new']['dir'].'/.'.$jailkit_chroot_userhome, '/usr/sbin/jk_chrootsh');
343         $app->system->usermod($this->data['new']['puser'], 0, 0, $this->data['new']['dir'].'/.'.$jailkit_chroot_userhome, '/usr/sbin/jk_chrootsh');
344
345         $this->app->log("Added jailkit user to chroot with command: ".$command, LOGLEVEL_DEBUG);
346
347         if(!is_dir($this->data['new']['dir'].$jailkit_chroot_userhome)) mkdir(escapeshellcmd($this->data['new']['dir'].$jailkit_chroot_userhome), 0755, true);
348         $app->system->chown(escapeshellcmd($this->data['new']['dir'].$jailkit_chroot_userhome), $this->data['new']['username']);
349         $app->system->chgrp(escapeshellcmd($this->data['new']['dir'].$jailkit_chroot_userhome), $this->data['new']['pgroup']);
350
351         $this->app->log("Added created jailkit user home in : ".$this->data['new']['dir'].$jailkit_chroot_userhome, LOGLEVEL_DEBUG);
352
353         if(!is_dir($this->data['new']['dir'].$jailkit_chroot_puserhome)) mkdir(escapeshellcmd($this->data['new']['dir'].$jailkit_chroot_puserhome), 0755, true);
354         $app->system->chown(escapeshellcmd($this->data['new']['dir'].$jailkit_chroot_puserhome), $this->data['new']['puser']);
355         $app->system->chgrp(escapeshellcmd($this->data['new']['dir'].$jailkit_chroot_puserhome), $this->data['new']['pgroup']);
356
357         $this->app->log("Added jailkit parent user home in : ".$this->data['new']['dir'].$jailkit_chroot_puserhome, LOGLEVEL_DEBUG);
358
8cf78b 359
396f0e 360     }
7fe908 361
8db8f3 362     //* Update the website root directory permissions depending on the security level
T 363     function _update_website_security_level() {
7fe908 364         global $app, $conf;
MC 365
8db8f3 366         // load the server configuration options
T 367         $app->uses("getconf");
368         $web_config = $app->getconf->get_server_config($conf["server_id"], 'web');
7fe908 369
8db8f3 370         // Get the parent website of this shell user
T 371         $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$this->data['new']['parent_domain_id']);
7fe908 372
8db8f3 373         //* If the security level is set to high
ff6a68 374         if($web_config['security_level'] == 20 && is_array($web)) {
7fe908 375             $app->system->web_folder_protection($web["document_root"], false);
MC 376             $app->system->chmod($web["document_root"], 0755);
377             $app->system->chown($web["document_root"], 'root');
378             $app->system->chgrp($web["document_root"], 'root');
379             $app->system->web_folder_protection($web["document_root"], true);
8db8f3 380         }
7fe908 381
8db8f3 382     }
7fe908 383
07bdbd 384     //* Wrapper for exec function for easier debugging
T 385     private function _exec($command) {
386         global $app;
7fe908 387         $app->log('exec: '.$command, LOGLEVEL_DEBUG);
07bdbd 388         exec($command);
T 389     }
396f0e 390
00a055 391     private function _setup_ssh_rsa() {
8ab3cd 392         global $app;
7fe908 393         $this->app->log("ssh-rsa setup shelluser_jailkit", LOGLEVEL_DEBUG);
00a055 394         // Get the client ID, username, and the key
27c623 395         $domain_data = $this->app->db->queryOneRecord('SELECT sys_groupid FROM web_domain WHERE web_domain.domain_id = '.intval($this->data['new']['parent_domain_id']));
L 396         $sys_group_data = $this->app->db->queryOneRecord('SELECT * FROM sys_group WHERE sys_group.groupid = '.intval($domain_data['sys_groupid']));
00a055 397         $id = intval($sys_group_data['client_id']);
L 398         $username= $sys_group_data['name'];
27c623 399         $client_data = $this->app->db->queryOneRecord('SELECT * FROM client WHERE client.client_id = '.$id);
00a055 400         $userkey = $client_data['ssh_rsa'];
L 401         unset($domain_data);
402         unset($client_data);
7fe908 403
00a055 404         // ssh-rsa authentication variables
8ab3cd 405         $sshrsa = $this->data['new']['ssh_rsa'];
00a055 406         $usrdir = escapeshellcmd($this->data['new']['dir']).'/'.$this->_get_home_dir($this->data['new']['username']);
8ab3cd 407         $sshdir = $usrdir.'/.ssh';
T 408         $sshkeys= $usrdir.'/.ssh/authorized_keys';
7fe908 409
8ab3cd 410         $app->uses('file');
T 411         $sshrsa = $app->file->unix_nl($sshrsa);
7fe908 412         $sshrsa = $app->file->remove_blank_lines($sshrsa, 0);
MC 413
00a055 414         // If this user has no key yet, generate a pair
8ab3cd 415         if ($userkey == '' && $id > 0){
00a055 416             //Generate ssh-rsa-keys
L 417             exec('ssh-keygen -t rsa -C '.$username.'-rsa-key-'.time().' -f /tmp/id_rsa -N ""');
7fe908 418
8ab3cd 419             // use the public key that has been generated
4bd960 420             $userkey = $app->system->file_get_contents('/tmp/id_rsa.pub');
7fe908 421
00a055 422             // save keypair in client table
4bd960 423             $this->app->db->query("UPDATE client SET created_at = ".time().", id_rsa = '".$app->db->quote($app->system->file_get_contents('/tmp/id_rsa'))."', ssh_rsa = '".$app->db->quote($userkey)."' WHERE client_id = ".$id);
8ab3cd 424
4bd960 425             $app->system->unlink('/tmp/id_rsa');
T 426             $app->system->unlink('/tmp/id_rsa.pub');
7fe908 427             $this->app->log("ssh-rsa keypair generated for ".$username, LOGLEVEL_DEBUG);
00a055 428         };
7fe908 429
8ab3cd 430         if (!file_exists($sshkeys)){
00a055 431             // add root's key
8ab3cd 432             $app->file->mkdirs($sshdir, '0755');
4bd960 433             if(is_file('/root/.ssh/authorized_keys')) $app->system->file_put_contents($sshkeys, $app->system->file_get_contents('/root/.ssh/authorized_keys'));
7fe908 434
8ab3cd 435             // Remove duplicate keys
26c0fc 436             $existing_keys = @file($sshkeys);
8ab3cd 437             $new_keys = explode("\n", $userkey);
26c0fc 438             $final_keys_arr = @array_merge($existing_keys, $new_keys);
8ab3cd 439             $new_final_keys_arr = array();
T 440             if(is_array($final_keys_arr) && !empty($final_keys_arr)){
441                 foreach($final_keys_arr as $key => $val){
442                     $new_final_keys_arr[$key] = trim($val);
443                 }
444             }
445             $final_keys = implode("\n", array_flip(array_flip($new_final_keys_arr)));
7fe908 446
00a055 447             // add the user's key
8ab3cd 448             file_put_contents($sshkeys, $final_keys);
T 449             $app->file->remove_blank_lines($sshkeys);
7fe908 450             $this->app->log("ssh-rsa authorisation keyfile created in ".$sshkeys, LOGLEVEL_DEBUG);
00a055 451         }
8cf78b 452         //* Get the keys
T 453         $existing_keys = file($sshkeys);
454         $new_keys = explode("\n", $sshrsa);
7fe908 455         $old_keys = explode("\n", $this->data['old']['ssh_rsa']);
MC 456
8cf78b 457         //* Remove all old keys
T 458         if(is_array($old_keys)) {
459             foreach($old_keys as $key => $val) {
7fe908 460                 $k = array_search(trim($val), $existing_keys);
8cf78b 461                 unset($existing_keys[$k]);
T 462             }
00a055 463         }
7fe908 464
8cf78b 465         //* merge the remaining keys and the ones fom the ispconfig database.
T 466         if(is_array($new_keys)) {
467             $final_keys_arr = array_merge($existing_keys, $new_keys);
468         } else {
469             $final_keys_arr = $existing_keys;
470         }
7fe908 471
8cf78b 472         $new_final_keys_arr = array();
T 473         if(is_array($final_keys_arr) && !empty($final_keys_arr)){
474             foreach($final_keys_arr as $key => $val){
475                 $new_final_keys_arr[$key] = trim($val);
476             }
477         }
478         $final_keys = implode("\n", array_flip(array_flip($new_final_keys_arr)));
7fe908 479
MC 480         // add the custom key
4bd960 481         $app->system->file_put_contents($sshkeys, $final_keys);
8cf78b 482         $app->file->remove_blank_lines($sshkeys);
7fe908 483         $this->app->log("ssh-rsa key updated in ".$sshkeys, LOGLEVEL_DEBUG);
MC 484
00a055 485         // set proper file permissions
8cf78b 486         exec("chown -R ".escapeshellcmd($this->data['new']['puser']).":".escapeshellcmd($this->data['new']['pgroup'])." ".$sshdir);
T 487         exec("chmod 700 ".$sshdir);
00a055 488         exec("chmod 600 '$sshkeys'");
7fe908 489
00a055 490     }
7fe908 491
396f0e 492 } // end class
T 493
8e725d 494 ?>