Skip to content
Permalink
Browse files

Fix 65069: Proper checking of glob stream paths when open_basedir set

  • Loading branch information...
bukka committed Jul 28, 2013
1 parent d4aee10 commit 86cbceff7105a65a4197b4d66fda90060da3ecf5
Showing with 55 additions and 9 deletions.
  1. +22 −0 ext/spl/tests/bug65069.phpt
  2. +33 −9 main/streams/glob_wrapper.c
@@ -0,0 +1,22 @@
--TEST--
Bug #65069: GlobIterator fails to access files inside an open_basedir restricted dir
--FILE--
<?php
ini_set('open_basedir', __DIR__);
$path = (dirname(__DIR__) . '/*/*.php');

This comment has been minimized.

Copy link
@weltling

weltling Jul 29, 2013

I'd suggest to iterate over files that don't change during test, otherwise the gap between glob() call and iterator instantiation might bring this test to fail in parallel test runs.

$std_glob = glob($path);
$spl_glob = array();
try {
$spl_glob_it = new \GlobIterator($path);
foreach ($spl_glob_it as $file_info) {
$spl_glob[] = $file_info->getPathname();
}
} catch (Exception $e) {
var_dump($e->getMessage());
}
echo $std_glob == $spl_glob ? "SUCCESS" : "FAILURE";

This comment has been minimized.

Copy link
@weltling

weltling Jul 29, 2013

comparing arrays with paths might not work on windows where '/' and '' might be mixed

?>
--EXPECT--
SUCCESS
@@ -45,6 +45,9 @@ typedef struct {
size_t path_len;
char *pattern;
size_t pattern_len;
char *basedir_indexmap;
size_t basedir_indexmap_size;
size_t basedir_indexmap_first;
} glob_s_t;

PHPAPI char* _php_glob_stream_get_path(php_stream *stream, int copy, int *plen STREAMS_DC TSRMLS_DC) /* {{{ */
@@ -99,7 +102,7 @@ PHPAPI int _php_glob_stream_get_count(php_stream *stream, int *pflags STREAMS_DC
if (pflags) {
*pflags = pglob->flags;
}
return pglob->glob.gl_pathc;
return pglob->basedir_indexmap ? (int) pglob->basedir_indexmap_size : pglob->glob.gl_pathc;
} else {
if (pflags) {
*pflags = 0;
@@ -146,7 +149,10 @@ static size_t php_glob_stream_read(php_stream *stream, char *buf, size_t count T
/* avoid problems if someone mis-uses the stream */
if (count == sizeof(php_stream_dirent) && pglob) {
if (pglob->index < (size_t)pglob->glob.gl_pathc) {
php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[pglob->index++], pglob->flags & GLOB_APPEND, &path TSRMLS_CC);
php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[pglob->index], pglob->flags & GLOB_APPEND, &path TSRMLS_CC);
do {
pglob->index++;
} while (pglob->basedir_indexmap && pglob->index < (size_t)pglob->glob.gl_pathc && !pglob->basedir_indexmap[pglob->index]);
PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path));
return sizeof(php_stream_dirent);
}
@@ -174,6 +180,9 @@ static int php_glob_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
if (pglob->pattern) {
efree(pglob->pattern);
}
if (pglob->basedir_indexmap) {
efree(pglob->basedir_indexmap);
}
}
efree(stream->abstract);
return 0;
@@ -185,7 +194,7 @@ static int php_glob_stream_rewind(php_stream *stream, off_t offset, int whence,
glob_s_t *pglob = (glob_s_t *)stream->abstract;

if (pglob) {
pglob->index = 0;
pglob->index = pglob->basedir_indexmap_first;
if (pglob->path) {
efree(pglob->path);
pglob->path = NULL;
@@ -210,13 +219,9 @@ static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, char *pat
int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
{
glob_s_t *pglob;
int ret;
int ret, i;
char *tmp, *pos;

if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path TSRMLS_CC)) {
return NULL;
}

if (!strncmp(path, "glob://", sizeof("glob://")-1)) {
path += sizeof("glob://")-1;
if (opened_path) {
@@ -236,6 +241,25 @@ static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, char *pat
}
}

if ((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) {
for (i = 0; i < pglob->glob.gl_pathc; i++) {
if (!php_check_open_basedir_ex(pglob->glob.gl_pathv[i], 0 TSRMLS_CC)) {
if (!pglob->basedir_indexmap) {
pglob->index = i;
pglob->basedir_indexmap = ecalloc(sizeof(char), pglob->glob.gl_pathc);

This comment has been minimized.

Copy link
@weltling

weltling Jul 29, 2013

if (NULL == pglob->basedir_indexmap) ....

pglob->basedir_indexmap_first = i;
}
pglob->basedir_indexmap[i] = 1;
pglob->basedir_indexmap_size++;
}
}
if (!pglob->basedir_indexmap) {

This comment has been minimized.

Copy link
@weltling

weltling Jul 29, 2013

  1. This will throw a warning if glob()'s result is empty
  2. Shouldn't it be an exception in the object context?
globfree(&pglob->glob);
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));
return NULL;
}
}

pos = path;
if ((tmp = strrchr(pos, '/')) != NULL) {
pos = tmp+1;
@@ -252,7 +276,7 @@ static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, char *pat
pglob->flags |= GLOB_APPEND;

if (pglob->glob.gl_pathc) {
php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[0], 1, &tmp TSRMLS_CC);
php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[pglob->index], 1, &tmp TSRMLS_CC);
} else {
php_glob_stream_path_split(pglob, path, 1, &tmp TSRMLS_CC);
}

0 comments on commit 86cbcef

Please sign in to comment.
You can’t perform that action at this time.