summaryrefslogtreecommitdiff
path: root/main/safe_mode.c
diff options
context:
space:
mode:
authorJames E. Flemer <jflemer@php.net>2001-07-13 18:21:21 +0000
committerJames E. Flemer <jflemer@php.net>2001-07-13 18:21:21 +0000
commit771e3e498fad6adcdc63d03ab97d4ff1f93a3987 (patch)
tree7cc1ecaa721adb2f927d947d5b61dae10760a42d /main/safe_mode.c
parentb9325a36a8df9619e4485b166516cff1e9193406 (diff)
downloadphp-git-771e3e498fad6adcdc63d03ab97d4ff1f93a3987.tar.gz
o Fixed Bug #12121: chdir and safe_mode
- [ main/safe_mode.h ] added new checkuid mode: CHECKUID_ALLOW_ONLY_FILE: skips directory check if file check fails - [ ext/standard/dir.c ] changed php_checkuid() to use CHECKUID_ALLOW_ONLY_FILE instead of CHECKUID_ALLOW_ONLY_DIR - [ main/safe_mode.c ] added code for new checkuid mode o Fixed Bug #12119: safe mode owner check can be bypassed with symlink - [ main/safe_mode.c ] use VCWD_REALPATH to resolve destination of symlink before trimming filename o New Feature: safe_mode_include_dir (php.ini directive) - Allows bypassing UID/GID checks when including files from the directory in safe_mode_include_dir and its subdirectories. (safe_mode must be on, directory must also be in include_path or full path must be used when including) o Fixed Feature: safe_mode_gid (php.ini directive) - Correctly check (and report) UID/GID bits on directories o Changed include() fall back to scripts cwd implementation - CWD added to the (local) search path in php_fopen_with_path() instead of seperate case. [ main/fopen_wrappers.c ]
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;
}