From 133c226f569c9e5bfc5290cbb360c01a0994a21f Mon Sep 17 00:00:00 2001 From: Pierre Joye Date: Wed, 14 Mar 2007 11:22:13 +0000 Subject: [PATCH] - MFB: - rename SAFEMODE_CHECKFILE to OPENBASEDIR_CHECKPATH (can be used without confusing in head without confusion) - Add safemode and open basedir checks in zip:// wrapper (revert Ilia's patch). Bug found by Stefan Esser in his MOPB-20-2007 --- ext/zip/php_zip.c | 18 ++++++++++++++++++ ext/zip/php_zip.h | 10 ++++++++++ ext/zip/zip_stream.c | 10 ++++++++++ 3 files changed, 38 insertions(+) diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 78f268a7fa1..c49e169c01f 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -122,6 +122,11 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil } php_basename(file, file_len, NULL, 0, &file_basename, (unsigned int *)&file_basename_len TSRMLS_CC); + if (OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) { + efree(file_dirname_fullpath); + efree(file_basename); + return 0; + } } /* let see if the path already exists */ if (php_stream_stat_path(file_dirname_fullpath, &ssb) < 0) { @@ -149,6 +154,16 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil return 0; } + /* check again the full path, not sure if it + * is required, does a file can have a different + * safemode status as its parent folder? + */ + if (OPENBASEDIR_CHECKPATH(fullpath)) { + efree(file_dirname_fullpath); + efree(file_basename); + return 0; + } + zf = zip_fopen(za, file, 0); if (zf == NULL) { efree(fullpath); @@ -609,6 +624,9 @@ static PHP_FUNCTION(zip_open) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &filename_zval) == FAILURE) { return; } + if (OPENBASEDIR_CHECKPATH(filename)) { + RETURN_FALSE; + } if (FAILURE == php_stream_path_param_encode(filename_zval, &filename, &filename_len, REPORT_ERRORS, FG(default_context))) { RETURN_FALSE; diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index cbfc9b9502f..f1941519413 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -30,6 +30,16 @@ extern zend_module_entry zip_module_entry; #include "lib/zip.h" +/* {{{ OPENBASEDIR_CHECKPATH(filename) */ +#if (PHP_MAJOR_VERSION < 6) +#define OPENBASEDIR_CHECKPATH(filename) \ + (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC) +#else +#define OPENBASEDIR_CHECKPATH(filename) \ + php_check_open_basedir(filename TSRMLS_CC) +#endif +/* }}} */ + typedef struct _ze_zip_rsrc { struct zip *za; int index_current; diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c index c36df3e4c06..1f305509ea2 100644 --- a/ext/zip/zip_stream.c +++ b/ext/zip/zip_stream.c @@ -12,6 +12,7 @@ #include "ext/standard/file.h" #include "ext/standard/php_string.h" #include "fopen_wrappers.h" +#include "php_zip.h" #include "ext/standard/url.h" @@ -112,6 +113,10 @@ php_stream *php_stream_zip_open(char *filename, char *path, char *mode STREAMS_D } if (filename) { + if (OPENBASEDIR_CHECKPATH(filename)) { + return NULL; + } + /* duplicate to make the stream za independent (esp. for MSHUTDOWN) */ stream_za = zip_open(filename, ZIP_CREATE, &err); if (!stream_za) { @@ -189,6 +194,11 @@ php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper, php_basename(path, path_len - fragment_len, NULL, 0, &file_basename, &file_basename_len TSRMLS_CC); fragment++; + if (OPENBASEDIR_CHECKPATH(file_dirname)) { + efree(file_basename); + return NULL; + } + za = zip_open(file_dirname, ZIP_CREATE, &err); if (za) { zf = zip_fopen(za, fragment, 0);