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>