--- php-4.3.9/main/safe_mode.c 2003-03-17 15:50:23.000000000 +0200 +++ phppatched/main/safe_mode.c 2004-09-24 23:46:21.000774340 +0300 @@ -14,7 +14,9 @@ +----------------------------------------------------------------------+ | Author: Rasmus Lerdorf | +----------------------------------------------------------------------+ - */ + | Applied patch by Anton Titov http://titov.net/safemodepatch | + +----------------------------------------------------------------------+ +*/ /* $Id: safe_mode.c,v 1.51.2.4 2003/03/17 13:50:23 wez Exp $ */ #include "php.h" @@ -46,14 +48,21 @@ PHPAPI int php_checkuid_ex(const char *filename, char *fopen_mode, int mode, int flags) { - struct stat sb; - int ret, nofile=0; + struct stat sb, sb2; + int ret, usegid, scriptuid, serveruid, scriptgid, nofile=0; long uid=0L, gid=0L, duid=0L, dgid=0L; - char path[MAXPATHLEN]; - char *s, filenamecopy[MAXPATHLEN]; + char path[MAXPATHLEN], path2[MAXPATHLEN]; + char *s, *s2, filenamecopy[MAXPATHLEN]; php_stream_wrapper *wrapper = NULL; TSRMLS_FETCH(); + + scriptuid=php_getuid(); + serveruid=getuid(); + if (usegid=PG(safe_mode_gid)){ // yes, it's correct + scriptgid=php_getgid(); + } + strlcpy(filenamecopy, filename, MAXPATHLEN); filename=(char *)&filenamecopy; @@ -99,11 +108,33 @@ } else { uid = sb.st_uid; gid = sb.st_gid; - if (uid == php_getuid()) { + if (uid == scriptuid) { return 1; - } else if (PG(safe_mode_gid) && gid == php_getgid()) { + } else if (usegid && gid == scriptgid) { return 1; } + strlcpy(path2, path, MAXPATHLEN); + while (uid==serveruid){ + if (!(s2 = strrchr(path2, DEFAULT_SLASH))) + break; + if (s2==path2) + break; + *s2='\0'; + ret = VCWD_STAT(path2, &sb2); + if (ret < 0) + break; // no need to throw error, as we can access the file itself + else { + uid = sb2.st_uid; + gid = sb2.st_gid; + } + } + if (uid==scriptuid) + return 1; + else if (usegid && gid == scriptgid) + return 1; + // restore uid & gid for error message + uid = sb.st_uid; + gid = sb.st_gid; } /* Trim off filename */ @@ -145,11 +176,34 @@ } duid = sb.st_uid; dgid = sb.st_gid; - if (duid == php_getuid()) { + if (duid == scriptuid) { return 1; - } else if (PG(safe_mode_gid) && dgid == php_getgid()) { + } else if (usegid && dgid == scriptgid) { return 1; } else { + + strlcpy(path2, path, MAXPATHLEN); + while (duid==serveruid){ + if (!(s2 = strrchr(path2, DEFAULT_SLASH))) + break; + if (s2==path2) + break; + *s2='\0'; + ret = VCWD_STAT(path2, &sb2); + if (ret < 0) + break; + else { + duid = sb2.st_uid; + dgid = sb2.st_gid; + } + } + if (duid==scriptuid) + return 1; + else if (usegid && dgid==scriptgid) + return 1; + duid = sb.st_uid; + dgid = sb.st_gid; + TSRMLS_FETCH(); if (SG(rfc1867_uploaded_files)) { @@ -159,7 +213,6 @@ } } } - if (mode == CHECKUID_ALLOW_ONLY_DIR) { uid = duid; gid = dgid;