summaryrefslogtreecommitdiff
path: root/main/safe_mode.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/safe_mode.c')
-rw-r--r--main/safe_mode.c93
1 files changed, 51 insertions, 42 deletions
diff --git a/main/safe_mode.c b/main/safe_mode.c
index e251d37b26..f20fe516c4 100644
--- a/main/safe_mode.c
+++ b/main/safe_mode.c
@@ -48,6 +48,7 @@ PHPAPI int php_checkuid(const char *filename, char *fopen_mode, int mode)
struct stat sb;
int ret;
long uid=0L, gid=0L, duid=0L, dgid=0L;
+ char path[MAXPATHLEN];
char *s;
PLS_FETCH();
@@ -71,8 +72,12 @@ PHPAPI int php_checkuid(const char *filename, char *fopen_mode, int mode)
return 1;
}
+ /* First we see if the file is owned by the same user...
+ * If that fails, passthrough and check directory...
+ */
if (mode != CHECKUID_ALLOW_ONLY_DIR) {
- ret = VCWD_STAT(filename, &sb);
+ VCWD_REALPATH(filename, path);
+ ret = VCWD_STAT(path, &sb);
if (ret < 0) {
if (mode == CHECKUID_DISALLOW_FILE_NOT_EXISTS) {
php_error(E_WARNING, "Unable to access %s", filename);
@@ -83,63 +88,67 @@ PHPAPI int php_checkuid(const char *filename, char *fopen_mode, int mode)
}
} else {
uid = sb.st_uid;
+ gid = sb.st_gid;
if (uid == php_getuid()) {
return 1;
+ } else if (PG(safe_mode_gid) && gid == php_getgid()) {
+ return 1;
}
}
- }
- s = strrchr(filename,'/');
- /* This loop gets rid of trailing slashes which could otherwise be
- * used to confuse the function.
- */
- while(s && *(s+1)=='\0' && s>filename) {
- *s='\0';
- s = strrchr(filename,'/');
- }
+ /* Trim off filename */
+ if (s = strrchr(path,DEFAULT_SLASH)) {
+ *s = '\0';
+ }
+ } else { /* CHECKUID_ALLOW_ONLY_DIR */
+ s = strrchr(filename,DEFAULT_SLASH);
- if (s) {
- *s='\0';
- ret = VCWD_STAT(filename, &sb);
- *s='/';
+ if (s) {
+ *s = '\0';
+ VCWD_REALPATH(filename, path);
+ *s = DEFAULT_SLASH;
+ } else {
+ VCWD_GETCWD(path, MAXPATHLEN);
+ }
+ } /* end CHECKUID_ALLOW_ONLY_DIR */
+
+ if (mode != CHECKUID_ALLOW_ONLY_FILE) {
+ /* check directory */
+ ret = VCWD_STAT(path, &sb);
if (ret < 0) {
php_error(E_WARNING, "Unable to access %s", filename);
return 0;
}
duid = sb.st_uid;
- } else {
- char cwd[MAXPATHLEN];
- if (!VCWD_GETCWD(cwd, MAXPATHLEN)) {
- php_error(E_WARNING, "Unable to access current working directory");
- return 0;
- }
- ret = VCWD_STAT(cwd, &sb);
- if (ret < 0) {
- php_error(E_WARNING, "Unable to access %s", cwd);
- return 0;
- }
- duid = sb.st_uid;
- }
- if (duid == (uid=php_getuid())) {
- return 1;
- } else if (PG(safe_mode_gid) && dgid == (gid=php_getgid())) {
- return 1;
- } else {
- SLS_FETCH();
+ dgid = sb.st_gid;
+ if (duid == php_getuid()) {
+ return 1;
+ } else if (PG(safe_mode_gid) && dgid == php_getgid()) {
+ return 1;
+ } else {
+ SLS_FETCH();
- if (SG(rfc1867_uploaded_files)) {
- if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, strlen(filename)+1)) {
- return 1;
+ if (SG(rfc1867_uploaded_files)) {
+ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, strlen(filename)+1)) {
+ return 1;
+ }
}
}
+ }
- if (PG(safe_mode_gid)) {
- php_error(E_WARNING, "SAFE MODE Restriction in effect. The script whose uid/gid is %ld/%ld is not allowed to access %s owned by uid/gid %ld/%ld", uid, gid, filename, duid, dgid);
- } else {
- php_error(E_WARNING, "SAFE MODE Restriction in effect. The script whose uid is %ld is not allowed to access %s owned by uid %ld", uid, filename, duid);
- }
- return 0;
+ if (mode == CHECKUID_ALLOW_ONLY_DIR) {
+ uid = duid;
+ gid = dgid;
+ if (s) {
+ *s = 0;
+ }
}
+ if (PG(safe_mode_gid)) {
+ php_error(E_WARNING, "SAFE MODE Restriction in effect. The script whose uid/gid is %ld/%ld is not allowed to access %s owned by uid/gid %ld/%ld", php_getuid(), php_getgid(), filename, uid, gid);
+ } else {
+ php_error(E_WARNING, "SAFE MODE Restriction in effect. The script whose uid is %ld is not allowed to access %s owned by uid %ld", php_getuid(), filename, uid);
+ }
+ return 0;
}