--- docman.php 2002/07/27 19:45:28 1.7 +++ docman.php 2002/07/28 16:24:54 1.18 @@ -20,7 +20,7 @@ ////////////////////////////////////////////////////////////////// // CONFIGURATION OPTIONS -// error_reporting(4) ; // how verbose ? + error_reporting(E_ALL) ; // how verbose ? // from where to include auth_*.php modules? $gblIncDir = "/data/docman2"; @@ -84,7 +84,7 @@ LoadLanguage($HTTP_SERVER_VARS["HTTP_ACCEPT_LANGUAGE"]); // for security and configuration - $realm=$HTTP_SERVER_VARS[HTTP_HOST]; + $realm=$HTTP_SERVER_VARS["HTTP_HOST"]; $fsDocumentRoot = dirname($HTTP_SERVER_VARS[SCRIPT_FILENAME]); if ($fsDocumentRoot == "") Error("Configuration error","Can't get SCRIPT_FILENAME from your web server. Please set \$fsDocumentRoot in \$",1); @@ -118,7 +118,7 @@ if (file_exists("$fsDocumentRoot/docman.css")) { $css=dirname($self)."/docman.css"; } else { - $css=$self."?STYLE=get&css=$css"; + $css=$self."?STYLE=get"; } include("$html/head.html"); @@ -138,13 +138,18 @@ } else { $url .= md5($gblLogin.$gblPasswd); } - if (isset($gblLogin) && $gblLogin != "" && ($gblPasswd == "" || !isset($gblPasswd))) { + if ( ( (isset($gblLogin) && $gblLogin != "") || + (!isset($gblLogin) || $gblLogin == "") + ) && ($gblPasswd == "" || !isset($gblPasswd))) { $url_title="login"; $url .= "&force_login=1"; } else { $url_title="relogin"; } include("$html/footer.html"); + + global $debug; + if ($debug) print $debug; } // end function EndHTML ////////////////////////////////////////////////////////////////// @@ -160,14 +165,16 @@ $exists = file_exists($fsPath) ; $ext = strtolower(strrchr($relPath,".")) ; - $editable = ( $ext=="" || strstr(join(" ",$gblEditable),$ext)) ; - $writable = is_writeable($fsPath) ; + $editable = ( $ext=="" || strstr(join(" ",$gblEditable),$ext)) && + check_perm($relPath,trperm_w); + $writable = is_writeable($fsPath) && check_perm($relPath,trperm_w) ; + $writable_dir = is_writeable($fsDir) && check_perm($relDir,trperm_w) ; $file_lock = CheckLock($fsPath); if (!$editable && !$exists) - Error("Creation unsupported for type",$relPath) ; - if (!exists && !is_writeable($fsDir) ) - Error("Creation denied",$relDir) ; + Error("Creation denied","Can't create $relPath") ; + if (!$exists && !$writable_dir ) + Error("Creation denied","Can't write in directory $relDir while creating $relPathfor which user has permissions.",1); $text = _("Use this page to view, modify or ") ; if (is_dir($fsPath)) { @@ -200,7 +207,7 @@ $fstr = htmlentities( $fstr ) ; ?> -
+ DOCUMENT CONTENTS
@@ -571,16 +578,23 @@ function Navigate($fsRoot,$relDir) { global $gblEditable, $gblIcon, $gblModDays, $webRoot, $gblHide, - $gblIgnoreUnknownFileType, + $gblIgnoreUnknownFileType, $gblRepositoryDir, + $fsRealmDir, $realm, $realm_sep, $HTTP_GET_VARS, $html, $realm_config; - + $self = $HTTP_SERVER_VARS["PHP_SELF"] ; - if ($relDir == "") $relDir = "/"; + $relDir = chopsl($relDir)."/"; + $fsDir = $fsRoot.$relDir; // current directory + + if (!is_dir($fsDir)) Error("Dir not found","Directory $relDir not found on filesystem at $fsDir",1) ; - $fsDir = $fsRoot.$relDir."/"; // current directory + global $debug; + $debug .= "[$gblLogin|$relDir] before >"; - if (!is_dir($fsDir)) Error("Dir not found",$relDir) ; + if (! check_perm($relDir,(trperm_b | trperm_r))) + Error("Access denied","User $gblLogin tried to access $relDir without valid trustee.",1); + $debug .= "< afeter"; $hide_items=",$gblHide,"; @@ -633,7 +647,7 @@ echo "" ; - // updir bar + // updir (parent) bar if (chopsl($fsDir) != chopsl($fsRoot)) { $parent = dirname($relDir) ; if ($parent == "") $parent = "/" ; @@ -713,7 +727,7 @@ $dir = $dirList[$key]; $info_url=self_args(array("A"=>"A=E", "F"=>"F=".urlencode($dir), "D"=>$D)); - $dir_url=$self."?D=".urlencode($relDir."/".$dir); + $dir_url=$self."?D=".urlencode(chopsl($relDir)."/".$dir); include("$html/Navigate-dirEntry.html"); } // iterate over dirs @@ -859,12 +873,18 @@ - "; + include("$fsRealmDir/$realm".$realm_sep."info.inc"); + print ""; +} elseif (file_exists("$gblRepositoryDir/.info.inc")) { + print ""; } + + ?> @@ -892,8 +912,6 @@ global $html, $HTTP_SERVER_VARS; $self = $HTTP_SERVER_VARS["PHP_SELF"] ; - if ($relDir == "") $relDir = "/" ; - include("$html/UploadPage.html"); } // end function UploadPage @@ -903,11 +921,11 @@ // Error with sysadmin flag are reported to error_log or hidden from // users -function Error($title,$text="",$sysadmin=0) { +function Error($title,$text="",$sysadmin=0,$no_404=0) { global $gblSeparateAdminMessages, $gblMailAdminMessages,$realm, $HTTP_SERVER_VARS; - if (! headers_sent()) header("HTTP/1.0 404 Not Found"); + if (! headers_sent() && ! $no_404) header("HTTP/1.0 404 Not Found"); if ($sysadmin) { if ($gblSeparateAdminMessages) { $user="Your administrator "; @@ -1076,13 +1094,15 @@ function try_rename($from,$to) { # print "$from -> $to\n"; if (file_exists($from) && is_writeable(dirname($to))) { - rename($from,$to); + return rename($from,$to); + } else { + return 0; } } function try_dir($todir) { if (! file_exists($todir)) { - mkdir($todir,0700); + @mkdir($todir,0700); } } @@ -1092,7 +1112,7 @@ # print "
$fromdir / $fromfile -> $todir / $tofile\n\n";
 
-	try_rename("$fromdir/$fromfile","$todir/$tofile");
+	if (! try_rename("$fromdir/$fromfile","$todir/$tofile")) Error("Rename error","Can't rename file $fromfile to $tofile",1);
 	try_dir("$todir/.log");
 	try_rename("$fromdir/.log/$fromfile","$todir/.log/$tofile");
 	try_dir("$todir/.note");
@@ -1203,8 +1223,8 @@
 //////////////////////////////////////////////////////////////////
 
 function chopsl($path) {
-	if (substr($path,strlen($path)-1,1) == "/") $path=substr($path,0,strlen($path)-1);
 	$path=str_replace("//","/",$path);
+	if (substr($path,strlen($path)-1,1) == "/") $path=substr($path,0,strlen($path)-1);
 	return $path;
 }
 
@@ -1361,12 +1381,14 @@
 }//init_trustee
 
 function in_group($user,$group) {
-	return in_array($groups[$group],$user);
+	global $groups;
+	return in_array($user,$groups[$group]);
 }
 
 // helper function
 function unroll_perm($u,$t,$user,$perm) {
-	// check user
+
+	// check user FIX
 	if ($t & trmask_not && ($u==$user)) continue;
 	if (!($t & trmask_not) && ($u!=$user)) continue;
 
@@ -1388,12 +1410,21 @@
 	global $trustees;
 	$perm[allow] = 0;
 	$perm[deny] = 0;
+
+global $debug;
+$debug .= "
check_trustee $path ... "; + $path_arr=explode("/",$path); - $path = "/"; + $tmppath = "/"; while (count($path_arr)) { - if (substr($path,strlen($path)-1,1) != "/") $path.="/"; - $path.=array_shift($path_arr); - $tr = $trustees[$path]; + $tmppath.=array_shift($path_arr); +$debug.= ">> $tmppath "; + if (substr($tmppath,strlen($tmppath)-1,1) != "/") $tmppath.="/"; + $tr = $trustees[$tmppath]; + + # clear one level flag + $perm[allow] &= ~trperm_one_level; + $perm[deny] &= ~trperm_one_level; if (isset($tr)) { // first apply trustee for all @@ -1402,26 +1433,25 @@ unset($tr['*']); } // then apply group policies - foreach ($tr as $u=>$t) { - if ($t & trmask_group && in_group($user,$u)) { + foreach ($tr as $g=>$t) { + if ($t & trmask_group && in_group($user,$g)) { // resolv user $t = $t & ~trmask_group; - $u = $user; - $perm = unroll_perm($u,$t,$user, $perm); - unset($tr[$u]); + $perm = unroll_perm($user,$t,$user, $perm); + unset($tr[$g]); } } - // then apply use policy + // then apply user policy if (isset($tr[$user])) { $perm = unroll_perm($user,$tr[$user],$user, $perm); unset($tr[$user]); } - } +$debug.="d:".display_trustee($perm[deny])." a:".display_trustee($perm[allow])." "; } -#print "
user: $user path: $path perm: "; -#print "d: $perm[deny] (".display_trustee($perm[deny]).") a: $perm[allow] (".display_trustee($perm[allow]).")
\n"; +$debug.="
check_trustee: user: $user path: $path==$tmppath perm: "; +$debug.="d: $perm[deny] (".display_trustee($perm[deny]).") a: $perm[allow] (".display_trustee($perm[allow]).")
\n"; return $perm; } @@ -1429,15 +1459,18 @@ function check_perm($path,$trperm) { global $gblLogin,$HAVE_TRUSTEE; -print "
check_perm: $path test perm ".display_trustee($perm)."
\n"; + + global $debug; +$debug.="
check_perm: $path test perm ".display_trustee($perm)."
\n"; + $return = ! $HAVE_TRUSTEE; if ($HAVE_TRUSTEE) { $perm = check_trustee($gblLogin,$path); -print " d: $perm[deny] (".display_trustee($perm[deny]).") a: $perm[allow] (".display_trustee($perm[allow]).") perm: $trperm"; +$debug.=" d: $perm[deny] (".display_trustee($perm[deny]).") a: $perm[allow] (".display_trustee($perm[allow]).") perm to have: $trperm (".display_trustee($trperm).")"; if ($perm[deny] & $trperm) $return=0; - elseif ($perm[allow] & $trperm) $return=1; + elseif (($perm[allow] & $trperm) == $trperm) $return=1; } -print " return: $return
\n"; +$debug.=" return: $return
\n"; return($return); } @@ -1467,11 +1500,25 @@ } ////////////////////////////////////////////////////////////////// + +// check for invalid characters in filename and dirname (.. and /) + +function check_dirname($file) { + if (strstr($file,"..")) Error("Security violation","No parent dir .. allowed in directory name $file",1); +} + +function check_filename($file) { + if (strstr($file,"..")) Error("Security violation","No parent dir .. allowed in file name $file",1); + if (strstr($file,"/")) Error("Security violation","No slashes / allowed in file name $file",1); +} + +////////////////////////////////////////////////////////////////// // MAIN PROGRAM $gblFilePerms = 0640 ; // default for new files $gblDirPerms = 0750 ; // default for new dirs + $STYLE = $HTTP_GET_VARS[STYLE]; if (isset($STYLE) && $STYLE == "get") { include("$html/docman.css"); exit; @@ -1490,7 +1537,16 @@ if (! isset($fsRealmDir)) { $fsRealmDir = "$gblIncDir/realm"; } - $realm_config = "$fsRealmDir/$realm.conf"; + + // try to add dir to script name to realm var + if (is_dir("$fsRealmDir/$realm/".dirname($HTTP_SERVER_VARS[SCRIPT_NAME]))) { + $realm .= dirname($HTTP_SERVER_VARS[SCRIPT_NAME]); + $realm_sep = "/"; + } else { + $realm_sep = "."; + } + + $realm_config = $fsRealmDir."/".$realm.$realm_sep."conf"; // read user-defined configuration if (file_exists($realm_config)) { @@ -1508,6 +1564,10 @@ Error("Configuration error","Can't find user handling module at $gblIncDir/htusers/$gblUsers.php ! Please fix $realm_config"); } + // take additional login vars + $relogin = $HTTP_GET_VARS[relogin]; + $force_login = $HTTP_GET_VARS[force_login]; + // if no password, or empty password logout if ( isset($gblLogin) && ( @@ -1526,17 +1586,18 @@ if (!is_dir($gblRepositoryDir)) Error("Repository dir not found","Can't find repository directory $gblRepositoryDir. Please fix that in $realm_config variable \$gblRepositoryDir.",1); // trustee (ACL) file configuration - $trustee_conf="$gblIncDir/realm/$realm.trustee"; + $trustee_conf="$fsRealmDir/$realm".$realm_sep."trustee"; // compiled version of trustee file $trustee_php="$gblRepositoryDir/.trustee.php"; // get ACL informations $HAVE_TRUSTEE = init_trustee(); - if (strtolower($gblLogin) == "anonymous" || !isset($gblPasswd)) { - $perm = check_trustee($gblLogin,$path); + if (strtolower($gblLogin) == "anonymous" || !isset($gblLogin)) { + $perm = check_trustee("anonymous",$path); // browsing must be explicitly allowed for root directory // of repository for anonymous user to work! if ($perm[allow] & trperm_b) { + $gblLogin = $gblPasswd = "anonymous"; $secHash = md5($gblLogin.$gblPasswd); $gblUserName = "Anonymous user"; } @@ -1547,39 +1608,49 @@ isset($relogin) && $secHash == $relogin) { header("WWW-authenticate: basic realm=\"$realm\"") ; header("HTTP/1.0 401 Unauthorized") ; - Error("401 Unauthorized","No trespassing !"); + Error("401 Unauthorized","No trespassing !",0,1); } + // read mime.types readMime(); - // get current directory relative to $gblFsRoot - $relDir = $DIR ; // from POST - if ($relDir == "") { // not defined in POST ? - $relDir = urldecode($D) ; // then use GET - } - - $relDir=stripSlashes($relDir); - - if ($relDir == "/") $relDir = "" ; - // default : website root = "" - - if (strstr($relDir,"..")) Error("No updirs allowed"); - - // full paths contain "fs" or "Fs". Paths realitve to root of - // website contain "rel" or "Rel". The script won't let you - // edit anything above directory equal to http://server.com - // i.e. below $gblFsRoot. + if ($HTTP_SERVER_VARS["REQUEST_METHOD"] == "POST") { + // take variables from server + $FN=stripSlashes($HTTP_POST_VARS["FN"]); + $DIR=stripSlashes($HTTP_POST_VARS["DIR"]); + $RELPATH=stripSlashes($HTTP_POST_VARS["RELPATH"]); + $T=stripSlashes($HTTP_POST_VARS["T"]); + $CONFIRM=stripSlashes($HTTP_POST_VARS["CONFIRM"]); + + check_filename($FN); + check_dirname($DIR); + check_dirname($RELPATH); + + $relDir = $DIR; + } else { + // get + $A=stripSlashes($HTTP_GET_VARS["A"]); + $D=stripSlashes(urldecode($HTTP_GET_VARS["D"])); + $F=stripSlashes($HTTP_GET_VARS["F"]); + + check_filename($F); + check_dirname($D); + + $relDir = $D; + } $relScriptDir = dirname($SCRIPT_NAME) ; // i.e. /docman // start on server root $gblFsRoot = $gblRepositoryDir; - // i.e. /home/httpd/html + // i.e. /home/httpd/repository $fsDir = $gblFsRoot . $relDir ; // current directory - if ( !is_dir($fsDir) ) Error("Dir not found",$relDir) ; + if ( !is_dir($fsDir) ) Error("Dir not found","Can't find $relDir which points to $fsDir",1) ; + + if ($relDir == "") $relDir="/"; if (isset($HTTP_SERVER_VARS["HTTPS"]) && $HTTP_SERVER_VARS["HTTPS"] == "on") { $webRoot = "https://"; @@ -1588,21 +1659,6 @@ } $webRoot .= $HTTP_SERVER_VARS["HTTP_HOST"] . $relScriptDir; - // take variables from server - $FN=stripSlashes($HTTP_POST_VARS["FN"]); - $DIR=stripSlashes($HTTP_POST_VARS["DIR"]); - $RELPATH=stripSlashes($HTTP_POST_VARS["RELPATH"]); - $T=stripSlashes($HTTP_POST_VARS["T"]); - $CONFIRM=stripSlashes($HTTP_POST_VARS["CONFIRM"]); - - // get - $A=stripSlashes($HTTP_GET_VARS["A"]); - $D=stripSlashes($HTTP_GET_VARS["D"]); - -// if (isset($F)) Error("Document manager system error","variable $F shouldn't be set here (re-check old code)",1); -// $F=stripSlashes($HTTP_SERVER_VARS["PATH_INFO"]); - $F=stripSlashes($HTTP_GET_VARS["F"]); - switch ($HTTP_POST_VARS["POSTACTION"]) { case "UPLOAD" : $FN_name=stripSlashes($HTTP_POST_FILES["FN"]["tmp_name"]); @@ -1615,10 +1671,10 @@ } $FILENAME = $HTTP_POST_VARS["FILENAME"]; - if (strstr($FILENAME,"/")) - Error("Upload error","Non-conforming filename. Filename $FILENAME has slashes (/) in it.") ; + check_filename($FILENAME); + if (! isset($FILENAME)) { // from update file - $target = "$fsDir/".basename($FN_name); + $target = "$fsDir/".basename($FN); } else { $target = "$fsDir/$FILENAME"; } @@ -1751,11 +1807,13 @@ case "RENAME" : if ( $CONFIRM != "on" ) break ; + $NEWNAME=stripSlashes($HTTP_POST_VARS["NEWNAME"]); LogIt("$fsDir/$FN","renamed $FN to $NEWNAME",trperm_r); safe_rename($fsDir,$FN,$NEWNAME); break ; case "NOTE" : + $NOTE=stripSlashes($HTTP_POST_VARS["NOTE"]); WriteNote("$fsDir/$FN","$NOTE"); break ; @@ -1782,14 +1840,16 @@ // $A=Co : checkout file $D/$F // $A=Ci : checkin file $D/$F // $A=V : view file (do nothing except log) - // $A=I : include file .$F.php from $gblFsRoot + // $A=I : include file .$F.php from [$gblIncDir|realm]/include_php // default : display directory $D switch ($A) { case "U" : // upload to $relDir + if (! check_perm($relDir, trperm_w)) + Error("Write access denied","You don't have permission to write in $relDir"); if (!is_writeable($gblFsRoot . $relDir)) - Error("Write access denied",$relDir) ; + Error("Write access denied","User $gblLogin has permission on $relDir, but directory is not writable",1); $text = "Use this page to upload a single " ; $text .= "file to $realm." ; StartHTML("(Upload Page)", $text) ; @@ -1837,11 +1897,14 @@ EndHTML() ; exit; case "I" : - $F=stripSlashes($F); - $inc_file="${gblFsRoot}/.${F}.php"; - if (!isset($F) || $F == "" || !file_exists($inc_file)) Error("Fatal error $inc_file"); // can't find file to include + if (! isset($F) || $F == "") + Error("Can't find file to include","Your request didn't specify file to include which should be in variable F like $HTTP_SERVER_VARS[REQUEST_URI]&F=include_php_file",1); + $inc_file="$fsRealmDir/$realm".$realm_sep.$F.".php"; + if (! file_exists($inc_file)) { + Error("Can't find file to include","Can't find include file $F.php in $fsRealmDir/$realm/. Meybe you should copy $gblIncDir/include_php/$F.php to $inc_file ?",1); + } if (!is_readable($inc_file)) - Error("Read access to include file denied",".${F}.php"); + Error("Read access to include file denied","Can't read PHP include file $inc_file. Fix permissions on it.",1); $text = "Your include file should define \$text variable which holds this text and \$title variable which is page title"; $title = "You should define \$title variable with page title"; include($inc_file);

"; - include(".info.inc"); - print "


"; + include("$gblRepositoryDir/.info.inc"); + print "