Annotation of embedaddon/php/main/safe_mode.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Author: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
! 16: +----------------------------------------------------------------------+
! 17: */
! 18:
! 19: /* $Id: safe_mode.c 321634 2012-01-01 13:15:04Z felipe $ */
! 20:
! 21: #include "php.h"
! 22:
! 23: #include <stdio.h>
! 24: #include <stdlib.h>
! 25:
! 26: #if HAVE_UNISTD_H
! 27: #include <unistd.h>
! 28: #endif
! 29: #include <sys/stat.h>
! 30: #include "ext/standard/pageinfo.h"
! 31: #include "safe_mode.h"
! 32: #include "SAPI.h"
! 33: #include "php_globals.h"
! 34:
! 35: /*
! 36: * php_checkuid
! 37: *
! 38: * This function has six modes:
! 39: *
! 40: * 0 - return invalid (0) if file does not exist
! 41: * 1 - return valid (1) if file does not exist
! 42: * 2 - if file does not exist, check directory
! 43: * 3 - only check directory (needed for mkdir)
! 44: * 4 - check mode and param
! 45: * 5 - only check file
! 46: */
! 47:
! 48: PHPAPI int php_checkuid_ex(const char *filename, const char *fopen_mode, int mode, int flags)
! 49: {
! 50: struct stat sb;
! 51: int ret, nofile=0;
! 52: long uid=0L, gid=0L, duid=0L, dgid=0L;
! 53: char path[MAXPATHLEN];
! 54: char *s, filenamecopy[MAXPATHLEN];
! 55: TSRMLS_FETCH();
! 56:
! 57: path[0] = '\0';
! 58:
! 59: if (!filename) {
! 60: return 0; /* path must be provided */
! 61: }
! 62:
! 63: if (strlcpy(filenamecopy, filename, MAXPATHLEN)>=MAXPATHLEN) {
! 64: return 0;
! 65: }
! 66: filename=(char *)&filenamecopy;
! 67:
! 68: if (fopen_mode) {
! 69: if (fopen_mode[0] == 'r') {
! 70: mode = CHECKUID_DISALLOW_FILE_NOT_EXISTS;
! 71: } else {
! 72: mode = CHECKUID_CHECK_FILE_AND_DIR;
! 73: }
! 74: }
! 75:
! 76: /* First we see if the file is owned by the same user...
! 77: * If that fails, passthrough and check directory...
! 78: */
! 79: if (mode != CHECKUID_ALLOW_ONLY_DIR) {
! 80: #if HAVE_BROKEN_GETCWD
! 81: char ftest[MAXPATHLEN];
! 82:
! 83: strcpy(ftest, filename);
! 84: if (VCWD_GETCWD(ftest, sizeof(ftest)) == NULL) {
! 85: strcpy(path, filename);
! 86: } else
! 87: #endif
! 88: expand_filepath(filename, path TSRMLS_CC);
! 89:
! 90: ret = VCWD_STAT(path, &sb);
! 91: if (ret < 0) {
! 92: if (mode == CHECKUID_DISALLOW_FILE_NOT_EXISTS) {
! 93: if ((flags & CHECKUID_NO_ERRORS) == 0) {
! 94: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to access %s", filename);
! 95: }
! 96: return 0;
! 97: } else if (mode == CHECKUID_ALLOW_FILE_NOT_EXISTS) {
! 98: if ((flags & CHECKUID_NO_ERRORS) == 0) {
! 99: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to access %s", filename);
! 100: }
! 101: return 1;
! 102: }
! 103: nofile = 1;
! 104: } else {
! 105: uid = sb.st_uid;
! 106: gid = sb.st_gid;
! 107: if (uid == php_getuid()) {
! 108: return 1;
! 109: } else if (PG(safe_mode_gid) && gid == php_getgid()) {
! 110: return 1;
! 111: }
! 112: }
! 113:
! 114: /* Trim off filename */
! 115: if ((s = strrchr(path, DEFAULT_SLASH))) {
! 116: if (*(s + 1) == '\0' && s != path) { /* make sure that the / is not the last character */
! 117: *s = '\0';
! 118: s = strrchr(path, DEFAULT_SLASH);
! 119: }
! 120: if (s) {
! 121: if (s == path) {
! 122: path[1] = '\0';
! 123: } else {
! 124: *s = '\0';
! 125: }
! 126: }
! 127: }
! 128: } else { /* CHECKUID_ALLOW_ONLY_DIR */
! 129: s = strrchr(filename, DEFAULT_SLASH);
! 130:
! 131: if (s == filename) {
! 132: /* root dir */
! 133: path[0] = DEFAULT_SLASH;
! 134: path[1] = '\0';
! 135: } else if (s && *(s + 1) != '\0') { /* make sure that the / is not the last character */
! 136: *s = '\0';
! 137: VCWD_REALPATH(filename, path);
! 138: *s = DEFAULT_SLASH;
! 139: } else {
! 140: /* Under Solaris, getcwd() can fail if there are no
! 141: * read permissions on a component of the path, even
! 142: * though it has the required x permissions */
! 143: path[0] = '.';
! 144: path[1] = '\0';
! 145: VCWD_GETCWD(path, sizeof(path));
! 146: }
! 147: } /* end CHECKUID_ALLOW_ONLY_DIR */
! 148:
! 149: if (mode != CHECKUID_ALLOW_ONLY_FILE) {
! 150: /* check directory */
! 151: ret = VCWD_STAT(path, &sb);
! 152: if (ret < 0) {
! 153: if ((flags & CHECKUID_NO_ERRORS) == 0) {
! 154: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to access %s", filename);
! 155: }
! 156: return 0;
! 157: }
! 158: duid = sb.st_uid;
! 159: dgid = sb.st_gid;
! 160: if (duid == php_getuid()) {
! 161: return 1;
! 162: } else if (PG(safe_mode_gid) && dgid == php_getgid()) {
! 163: return 1;
! 164: } else {
! 165: if (SG(rfc1867_uploaded_files)) {
! 166: if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, strlen(filename)+1)) {
! 167: return 1;
! 168: }
! 169: }
! 170: }
! 171: }
! 172:
! 173: if (mode == CHECKUID_ALLOW_ONLY_DIR) {
! 174: uid = duid;
! 175: gid = dgid;
! 176: if (s) {
! 177: *s = 0;
! 178: }
! 179: }
! 180:
! 181: if (nofile) {
! 182: uid = duid;
! 183: gid = dgid;
! 184: filename = path;
! 185: }
! 186:
! 187: if ((flags & CHECKUID_NO_ERRORS) == 0) {
! 188: if (PG(safe_mode_gid)) {
! 189: php_error_docref(NULL TSRMLS_CC, 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);
! 190: } else {
! 191: php_error_docref(NULL TSRMLS_CC, 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);
! 192: }
! 193: }
! 194:
! 195: return 0;
! 196: }
! 197:
! 198: PHPAPI int php_checkuid(const char *filename, const char *fopen_mode, int mode)
! 199: {
! 200: #ifdef NETWARE
! 201: /* NetWare don't have uid*/
! 202: return 1;
! 203: #else
! 204: return php_checkuid_ex(filename, fopen_mode, mode, 0);
! 205: #endif
! 206: }
! 207:
! 208: PHPAPI char *php_get_current_user(void)
! 209: {
! 210: struct stat *pstat;
! 211: TSRMLS_FETCH();
! 212:
! 213: if (SG(request_info).current_user) {
! 214: return SG(request_info).current_user;
! 215: }
! 216:
! 217: /* FIXME: I need to have this somehow handled if
! 218: USE_SAPI is defined, because cgi will also be
! 219: interfaced in USE_SAPI */
! 220:
! 221: pstat = sapi_get_stat(TSRMLS_C);
! 222:
! 223: if (!pstat) {
! 224: return "";
! 225: } else {
! 226: #ifdef PHP_WIN32
! 227: char name[256];
! 228: DWORD len = sizeof(name)-1;
! 229:
! 230: if (!GetUserName(name, &len)) {
! 231: return "";
! 232: }
! 233: name[len] = '\0';
! 234: SG(request_info).current_user_length = len;
! 235: SG(request_info).current_user = estrndup(name, len);
! 236: return SG(request_info).current_user;
! 237: #else
! 238: struct passwd *pwd;
! 239: #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
! 240: struct passwd _pw;
! 241: struct passwd *retpwptr = NULL;
! 242: int pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
! 243: char *pwbuf;
! 244:
! 245: if (pwbuflen < 1) {
! 246: return "";
! 247: }
! 248: pwbuf = emalloc(pwbuflen);
! 249: if (getpwuid_r(pstat->st_uid, &_pw, pwbuf, pwbuflen, &retpwptr) != 0) {
! 250: efree(pwbuf);
! 251: return "";
! 252: }
! 253: pwd = &_pw;
! 254: #else
! 255: if ((pwd=getpwuid(pstat->st_uid))==NULL) {
! 256: return "";
! 257: }
! 258: #endif
! 259: SG(request_info).current_user_length = strlen(pwd->pw_name);
! 260: SG(request_info).current_user = estrndup(pwd->pw_name, SG(request_info).current_user_length);
! 261: #if defined(ZTS) && defined(HAVE_GETPWUID_R) && defined(_SC_GETPW_R_SIZE_MAX)
! 262: efree(pwbuf);
! 263: #endif
! 264: return SG(request_info).current_user;
! 265: #endif
! 266: }
! 267: }
! 268:
! 269: /*
! 270: * Local variables:
! 271: * tab-width: 4
! 272: * c-basic-offset: 4
! 273: * End:
! 274: * vim600: sw=4 ts=4 fdm=marker
! 275: * vim<600: sw=4 ts=4
! 276: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>