Hi, I want your comments. This patch adds safe_mode awareness to the ftp extension. It was done against the 4.2.0 tree because there must be some changes in the extension because of streams and so i wanted to ensure that it is working first.
This patch modifies: is_uploaded_file : works now also on files retrieved via ftp_get move_uploaded_file : works now also on files retrieved via ftp_get ftp_get: checks safe_mode and openbasedir restrictions and adds downloaded files to a hashtable ftp_put: checks safe_mode and openbasedir restrictions php_checkuid: handles ftp_uploaded files in the same way rfc1867 uploaded files are handled + FIX: correct output if file does not exist sapi_deactivate: will remove uploaded files Stefan PS: Due to the changes done a few days ago in php_checkuid there will be a lot of bug reports (i guess) because checkuid is now really strict
diff -ur php420_mar171200/ext/ftp/php_ftp.c php420/ext/ftp/php_ftp.c --- php420_mar171200/ext/ftp/php_ftp.c Thu Feb 28 09:26:10 2002 +++ php420/ext/ftp/php_ftp.c Sun Mar 17 15:14:18 2002 @@ -81,6 +81,19 @@ ZEND_GET_MODULE(php_ftp) #endif +static int unlink_filename(char **filename TSRMLS_DC) +{ + VCWD_UNLINK(*filename); + return 0; +} + +void destroy_ftp_uploaded_files_hash(TSRMLS_D) +{ + zend_hash_apply(SG(ftp_uploaded_files), (apply_func_t) unlink_filename +TSRMLS_CC); + zend_hash_destroy(SG(ftp_uploaded_files)); + FREE_HASHTABLE(SG(ftp_uploaded_files)); +} + static void ftp_destructor_ftpbuf(zend_rsrc_list_entry *rsrc TSRMLS_DC) { ftpbuf_t *ftp = (ftpbuf_t *)rsrc->ptr; @@ -413,6 +426,7 @@ FILEP(fp, z_file); XTYPE(xtype, mode); + if (!ftp_get(ftp, fp, file, xtype) || ferror(fp)) { php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf); RETURN_FALSE; @@ -468,6 +482,14 @@ ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); XTYPE(xtype, mode); + if (PG(safe_mode) && (!php_checkuid(local, NULL, +CHECKUID_CHECK_FILE_AND_DIR))) { + RETURN_FALSE; + } + + if (php_check_open_basedir(local TSRMLS_CC)) { + RETURN_FALSE; + } + /* get to temporary file, so if there is an error, no existing * file gets clobbered */ @@ -482,6 +504,11 @@ RETURN_FALSE; } + if (!SG(ftp_uploaded_files)) { + ALLOC_HASHTABLE(SG(ftp_uploaded_files)); + zend_hash_init(SG(ftp_uploaded_files), 5, NULL, (dtor_func_t) +free_estring, 0); + } + #ifdef PHP_WIN32 if ((outfp = VCWD_FOPEN(local, "wb")) == NULL) { #else @@ -503,6 +530,9 @@ RETURN_FALSE; } + local=estrdup(local); + zend_hash_add(SG(ftp_uploaded_files), local, strlen(local)+1, &local, +sizeof(char *), NULL); + fclose(tmpfp); fclose(outfp); @@ -556,6 +586,14 @@ ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf); XTYPE(xtype, mode); + + if (PG(safe_mode) && (!php_checkuid(local, NULL, +CHECKUID_CHECK_FILE_AND_DIR))) { + RETURN_FALSE; + } + + if (php_check_open_basedir(local TSRMLS_CC)) { + RETURN_FALSE; + } #ifdef PHP_WIN32 if ((infp = VCWD_FOPEN(local, "rb")) == NULL) { diff -ur php420_mar171200/ext/ftp/php_ftp.h php420/ext/ftp/php_ftp.h --- php420_mar171200/ext/ftp/php_ftp.h Thu Feb 28 09:26:10 2002 +++ php420/ext/ftp/php_ftp.h Sun Mar 17 12:36:34 2002 @@ -58,6 +58,8 @@ #define phpext_ftp_ptr php_ftp_module_ptr +void destroy_ftp_uploaded_files_hash(TSRMLS_D); + #else #define php_ftp_module_ptr NULL #endif /* HAVE_FTP */ diff -ur php420_mar171200/ext/standard/basic_functions.c php420/ext/standard/basic_functions.c --- php420_mar171200/ext/standard/basic_functions.c Fri Mar 1 04:05:49 2002 +++ php420/ext/standard/basic_functions.c Sun Mar 17 15:18:46 2002 @@ -2309,12 +2309,17 @@ } /* {{{ proto bool is_uploaded_file(string path) - Check if file was created by rfc1867 upload */ + Check if file was created by rfc1867 or ftp upload */ PHP_FUNCTION(is_uploaded_file) { zval **path; +#ifdef HAVE_FTP + if ((!SG(ftp_uploaded_files)) && + (!SG(rfc1867_uploaded_files))) { +#else /* HAVE_FTP */ if (!SG(rfc1867_uploaded_files)) { +#endif /* HAVE_FTP */ RETURN_FALSE; } @@ -2324,6 +2329,11 @@ convert_to_string_ex(path); +#ifdef HAVE_FTP + if (zend_hash_exists(SG(ftp_uploaded_files), Z_STRVAL_PP(path), +Z_STRLEN_PP(path)+1)) { + RETURN_TRUE; + } else +#endif /* HAVE_FTP */ if (zend_hash_exists(SG(rfc1867_uploaded_files), Z_STRVAL_PP(path), Z_STRLEN_PP(path)+1)) { RETURN_TRUE; } else { @@ -2338,20 +2348,31 @@ { zval **path, **new_path; zend_bool successful = 0; - +#ifdef HAVE_FTP + zend_bool ftpupload = 0; + + if ((!SG(ftp_uploaded_files)) && + (!SG(rfc1867_uploaded_files))) { +#else /* HAVE_FTP */ if (!SG(rfc1867_uploaded_files)) { +#endif RETURN_FALSE; } - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &path, &new_path) != SUCCESS) { ZEND_WRONG_PARAM_COUNT(); } convert_to_string_ex(path); convert_to_string_ex(new_path); +#ifdef HAVE_FTP + if (zend_hash_exists(SG(ftp_uploaded_files), Z_STRVAL_PP(path), +Z_STRLEN_PP(path)+1)) { + ftpupload = 1; + } else +#else /* HAVE_FTP */ if (!zend_hash_exists(SG(rfc1867_uploaded_files), Z_STRVAL_PP(path), Z_STRLEN_PP(path)+1)) { RETURN_FALSE; } +#endif /* HAVE_FTP */ if (PG(safe_mode) && (!php_checkuid(Z_STRVAL_PP(new_path), NULL, CHECKUID_CHECK_FILE_AND_DIR))) { RETURN_FALSE; @@ -2367,7 +2388,15 @@ } if (successful) { +#ifdef HAVE_FTP + if (ftpupload) { + zend_hash_del(SG(ftp_uploaded_files), Z_STRVAL_PP(path), +Z_STRLEN_PP(path)+1); + } else { + zend_hash_del(SG(rfc1867_uploaded_files), Z_STRVAL_PP(path), +Z_STRLEN_PP(path)+1); + } +#else /* HAVE_FTP */ zend_hash_del(SG(rfc1867_uploaded_files), Z_STRVAL_PP(path), Z_STRLEN_PP(path)+1); +#endif /* HAVE_FTP */ } else { php_error(E_WARNING, "Unable to move '%s' to '%s'", Z_STRVAL_PP(path), Z_STRVAL_PP(new_path)); } Only in php420_mar171200/ext/standard/tests/aggregation: aggregate.lib.php diff -ur php420_mar171200/main/SAPI.c php420/main/SAPI.c --- php420_mar171200/main/SAPI.c Mon Jan 14 14:36:54 2002 +++ php420/main/SAPI.c Sun Mar 17 15:15:54 2002 @@ -300,6 +300,9 @@ SG(request_info).headers_only = 0; } SG(rfc1867_uploaded_files) = NULL; +#ifdef HAVE_FTP + SG(ftp_uploaded_files) = NULL; +#endif /* HAVE_FTP */ if (SG(server_context)) { if (SG(request_info).request_method @@ -358,6 +361,11 @@ if (SG(rfc1867_uploaded_files)) { destroy_uploaded_files_hash(TSRMLS_C); } +#ifdef HAVE_FTP + if (SG(ftp_uploaded_files)) { + destroy_ftp_uploaded_files_hash(TSRMLS_C); + } +#endif } diff -ur php420_mar171200/main/SAPI.h php420/main/SAPI.h --- php420_mar171200/main/SAPI.h Thu Feb 28 09:27:02 2002 +++ php420/main/SAPI.h Sun Mar 17 13:59:21 2002 @@ -114,6 +114,9 @@ char *default_mimetype; char *default_charset; HashTable *rfc1867_uploaded_files; +#ifdef HAVE_FTP + HashTable *ftp_uploaded_files; +#endif /* HAVE_FTP */ long post_max_size; int options; } sapi_globals_struct; diff -ur php420_mar171200/main/safe_mode.c php420/main/safe_mode.c --- php420_mar171200/main/safe_mode.c Thu Mar 14 20:17:23 2002 +++ php420/main/safe_mode.c Sun Mar 17 14:55:55 2002 @@ -46,7 +46,7 @@ PHPAPI int php_checkuid(const char *filename, char *fopen_mode, int mode) { struct stat sb; - int ret; + int ret, nofile=0; long uid=0L, gid=0L, duid=0L, dgid=0L; char path[MAXPATHLEN]; char *s; @@ -86,6 +86,7 @@ php_error(E_WARNING, "Unable to access %s", filename); return 1; } + nofile = 1; } else { uid = sb.st_uid; gid = sb.st_gid; @@ -140,6 +141,13 @@ return 1; } } +#ifdef HAVE_FTP + if (SG(ftp_uploaded_files)) { + if (zend_hash_exists(SG(ftp_uploaded_files), (char *) +filename, strlen(filename)+1)) { + return 1; + } + } +#endif /* HAVE_FTP */ } } @@ -150,6 +158,13 @@ *s = 0; } } + + if (nofile) { + uid = duid; + gid = dgid; + filename = path; + } + 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 Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php