1999-04-08 05:05:13 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-08 16:18:22 +08:00
| PHP Version 5 |
1999-04-08 05:05:13 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2007-01-01 17:36:18 +08:00
| Copyright ( c ) 1997 - 2007 The PHP Group |
1999-04-08 05:05:13 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 20:51:34 +08:00
| This source file is subject to version 3.01 of the PHP license , |
1999-07-16 21:13:16 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
2006-01-01 20:51:34 +08:00
| http : //www.php.net/license/3_01.txt |
1999-07-16 21:13:16 +08:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
1999-04-08 05:05:13 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Authors : Rasmus Lerdorf < rasmus @ lerdorf . on . ca > |
| Jim Winstead < jimw @ php . net > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
2003-02-19 16:40:19 +08:00
1999-04-08 05:05:13 +08:00
/* $Id$ */
2001-06-06 21:06:12 +08:00
/* {{{ includes
*/
1999-04-08 05:05:13 +08:00
# include "php.h"
1999-04-10 20:17:20 +08:00
# include "php_globals.h"
1999-05-03 03:54:02 +08:00
# include "SAPI.h"
1999-04-08 05:05:13 +08:00
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
2000-02-11 23:59:30 +08:00
# ifdef PHP_WIN32
1999-04-08 05:05:13 +08:00
# define O_RDONLY _O_RDONLY
# include "win32/param.h"
# else
# include <sys/param.h>
# endif
# include "safe_mode.h"
1999-06-16 05:51:00 +08:00
# include "ext/standard/head.h"
1999-12-05 03:19:57 +08:00
# include "ext/standard/php_standard.h"
1999-04-08 05:05:13 +08:00
# include "zend_compile.h"
2000-09-05 23:59:08 +08:00
# include "php_network.h"
1999-04-08 05:05:13 +08:00
# if HAVE_PWD_H
# include <pwd.h>
# endif
# include <sys/types.h>
# if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
# endif
# ifndef S_ISREG
2000-12-15 07:05:31 +08:00
# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
1999-04-08 05:05:13 +08:00
# endif
2000-02-11 23:59:30 +08:00
# ifdef PHP_WIN32
2003-02-16 11:48:49 +08:00
# include <winsock2.h>
2002-09-09 18:56:28 +08:00
# elif defined(NETWARE) && defined(USE_WINSOCK)
# include <novsock2.h>
1999-04-08 05:05:13 +08:00
# else
# include <netinet/in.h>
# include <netdb.h>
2001-01-22 01:29:15 +08:00
# if HAVE_ARPA_INET_H
1999-04-08 05:05:13 +08:00
# include <arpa/inet.h>
# endif
2001-01-22 01:29:15 +08:00
# endif
1999-04-08 05:05:13 +08:00
2002-09-09 18:56:28 +08:00
# if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
1999-04-08 05:05:13 +08:00
# undef AF_UNIX
# endif
# if defined(AF_UNIX)
# include <sys/un.h>
# endif
2001-06-06 21:06:12 +08:00
/* }}} */
1999-04-08 05:05:13 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_check_specific_open_basedir
1999-04-08 05:05:13 +08:00
When open_basedir is not NULL , check if the given filename is located in
2007-10-09 16:40:36 +08:00
open_basedir . Returns - 1 if error or not in the open_basedir , else 0.
When open_basedir is NULL , always return 0.
1999-04-08 05:05:13 +08:00
*/
2002-08-20 04:47:55 +08:00
PHPAPI int php_check_specific_open_basedir ( const char * basedir , const char * path TSRMLS_DC )
1999-04-08 05:05:13 +08:00
{
char resolved_name [ MAXPATHLEN ] ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
char resolved_basedir [ MAXPATHLEN ] ;
1999-04-08 05:05:13 +08:00
char local_open_basedir [ MAXPATHLEN ] ;
2007-04-11 06:30:07 +08:00
char path_tmp [ MAXPATHLEN ] ;
char * path_file ;
2002-09-23 02:30:38 +08:00
int resolved_basedir_len ;
2002-10-05 06:16:16 +08:00
int resolved_name_len ;
2007-04-11 06:30:07 +08:00
int path_len ;
int nesting_level = 0 ;
2007-10-09 16:40:36 +08:00
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
/* Special case basedir==".": Use script-directory */
2005-02-03 07:43:17 +08:00
if ( strcmp ( basedir , " . " ) | | ! VCWD_GETCWD ( local_open_basedir , MAXPATHLEN ) ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
/* Else use the unmodified path */
2000-03-11 02:19:08 +08:00
strlcpy ( local_open_basedir , basedir , sizeof ( local_open_basedir ) ) ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
}
2007-04-11 06:30:07 +08:00
path_len = strlen ( path ) ;
if ( path_len > ( MAXPATHLEN - 1 ) ) {
/* empty and too long paths are invalid */
return - 1 ;
}
/* normalize and expand path */
if ( expand_filepath ( path , resolved_name TSRMLS_CC ) = = NULL ) {
return - 1 ;
}
2007-10-09 16:40:36 +08:00
2007-04-11 06:30:07 +08:00
path_len = strlen ( resolved_name ) ;
memcpy ( path_tmp , resolved_name , path_len + 1 ) ; /* safe */
while ( VCWD_REALPATH ( path_tmp , resolved_name ) = = NULL ) {
# ifdef HAVE_SYMLINK
if ( nesting_level = = 0 ) {
int ret ;
char buf [ MAXPATHLEN ] ;
2007-10-09 16:40:36 +08:00
2007-04-11 06:30:07 +08:00
ret = readlink ( path_tmp , buf , MAXPATHLEN - 1 ) ;
if ( ret < 0 ) {
/* not a broken symlink, move along.. */
} else {
/* put the real path into the path buffer */
memcpy ( path_tmp , buf , ret ) ;
path_tmp [ ret ] = ' \0 ' ;
}
}
# endif
# if defined(PHP_WIN32) || defined(NETWARE)
path_file = strrchr ( path_tmp , DEFAULT_SLASH ) ;
if ( ! path_file ) {
path_file = strrchr ( path_tmp , ' / ' ) ;
}
# else
path_file = strrchr ( path_tmp , DEFAULT_SLASH ) ;
# endif
if ( ! path_file ) {
/* none of the path components exist. definitely not in open_basedir.. */
return - 1 ;
} else {
path_len = path_file - path_tmp + 1 ;
# if defined(PHP_WIN32) || defined(NETWARE)
if ( path_len > 1 & & path_tmp [ path_len - 2 ] = = ' : ' ) {
2007-10-09 16:40:36 +08:00
/* this is c:\ */
2007-04-11 06:30:07 +08:00
path_tmp [ path_len ] = ' \0 ' ;
2007-04-18 19:58:40 +08:00
} else {
path_tmp [ path_len - 1 ] = ' \0 ' ;
2007-04-11 06:30:07 +08:00
}
# else
path_tmp [ path_len - 1 ] = ' \0 ' ;
# endif
}
nesting_level + + ;
}
/* Resolve open_basedir to resolved_basedir */
if ( expand_filepath ( local_open_basedir , resolved_basedir TSRMLS_CC ) ! = NULL ) {
2003-07-31 01:55:06 +08:00
/* Handler for basedirs that end with a / */
resolved_basedir_len = strlen ( resolved_basedir ) ;
2004-03-16 08:31:22 +08:00
if ( basedir [ strlen ( basedir ) - 1 ] = = PHP_DIR_SEPARATOR ) {
2005-09-27 23:07:49 +08:00
if ( resolved_basedir [ resolved_basedir_len - 1 ] ! = PHP_DIR_SEPARATOR ) {
resolved_basedir [ resolved_basedir_len ] = PHP_DIR_SEPARATOR ;
2004-03-16 08:31:22 +08:00
resolved_basedir [ + + resolved_basedir_len ] = ' \0 ' ;
}
2002-09-23 02:30:38 +08:00
}
2004-03-16 08:31:22 +08:00
2007-06-01 21:35:23 +08:00
resolved_name_len = strlen ( resolved_name ) ;
2007-04-11 06:30:07 +08:00
if ( path_tmp [ path_len - 1 ] = = PHP_DIR_SEPARATOR ) {
2003-07-31 01:55:06 +08:00
if ( resolved_name [ resolved_name_len - 1 ] ! = PHP_DIR_SEPARATOR ) {
2004-02-11 00:08:54 +08:00
resolved_name [ resolved_name_len ] = PHP_DIR_SEPARATOR ;
2003-07-31 01:55:06 +08:00
resolved_name [ + + resolved_name_len ] = ' \0 ' ;
}
2002-10-05 06:16:16 +08:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
/* Check the path */
2005-07-16 20:21:34 +08:00
# if defined(PHP_WIN32) || defined(NETWARE)
2002-09-23 02:30:38 +08:00
if ( strncasecmp ( resolved_basedir , resolved_name , resolved_basedir_len ) = = 0 ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
# else
2002-09-23 02:30:38 +08:00
if ( strncmp ( resolved_basedir , resolved_name , resolved_basedir_len ) = = 0 ) {
1999-06-16 05:51:00 +08:00
# endif
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
/* File is in the right directory */
return 0 ;
1999-04-08 05:05:13 +08:00
} else {
2007-06-01 21:35:23 +08:00
/* /openbasedir/ and /openbasedir are the same directory */
if ( resolved_basedir_len = = ( resolved_name_len + 1 ) & & resolved_basedir [ resolved_basedir_len - 1 ] = = PHP_DIR_SEPARATOR ) {
# if defined(PHP_WIN32) || defined(NETWARE)
if ( strncasecmp ( resolved_basedir , resolved_name , resolved_name_len ) = = 0 ) {
# else
if ( strncmp ( resolved_basedir , resolved_name , resolved_name_len ) = = 0 ) {
# endif
return 0 ;
}
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
return - 1 ;
1999-04-08 05:05:13 +08:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
} else {
/* Unable to resolve the real path, return -1 */
return - 1 ;
}
}
2001-06-06 21:06:12 +08:00
/* }}} */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
2003-06-24 21:56:25 +08:00
PHPAPI int php_check_open_basedir ( const char * path TSRMLS_DC )
{
2003-06-24 22:36:01 +08:00
return php_check_open_basedir_ex ( path , 1 TSRMLS_CC ) ;
2003-06-24 21:56:25 +08:00
}
2001-06-06 21:06:12 +08:00
/* {{{ php_check_open_basedir
*/
2003-06-24 21:56:25 +08:00
PHPAPI int php_check_open_basedir_ex ( const char * path , int warn TSRMLS_DC )
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
{
/* Only check when open_basedir is available */
if ( PG ( open_basedir ) & & * PG ( open_basedir ) ) {
char * pathbuf ;
char * ptr ;
char * end ;
pathbuf = estrdup ( PG ( open_basedir ) ) ;
ptr = pathbuf ;
while ( ptr & & * ptr ) {
2001-07-16 21:31:55 +08:00
end = strchr ( ptr , DEFAULT_DIR_SEPARATOR ) ;
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
if ( end ! = NULL ) {
* end = ' \0 ' ;
end + + ;
}
2001-07-28 19:36:37 +08:00
if ( php_check_specific_open_basedir ( ptr , path TSRMLS_CC ) = = 0 ) {
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
efree ( pathbuf ) ;
1999-04-08 05:05:13 +08:00
return 0 ;
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
ptr = end ;
1999-04-08 05:05:13 +08:00
}
2003-06-24 21:56:25 +08:00
if ( warn ) {
2007-10-09 16:40:36 +08:00
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s) " , path , PG ( open_basedir ) ) ;
2003-06-24 21:56:25 +08:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
efree ( pathbuf ) ;
2000-08-09 00:36:25 +08:00
errno = EPERM ; /* we deny permission to open it */
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
return - 1 ;
1999-04-08 05:05:13 +08:00
}
* fixed some #if/#ifdef issues
* hand-patched in php3 changes from 3.0.6 to HEAD in these files:
fopen-wrappers.[ch] ext/standard/file.[ch] ext/standard/fsock.[ch]
ext/standard/php3_string.h ext/standard/string.c
* added some new file/socket macros for more readable code:
FP_FGETS(buf,len,sock,fp,issock)
FP_FREAD(buf,len,sock,fp,issock)
FP_FEOF(sock,fp,issock)
FP_FGETC(sock,fp,issock)
1999-06-17 01:06:53 +08:00
/* Nothing to check... */
return 0 ;
1999-04-08 05:05:13 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-04-08 05:05:13 +08:00
2002-02-02 04:04:14 +08:00
/* {{{ php_check_safe_mode_include_dir
*/
2006-07-01 19:35:34 +08:00
PHPAPI int php_check_safe_mode_include_dir ( const char * path TSRMLS_DC )
2002-02-02 04:04:14 +08:00
{
2003-07-22 09:32:01 +08:00
if ( PG ( safe_mode ) ) {
if ( PG ( safe_mode_include_dir ) & & * PG ( safe_mode_include_dir ) ) {
char * pathbuf ;
char * ptr ;
char * end ;
char resolved_name [ MAXPATHLEN ] ;
2002-02-02 04:04:14 +08:00
2003-07-22 09:32:01 +08:00
/* Resolve the real path into resolved_name */
2007-10-09 16:40:36 +08:00
if ( expand_filepath ( path , resolved_name TSRMLS_CC ) = = NULL ) {
2003-07-22 09:32:01 +08:00
return - 1 ;
2007-10-09 16:40:36 +08:00
}
2003-07-22 09:32:01 +08:00
pathbuf = estrdup ( PG ( safe_mode_include_dir ) ) ;
ptr = pathbuf ;
2002-02-02 04:04:14 +08:00
2003-07-22 09:32:01 +08:00
while ( ptr & & * ptr ) {
end = strchr ( ptr , DEFAULT_DIR_SEPARATOR ) ;
if ( end ! = NULL ) {
* end = ' \0 ' ;
end + + ;
}
2002-02-02 04:04:14 +08:00
2003-07-22 09:32:01 +08:00
/* Check the path */
2002-02-02 04:04:14 +08:00
# ifdef PHP_WIN32
2003-07-22 09:32:01 +08:00
if ( strncasecmp ( ptr , resolved_name , strlen ( ptr ) ) = = 0 )
2002-02-02 04:04:14 +08:00
# else
2003-07-22 09:32:01 +08:00
if ( strncmp ( ptr , resolved_name , strlen ( ptr ) ) = = 0 )
2002-02-02 04:04:14 +08:00
# endif
2003-07-22 09:32:01 +08:00
{
/* File is in the right directory */
efree ( pathbuf ) ;
return 0 ;
}
2002-02-02 04:04:14 +08:00
2003-07-22 09:32:01 +08:00
ptr = end ;
}
efree ( pathbuf ) ;
2002-02-02 04:04:14 +08:00
}
return - 1 ;
}
/* Nothing to check... */
2002-09-29 00:27:10 +08:00
return 0 ;
2002-02-02 04:04:14 +08:00
}
/* }}} */
2001-06-06 21:06:12 +08:00
/* {{{ php_fopen_and_set_opened_path
*/
2006-07-01 19:35:34 +08:00
static FILE * php_fopen_and_set_opened_path ( const char * path , const char * mode , char * * opened_path TSRMLS_DC )
2000-08-17 03:26:21 +08:00
{
2001-07-11 02:49:47 +08:00
FILE * fp ;
2000-08-17 03:26:21 +08:00
2001-07-31 14:28:05 +08:00
if ( php_check_open_basedir ( ( char * ) path TSRMLS_CC ) ) {
2001-07-11 02:49:47 +08:00
return NULL ;
}
fp = VCWD_FOPEN ( path , mode ) ;
if ( fp & & opened_path ) {
2001-08-05 09:43:02 +08:00
* opened_path = expand_filepath ( path , NULL TSRMLS_CC ) ;
2001-07-11 02:49:47 +08:00
}
return fp ;
2000-08-17 03:26:21 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
2000-08-17 03:26:21 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_fopen_primary_script
*/
2001-07-31 15:09:49 +08:00
PHPAPI int php_fopen_primary_script ( zend_file_handle * file_handle TSRMLS_DC )
1999-04-08 05:05:13 +08:00
{
FILE * fp ;
2006-11-10 18:55:26 +08:00
# ifndef PHP_WIN32
1999-04-08 05:05:13 +08:00
struct stat st ;
2006-11-10 18:55:26 +08:00
# endif
2000-10-03 23:05:50 +08:00
char * path_info , * filename ;
2000-06-16 08:56:38 +08:00
int length ;
1999-04-08 05:05:13 +08:00
2000-06-16 08:56:38 +08:00
filename = SG ( request_info ) . path_translated ;
1999-06-16 05:51:00 +08:00
path_info = SG ( request_info ) . request_uri ;
1999-04-08 05:05:13 +08:00
# if HAVE_PWD_H
2007-01-12 09:46:11 +08:00
if ( PG ( user_dir ) & & * PG ( user_dir ) & & path_info & & ' / ' = = path_info [ 0 ] & & ' ~ ' = = path_info [ 1 ] ) {
1999-04-08 05:05:13 +08:00
char * s = strchr ( path_info + 2 , ' / ' ) ;
2000-06-16 08:56:38 +08:00
filename = NULL ; /* discard the original filename, it must not be used */
if ( s ) { /* if there is no path name after the file, do not bother */
2007-01-12 09:46:11 +08:00
char user [ 32 ] ; /* to try open the directory */
struct passwd * pw ;
# if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
2007-01-12 22:31:28 +08:00
struct passwd pwstruc ;
2007-01-12 09:46:11 +08:00
long pwbuflen = sysconf ( _SC_GETPW_R_SIZE_MAX ) ;
char * pwbuf ;
if ( pwbuflen < 1 ) {
return FAILURE ;
}
2007-10-09 16:40:36 +08:00
2007-01-12 09:46:11 +08:00
pwbuf = emalloc ( pwbuflen ) ;
# endif
2000-06-16 08:56:38 +08:00
length = s - ( path_info + 2 ) ;
2007-01-12 09:46:11 +08:00
if ( length > ( int ) sizeof ( user ) - 1 ) {
2000-06-16 08:56:38 +08:00
length = sizeof ( user ) - 1 ;
2007-01-12 09:46:11 +08:00
}
2000-06-16 08:56:38 +08:00
memcpy ( user , path_info + 2 , length ) ;
user [ length ] = ' \0 ' ;
2007-01-12 09:46:11 +08:00
# if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
if ( getpwnam_r ( user , & pwstruc , pwbuf , pwbuflen , & pw ) ) {
efree ( pwbuf ) ;
return FAILURE ;
}
# else
1999-04-08 05:05:13 +08:00
pw = getpwnam ( user ) ;
2007-01-12 09:46:11 +08:00
# endif
1999-04-08 05:05:13 +08:00
if ( pw & & pw - > pw_dir ) {
2007-10-09 16:40:36 +08:00
spprintf ( & filename , 0 , " %s%c%s%c%s " , pw - > pw_dir , PHP_DIR_SEPARATOR , PG ( user_dir ) , PHP_DIR_SEPARATOR , s + 1 ) ; /* Safe */
2007-02-24 10:17:47 +08:00
STR_FREE ( SG ( request_info ) . path_translated ) ;
SG ( request_info ) . path_translated = filename ;
1999-04-08 05:05:13 +08:00
}
2007-01-12 17:10:16 +08:00
# if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
efree ( pwbuf ) ;
# endif
1999-04-08 05:05:13 +08:00
}
} else
# endif
2000-06-16 09:23:03 +08:00
if ( PG ( doc_root ) & & path_info ) {
length = strlen ( PG ( doc_root ) ) ;
2000-09-01 03:49:36 +08:00
if ( IS_ABSOLUTE_PATH ( PG ( doc_root ) , length ) ) {
2000-06-16 09:23:03 +08:00
filename = emalloc ( length + strlen ( path_info ) + 2 ) ;
if ( filename ) {
memcpy ( filename , PG ( doc_root ) , length ) ;
if ( ! IS_SLASH ( filename [ length - 1 ] ) ) { /* length is never 0 */
2000-08-21 03:56:24 +08:00
filename [ length + + ] = PHP_DIR_SEPARATOR ;
2000-06-16 09:23:03 +08:00
}
if ( IS_SLASH ( path_info [ 0 ] ) ) {
length - - ;
}
strcpy ( filename + length , path_info ) ;
STR_FREE ( SG ( request_info ) . path_translated ) ;
SG ( request_info ) . path_translated = filename ;
}
1999-04-08 05:05:13 +08:00
}
2000-06-16 09:23:03 +08:00
} /* if doc_root && path_info */
2000-06-16 08:56:38 +08:00
if ( ! filename ) {
1999-06-27 03:14:26 +08:00
/* we have to free SG(request_info).path_translated here because
2007-10-09 16:40:36 +08:00
* php_destroy_request_info assumes that it will get
* freed when the include_names hash is emptied , but
* we ' re not adding it in this case */
1999-06-27 03:14:26 +08:00
STR_FREE ( SG ( request_info ) . path_translated ) ;
SG ( request_info ) . path_translated = NULL ;
2001-07-21 23:11:30 +08:00
return FAILURE ;
1999-04-08 05:05:13 +08:00
}
2001-04-30 20:45:02 +08:00
fp = VCWD_FOPEN ( filename , " rb " ) ;
1999-04-08 05:05:13 +08:00
2006-11-10 18:55:26 +08:00
# ifndef PHP_WIN32
1999-04-08 05:05:13 +08:00
/* refuse to open anything that is not a regular file */
if ( fp & & ( 0 > fstat ( fileno ( fp ) , & st ) | | ! S_ISREG ( st . st_mode ) ) ) {
fclose ( fp ) ;
fp = NULL ;
}
2006-11-10 18:55:26 +08:00
# endif
1999-04-08 05:05:13 +08:00
if ( ! fp ) {
1999-06-27 03:14:26 +08:00
STR_FREE ( SG ( request_info ) . path_translated ) ; /* for same reason as above */
2002-12-02 05:28:27 +08:00
SG ( request_info ) . path_translated = NULL ;
2001-07-21 23:11:30 +08:00
return FAILURE ;
1999-04-08 05:05:13 +08:00
}
2001-07-21 23:11:30 +08:00
2001-08-05 09:43:02 +08:00
file_handle - > opened_path = expand_filepath ( filename , NULL TSRMLS_CC ) ;
2001-07-21 23:11:30 +08:00
2007-10-09 16:40:36 +08:00
if ( ! ( SG ( options ) & SAPI_OPTION_NO_CHDIR ) ) {
2001-04-30 20:45:02 +08:00
VCWD_CHDIR_FILE ( filename ) ;
2007-10-09 16:40:36 +08:00
}
2000-06-16 08:56:38 +08:00
SG ( request_info ) . path_translated = filename ;
1999-04-08 05:05:13 +08:00
2001-07-21 23:11:30 +08:00
file_handle - > filename = SG ( request_info ) . path_translated ;
file_handle - > free_filename = 0 ;
file_handle - > handle . fp = fp ;
2001-11-27 02:57:44 +08:00
file_handle - > type = ZEND_HANDLE_FP ;
2001-07-21 23:11:30 +08:00
return SUCCESS ;
1999-04-08 05:05:13 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-04-08 05:05:13 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_fopen_with_path
1999-04-08 05:05:13 +08:00
* Tries to open a file with a PATH - style list of directories .
* If the filename starts with " . " or " / " , the path is ignored .
*/
2006-07-01 19:35:34 +08:00
PHPAPI FILE * php_fopen_with_path ( const char * filename , const char * mode , const char * path , char * * opened_path TSRMLS_DC )
1999-04-08 05:05:13 +08:00
{
char * pathbuf , * ptr , * end ;
2001-07-14 02:21:21 +08:00
char * exec_fname ;
2000-12-17 04:52:43 +08:00
char trypath [ MAXPATHLEN ] ;
1999-04-08 05:05:13 +08:00
struct stat sb ;
2000-08-19 07:03:49 +08:00
FILE * fp ;
2001-07-14 02:21:21 +08:00
int path_length ;
2000-09-15 04:47:35 +08:00
int filename_length ;
2001-07-14 02:21:21 +08:00
int exec_fname_length ;
1999-04-08 05:05:13 +08:00
if ( opened_path ) {
* opened_path = NULL ;
}
2007-10-09 16:40:36 +08:00
if ( ! filename ) {
2001-07-14 02:21:21 +08:00
return NULL ;
}
1999-12-06 23:30:44 +08:00
2000-09-17 13:52:26 +08:00
filename_length = strlen ( filename ) ;
2007-10-09 16:40:36 +08:00
2001-07-14 02:21:21 +08:00
/* Relative path open */
if ( * filename = = ' . ' ) {
if ( PG ( safe_mode ) & & ( ! php_checkuid ( filename , mode , CHECKUID_CHECK_MODE_PARAM ) ) ) {
return NULL ;
}
2001-07-31 15:09:49 +08:00
return php_fopen_and_set_opened_path ( filename , mode , opened_path TSRMLS_CC ) ;
2001-07-14 02:21:21 +08:00
}
2007-10-09 16:40:36 +08:00
2001-07-14 02:21:21 +08:00
/*
* files in safe_mode_include_dir ( or subdir ) are excluded from
* safe mode GID / UID checks
*/
2007-10-09 16:40:36 +08:00
2001-07-14 02:21:21 +08:00
/* Absolute path open */
if ( IS_ABSOLUTE_PATH ( filename , filename_length ) ) {
2007-10-09 16:40:36 +08:00
if ( php_check_safe_mode_include_dir ( filename TSRMLS_CC ) = = 0 ) {
2002-02-02 04:04:14 +08:00
/* filename is in safe_mode_include_dir (or subdir) */
return php_fopen_and_set_opened_path ( filename , mode , opened_path TSRMLS_CC ) ;
2007-10-09 16:40:36 +08:00
}
if ( PG ( safe_mode ) & & ( ! php_checkuid ( filename , mode , CHECKUID_CHECK_MODE_PARAM ) ) ) {
1999-04-08 05:05:13 +08:00
return NULL ;
2007-10-09 16:40:36 +08:00
}
2001-07-31 15:09:49 +08:00
return php_fopen_and_set_opened_path ( filename , mode , opened_path TSRMLS_CC ) ;
1999-04-08 05:05:13 +08:00
}
2000-09-15 04:47:35 +08:00
1999-04-08 05:05:13 +08:00
if ( ! path | | ( path & & ! * path ) ) {
2000-11-03 07:30:48 +08:00
if ( PG ( safe_mode ) & & ( ! php_checkuid ( filename , mode , CHECKUID_CHECK_MODE_PARAM ) ) ) {
1999-04-08 05:05:13 +08:00
return NULL ;
}
2001-07-31 15:09:49 +08:00
return php_fopen_and_set_opened_path ( filename , mode , opened_path TSRMLS_CC ) ;
1999-04-08 05:05:13 +08:00
}
2001-07-14 02:21:21 +08:00
/* check in provided path */
/* append the calling scripts' current working directory
* as a fall back case
*/
2001-07-30 16:24:42 +08:00
if ( zend_is_executing ( TSRMLS_C ) ) {
2001-07-27 18:16:41 +08:00
exec_fname = zend_get_executed_filename ( TSRMLS_C ) ;
2001-07-15 20:24:06 +08:00
exec_fname_length = strlen ( exec_fname ) ;
path_length = strlen ( path ) ;
2001-07-14 02:21:21 +08:00
2001-07-16 21:48:07 +08:00
while ( ( - - exec_fname_length > = 0 ) & & ! IS_SLASH ( exec_fname [ exec_fname_length ] ) ) ;
2007-10-09 16:40:36 +08:00
if ( ( exec_fname & & exec_fname [ 0 ] = = ' [ ' ) | | exec_fname_length < = 0 ) {
2001-07-16 21:48:07 +08:00
/* [no active file] or no path */
pathbuf = estrdup ( path ) ;
2007-10-09 16:40:36 +08:00
} else {
pathbuf = ( char * ) emalloc ( exec_fname_length + path_length + 1 + 1 ) ;
2001-07-16 21:48:07 +08:00
memcpy ( pathbuf , path , path_length ) ;
pathbuf [ path_length ] = DEFAULT_DIR_SEPARATOR ;
2007-10-09 16:40:36 +08:00
memcpy ( pathbuf + path_length + 1 , exec_fname , exec_fname_length ) ;
pathbuf [ path_length + exec_fname_length + 1 ] = ' \0 ' ;
2001-07-15 20:24:06 +08:00
}
} else {
pathbuf = estrdup ( path ) ;
}
1999-04-08 05:05:13 +08:00
ptr = pathbuf ;
while ( ptr & & * ptr ) {
2001-07-16 21:31:55 +08:00
end = strchr ( ptr , DEFAULT_DIR_SEPARATOR ) ;
1999-04-08 05:05:13 +08:00
if ( end ! = NULL ) {
* end = ' \0 ' ;
end + + ;
}
snprintf ( trypath , MAXPATHLEN , " %s/%s " , ptr , filename ) ;
1999-04-10 20:17:20 +08:00
if ( PG ( safe_mode ) ) {
2002-02-02 04:04:14 +08:00
if ( VCWD_STAT ( trypath , & sb ) = = 0 ) {
/* file exists ... check permission */
2007-10-09 16:40:36 +08:00
if ( php_check_safe_mode_include_dir ( trypath TSRMLS_CC ) = = 0 | |
php_checkuid ( trypath , mode , CHECKUID_CHECK_MODE_PARAM )
) {
2002-02-02 04:04:14 +08:00
/* UID ok, or trypath is in safe_mode_include_dir */
fp = php_fopen_and_set_opened_path ( trypath , mode , opened_path TSRMLS_CC ) ;
2007-10-09 16:40:36 +08:00
} else {
2002-02-02 04:04:14 +08:00
fp = NULL ;
2007-10-09 16:40:36 +08:00
}
1999-04-08 05:05:13 +08:00
efree ( pathbuf ) ;
2002-02-02 04:04:14 +08:00
return fp ;
1999-04-08 05:05:13 +08:00
}
}
2001-07-31 15:09:49 +08:00
fp = php_fopen_and_set_opened_path ( trypath , mode , opened_path TSRMLS_CC ) ;
2000-08-19 07:03:49 +08:00
if ( fp ) {
1999-04-08 05:05:13 +08:00
efree ( pathbuf ) ;
2000-08-19 07:03:49 +08:00
return fp ;
1999-04-08 05:05:13 +08:00
}
ptr = end ;
2001-07-14 02:21:21 +08:00
} /* end provided path */
2001-07-11 04:38:39 +08:00
1999-04-08 05:05:13 +08:00
efree ( pathbuf ) ;
2001-07-14 02:21:21 +08:00
return NULL ;
1999-04-08 05:05:13 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
2007-10-09 16:40:36 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ php_strip_url_passwd
*/
1999-12-18 03:16:50 +08:00
PHPAPI char * php_strip_url_passwd ( char * url )
1999-04-08 05:05:13 +08:00
{
2003-03-27 07:01:39 +08:00
register char * p , * url_start ;
2007-10-09 16:40:36 +08:00
2003-03-27 07:01:39 +08:00
if ( url = = NULL ) {
2003-03-27 07:03:48 +08:00
return " " ;
2003-03-27 07:01:39 +08:00
}
2007-10-09 16:40:36 +08:00
2003-03-27 07:01:39 +08:00
p = url ;
2007-10-09 16:40:36 +08:00
1999-04-08 05:05:13 +08:00
while ( * p ) {
2007-10-09 16:40:36 +08:00
if ( * p = = ' : ' & & * ( p + 1 ) = = ' / ' & & * ( p + 2 ) = = ' / ' ) {
1999-04-08 05:05:13 +08:00
/* found protocol */
2007-10-09 16:40:36 +08:00
url_start = p = p + 3 ;
1999-04-08 05:05:13 +08:00
while ( * p ) {
2007-10-09 16:40:36 +08:00
if ( * p = = ' @ ' ) {
1999-04-08 05:05:13 +08:00
int i ;
2007-10-09 16:40:36 +08:00
for ( i = 0 ; i < 3 & & url_start < p ; i + + , url_start + + ) {
1999-04-08 05:05:13 +08:00
* url_start = ' . ' ;
}
for ( ; * p ; p + + ) {
* url_start + + = * p ;
}
* url_start = 0 ;
break ;
}
p + + ;
}
return url ;
}
p + + ;
}
return url ;
}
2001-06-06 21:06:12 +08:00
/* }}} */
1999-04-08 05:05:13 +08:00
2001-06-06 21:06:12 +08:00
/* {{{ expand_filepath
*/
2001-08-05 09:43:02 +08:00
PHPAPI char * expand_filepath ( const char * filepath , char * real_path TSRMLS_DC )
2000-04-10 03:54:50 +08:00
{
cwd_state new_state ;
2000-12-17 04:52:43 +08:00
char cwd [ MAXPATHLEN ] ;
2007-10-09 16:40:36 +08:00
int copy_len ;
2000-04-10 03:54:50 +08:00
2007-10-09 16:40:36 +08:00
if ( ! filepath [ 0 ] ) {
return NULL ;
} else if ( IS_ABSOLUTE_PATH ( filepath , strlen ( filepath ) ) ) {
cwd [ 0 ] = ' \0 ' ;
} else {
const char * iam = SG ( request_info ) . path_translated ;
char * result = VCWD_GETCWD ( cwd , MAXPATHLEN ) ;
if ( ! result & & ( iam ! = filepath ) ) {
int fdtest = - 1 ;
fdtest = VCWD_OPEN ( filepath , O_RDONLY ) ;
if ( fdtest ! = - 1 ) {
/* return a relative file path if for any reason
* we cannot cannot getcwd ( ) and the requested ,
* relatively referenced file is accessible */
copy_len = strlen ( filepath ) > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : strlen ( filepath ) ;
real_path = estrndup ( filepath , copy_len ) ;
2007-12-27 10:09:26 +08:00
close ( fdtest ) ;
2007-10-09 16:40:36 +08:00
return real_path ;
2007-10-09 18:05:08 +08:00
} else {
cwd [ 0 ] = ' \0 ' ;
2007-10-09 16:40:36 +08:00
}
2007-10-09 18:05:08 +08:00
} else if ( ! result ) {
2007-10-09 16:40:36 +08:00
cwd [ 0 ] = ' \0 ' ;
}
}
2000-04-10 03:54:50 +08:00
new_state . cwd = strdup ( cwd ) ;
new_state . cwd_length = strlen ( cwd ) ;
2007-10-09 16:40:36 +08:00
if ( virtual_file_ex ( & new_state , filepath , NULL , CWD_FILEPATH ) ) {
2000-10-13 03:58:20 +08:00
free ( new_state . cwd ) ;
2000-08-09 00:36:25 +08:00
return NULL ;
}
2007-10-09 16:40:36 +08:00
if ( real_path ) {
copy_len = new_state . cwd_length > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : new_state . cwd_length ;
2001-07-21 23:11:30 +08:00
memcpy ( real_path , new_state . cwd , copy_len ) ;
2007-10-09 16:40:36 +08:00
real_path [ copy_len ] = ' \0 ' ;
2000-08-09 00:36:25 +08:00
} else {
2000-09-01 06:24:20 +08:00
real_path = estrndup ( new_state . cwd , new_state . cwd_length ) ;
2000-08-09 00:36:25 +08:00
}
2000-10-13 03:58:20 +08:00
free ( new_state . cwd ) ;
2000-08-09 00:36:25 +08:00
return real_path ;
2000-04-10 03:54:50 +08:00
}
2001-06-06 21:06:12 +08:00
/* }}} */
2000-04-10 03:54:50 +08:00
1999-04-08 05:05:13 +08:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
2001-09-09 21:29:31 +08:00
* vim600 : sw = 4 ts = 4 fdm = marker
* vim < 600 : sw = 4 ts = 4
1999-04-08 05:05:13 +08:00
*/