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

Reply via email to