Skip to content

Commit c3ac0a4

Browse files
committed
Added wrappers for several base filesystem functions like rename, copy, chown, chgrp etc. to system lib.
1 parent 3a21710 commit c3ac0a4

File tree

1 file changed

+100
-16
lines changed

1 file changed

+100
-16
lines changed

server/lib/classes/system.inc.php

Lines changed: 100 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -610,18 +610,89 @@ function get_user_attributes($user){
610610
* Edit the owner of a file
611611
*
612612
*/
613-
function chown($file, $owner, $group = ''){
614-
$owner_change = @chown($file, $owner);
615-
if($group != ''){
616-
$group_change = @chgrp($file, $group);
617-
} else {
618-
$group_change = 1;
613+
function chown($file, $owner, $allow_symlink = false){
614+
if($allow_symlink == false && $this->checkpath($file) == false) {
615+
$app->log("Action aborted, file is a symlink: $file",LOGLEVEL_WARN);
616+
return false;
619617
}
620-
if($owner_change && $group_change){
621-
return true;
622-
} else {
623-
return false;
618+
return chown($file, $owner);
619+
}
620+
621+
function chgrp($file, $group = '', $allow_symlink = false){
622+
if($allow_symlink == false && $this->checkpath($file) == false) {
623+
$app->log("Action aborted, file is a symlink: $file",LOGLEVEL_WARN);
624+
return false;
624625
}
626+
return chgrp($file, $group);
627+
}
628+
629+
//* Change the mode of a file
630+
function chmod($file, $mode, $allow_symlink = false) {
631+
if($allow_symlink == false && $this->checkpath($file) == false) {
632+
$app->log("Action aborted, file is a symlink: $file",LOGLEVEL_WARN);
633+
return false;
634+
}
635+
return chmod($file, $mode);
636+
}
637+
638+
function file_put_contents($filename, $data, $allow_symlink = false) {
639+
if($allow_symlink == false && $this->checkpath($filename) == false) {
640+
$app->log("Action aborted, file is a symlink: $filename",LOGLEVEL_WARN);
641+
return false;
642+
}
643+
unlink($filename);
644+
return file_put_contents($filename, $data);
645+
}
646+
647+
function file_get_contents($filename, $allow_symlink = false) {
648+
if($allow_symlink == false && $this->checkpath($filename) == false) {
649+
$app->log("Action aborted, file is a symlink: $filename",LOGLEVEL_WARN);
650+
return false;
651+
}
652+
return file_put_contents($filename, $data);
653+
}
654+
655+
function rename($filename, $new_filename, $allow_symlink = false) {
656+
if($allow_symlink == false && $this->checkpath($filename) == false) {
657+
$app->log("Action aborted, file is a symlink: $filename",LOGLEVEL_WARN);
658+
return false;
659+
}
660+
return rename($filename, $new_filename);
661+
}
662+
663+
function mkdir($dirname, $allow_symlink = false) {
664+
if($allow_symlink == false && $this->checkpath($dirname) == false) {
665+
$app->log("Action aborted, file is a symlink: $dirname",LOGLEVEL_WARN);
666+
return false;
667+
}
668+
return mkdir($dirname);
669+
}
670+
671+
function unlink($file) {
672+
return unlink($file);
673+
}
674+
675+
function copy($file1,$file2) {
676+
return copy($file1,$file2);
677+
}
678+
679+
function checkpath($path) {
680+
$path = trim($path);
681+
//* We allow only absolute paths
682+
if(substr($path,0,1) != '/') return false;
683+
684+
//* We allow only some characters in the path
685+
if(!preg_match('/[a-zA-Z0-9_\.\-]{1,}/',$path)) return false;
686+
687+
//* Check path for symlinks
688+
$path_parts = explode($path);
689+
$testpath = '';
690+
foreach($path_parts as $p) {
691+
$testpath .= '/'.$p;
692+
if(is_link($testpath)) return false;
693+
}
694+
695+
return true;
625696
}
626697

627698
/**
@@ -1132,6 +1203,10 @@ function get_time(){
11321203
}
11331204

11341205
function replaceLine($filename,$search_pattern,$new_line,$strict = 0,$append = 1) {
1206+
if($this->checkpath($filename) == false) {
1207+
$app->log("Action aborted, file is a symlink: $filename",LOGLEVEL_WARN);
1208+
return false;
1209+
}
11351210
$lines = @file($filename);
11361211
$out = '';
11371212
$found = 0;
@@ -1167,6 +1242,10 @@ function replaceLine($filename,$search_pattern,$new_line,$strict = 0,$append = 1
11671242
}
11681243

11691244
function removeLine($filename,$search_pattern,$strict = 0) {
1245+
if($this->checkpath($filename) == false) {
1246+
$app->log("Action aborted, file is a symlink: $filename",LOGLEVEL_WARN);
1247+
return false;
1248+
}
11701249
if($lines = @file($filename)) {
11711250
$out = '';
11721251
foreach($lines as $line) {
@@ -1200,8 +1279,8 @@ function maildirmake($maildir_path, $user = '', $subfolder = '') {
12001279
$user = escapeshellcmd($user);
12011280
// I assume that the name of the (vmail group) is the same as the name of the mail user in ISPConfig 3
12021281
$group = $user;
1203-
if(is_dir($dir)) chown($dir,$user);
1204-
if(is_dir($dir)) chgrp($dir,$group);
1282+
if(is_dir($dir)) $this->chown($dir,$user);
1283+
if(is_dir($dir)) $this->chgrp($dir,$group);
12051284

12061285
$chown_mdsub = true;
12071286
}
@@ -1262,10 +1341,10 @@ function mkdirpath($path, $mode = 0755, $user = '', $group = '') {
12621341
foreach($path_parts as $part) {
12631342
$new_path .= '/'.$part;
12641343
if(!@is_dir($new_path)) {
1265-
mkdir($new_path);
1266-
chmod($new_path,$mode);
1267-
if($user != '') chown($new_path,$user);
1268-
if($group != '') chgrp($new_path,$group);
1344+
$this->mkdir($new_path);
1345+
$this->chmod($new_path,$mode);
1346+
if($user != '') $this->chown($new_path,$user);
1347+
if($group != '') $this->chgrp($new_path,$group);
12691348
}
12701349
}
12711350
}
@@ -1285,6 +1364,11 @@ function is_installed($appname) {
12851364
function web_folder_protection($document_root,$protect) {
12861365
global $app,$conf;
12871366

1367+
if($this->checkpath($document_root) == false) {
1368+
$app->log("Action aborted, target is a symlink: $document_root",LOGLEVEL_DEBUG);
1369+
return false;
1370+
}
1371+
12881372
//* load the server configuration options
12891373
$app->uses('getconf');
12901374
$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');

0 commit comments

Comments
 (0)