diff options
| author | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:38:07 -0400 |
|---|---|---|
| committer | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:38:07 -0400 |
| commit | bb01389fbd53ec1cbcb80d0681a37cca1267891a (patch) | |
| tree | 4783178fca65a5d9071c8df34f2ddc3d31728673 /ext/session | |
| parent | eddbbea4325e602ddc87c545531609132d4f0e3b (diff) | |
| download | php-upstream/5.2.4.tar.gz | |
Imported Upstream version 5.2.4upstream/5.2.4
Diffstat (limited to 'ext/session')
| -rw-r--r-- | ext/session/mod_files.c | 110 | ||||
| -rw-r--r-- | ext/session/session.c | 34 | ||||
| -rw-r--r-- | ext/session/tests/004.phpt | 2 | ||||
| -rw-r--r-- | ext/session/tests/020.phpt | 2 | ||||
| -rw-r--r-- | ext/session/tests/bug41600.phpt | 26 |
5 files changed, 124 insertions, 50 deletions
diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index 9cba9f2ef..e80e51d10 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: mod_files.c,v 1.100.2.3.2.5 2007/03/03 15:07:31 iliaa Exp $ */ +/* $Id: mod_files.c,v 1.100.2.3.2.9 2007/08/23 12:23:59 jani Exp $ */ #include "php.h" @@ -87,9 +87,10 @@ static int ps_files_valid_key(const char *key) len = p - key; - if (len == 0) + if (len == 0) { ret = 0; - + } + return ret; } @@ -101,9 +102,11 @@ static char *ps_files_path_create(char *buf, size_t buflen, ps_files *data, cons int n; key_len = strlen(key); - if (key_len <= data->dirdepth || buflen < - (strlen(data->basedir) + 2 * data->dirdepth + key_len + 5 + sizeof(FILE_PREFIX))) + if (key_len <= data->dirdepth || + buflen < (strlen(data->basedir) + 2 * data->dirdepth + key_len + 5 + sizeof(FILE_PREFIX))) { return NULL; + } + p = key; memcpy(buf, data->basedir, data->basedir_len); n = data->basedir_len; @@ -149,27 +152,49 @@ static void ps_files_open(ps_files *data, const char *key TSRMLS_DC) } ps_files_close(data); - + if (!ps_files_valid_key(key)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,'"); PS(invalid_session_id) = 1; return; } - if (!ps_files_path_create(buf, sizeof(buf), data, key)) + if (!ps_files_path_create(buf, sizeof(buf), data, key)) { return; - + } + data->lastkey = estrdup(key); - - data->fd = VCWD_OPEN_MODE(buf, O_CREAT | O_RDWR | O_BINARY, - data->filemode); - + + data->fd = VCWD_OPEN_MODE(buf, O_CREAT | O_RDWR | O_BINARY, data->filemode); + if (data->fd != -1) { +#ifndef PHP_WIN32 + /* check to make sure that the opened file is not a symlink, linking to data outside of allowable dirs */ + if (PG(safe_mode) || PG(open_basedir)) { + struct stat sbuf; + + if (fstat(data->fd, &sbuf)) { + close(data->fd); + return; + } + if ( + S_ISLNK(sbuf.st_mode) && + ( + php_check_open_basedir(buf TSRMLS_CC) || + (PG(safe_mode) && !php_checkuid(buf, NULL, CHECKUID_CHECK_FILE_AND_DIR)) + ) + ) { + + close(data->fd); + return; + } + } +#endif flock(data->fd, LOCK_EX); #ifdef F_SETFD -#ifndef FD_CLOEXEC -#define FD_CLOEXEC 1 -#endif +# ifndef FD_CLOEXEC +# define FD_CLOEXEC 1 +# endif if (fcntl(data->fd, F_SETFD, FD_CLOEXEC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "fcntl(%d, F_SETFD, FD_CLOEXEC) failed: %s (%d)", data->fd, strerror(errno), errno); } @@ -209,15 +234,16 @@ static int ps_files_cleanup_dir(const char *dirname, int maxlifetime TSRMLS_DC) while (php_readdir_r(dir, (struct dirent *) dentry, &entry) == 0 && entry) { /* does the file start with our prefix? */ if (!strncmp(entry->d_name, FILE_PREFIX, sizeof(FILE_PREFIX) - 1)) { - size_t entry_len; + size_t entry_len = strlen(entry->d_name); - entry_len = strlen(entry->d_name); /* does it fit into our buffer? */ if (entry_len + dirname_len + 2 < MAXPATHLEN) { /* create the full path.. */ memcpy(buf + dirname_len + 1, entry->d_name, entry_len); + /* NUL terminate it and */ buf[dirname_len + entry_len + 1] = '\0'; + /* check whether its last access was more than maxlifet ago */ if (VCWD_STAT(buf, &sbuf) == 0 && #ifdef NETWARE @@ -277,8 +303,7 @@ PS_OPEN_FUNC(files) errno = 0; dirdepth = (size_t) strtol(argv[0], NULL, 10); if (errno == ERANGE) { - php_error(E_WARNING, - "The first parameter in session.save_path is invalid"); + php_error(E_WARNING, "The first parameter in session.save_path is invalid"); return FAILURE; } } @@ -287,8 +312,7 @@ PS_OPEN_FUNC(files) errno = 0; filemode = strtol(argv[1], NULL, 8); if (errno == ERANGE || filemode < 0 || filemode > 07777) { - php_error(E_WARNING, - "The second parameter in session.save_path is invalid"); + php_error(E_WARNING, "The second parameter in session.save_path is invalid"); return FAILURE; } } @@ -314,8 +338,10 @@ PS_CLOSE_FUNC(files) ps_files_close(data); - if (data->lastkey) + if (data->lastkey) { efree(data->lastkey); + } + efree(data->basedir); efree(data); *mod_data = NULL; @@ -330,19 +356,21 @@ PS_READ_FUNC(files) PS_FILES_DATA; ps_files_open(data, key TSRMLS_CC); - if (data->fd < 0) + if (data->fd < 0) { return FAILURE; - - if (fstat(data->fd, &sbuf)) + } + + if (fstat(data->fd, &sbuf)) { return FAILURE; - + } + data->st_size = *vallen = sbuf.st_size; - + if (sbuf.st_size == 0) { *val = STR_EMPTY_ALLOC(); return SUCCESS; } - + *val = emalloc(sbuf.st_size); #if defined(HAVE_PREAD) @@ -353,10 +381,11 @@ PS_READ_FUNC(files) #endif if (n != sbuf.st_size) { - if (n == -1) + if (n == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "read failed: %s (%d)", strerror(errno), errno); - else + } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "read returned less bytes than requested"); + } efree(*val); return FAILURE; } @@ -370,16 +399,18 @@ PS_WRITE_FUNC(files) PS_FILES_DATA; ps_files_open(data, key TSRMLS_CC); - if (data->fd < 0) + if (data->fd < 0) { return FAILURE; + } /* * truncate file, if the amount of new data is smaller than * the existing data set. */ - if (vallen < (int)data->st_size) + if (vallen < (int)data->st_size) { ftruncate(data->fd, 0); + } #if defined(HAVE_PWRITE) n = pwrite(data->fd, val, vallen, 0); @@ -389,10 +420,11 @@ PS_WRITE_FUNC(files) #endif if (n != vallen) { - if (n == -1) + if (n == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "write failed: %s (%d)", strerror(errno), errno); - else + } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "write wrote less bytes than requested"); + } return FAILURE; } @@ -404,9 +436,10 @@ PS_DESTROY_FUNC(files) char buf[MAXPATHLEN]; PS_FILES_DATA; - if (!ps_files_path_create(buf, sizeof(buf), data, key)) + if (!ps_files_path_create(buf, sizeof(buf), data, key)) { return FAILURE; - + } + if (data->fd != -1) { ps_files_close(data); @@ -431,9 +464,10 @@ PS_GC_FUNC(files) we return SUCCESS, since all cleanup should be handled by an external entity (i.e. find -ctime x | xargs rm) */ - if (data->dirdepth == 0) + if (data->dirdepth == 0) { *nrdels = ps_files_cleanup_dir(data->basedir, maxlifetime TSRMLS_CC); - + } + return SUCCESS; } diff --git a/ext/session/session.c b/ext/session/session.c index b2a4ac7d5..9ec40f6e2 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: session.c,v 1.417.2.8.2.34 2007/05/16 01:18:14 stas Exp $ */ +/* $Id: session.c,v 1.417.2.8.2.40 2007/08/03 01:16:40 stas Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -46,6 +46,7 @@ #include "ext/standard/php_rand.h" /* for RAND_MAX */ #include "ext/standard/info.h" #include "ext/standard/php_smart_str.h" +#include "ext/standard/url.h" #include "mod_files.h" #include "mod_user.h" @@ -150,7 +151,7 @@ static PHP_INI_MH(OnUpdateSerializer) static PHP_INI_MH(OnUpdateSaveDir) { /* Only do the safemode/open_basedir check at runtime */ - if (stage == PHP_INI_STAGE_RUNTIME) { + if (stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) { char *p; if (memchr(new_value, '\0', new_value_length) != NULL) { @@ -167,7 +168,7 @@ static PHP_INI_MH(OnUpdateSaveDir) return FAILURE; } - if (php_check_open_basedir(p TSRMLS_CC)) { + if (PG(open_basedir) && php_check_open_basedir(p TSRMLS_CC)) { return FAILURE; } } @@ -946,10 +947,15 @@ static char *week_days[] = { static void strcpy_gmt(char *ubuf, time_t *when) { char buf[MAX_STR]; - struct tm tm; + struct tm tm, *res; int n; - php_gmtime_r(when, &tm); + res = php_gmtime_r(when, &tm); + + if (!res) { + buf[0] = '\0'; + return; + } n = slprintf(buf, sizeof(buf), "%s, %02d %s %d %02d:%02d:%02d GMT", /* SAFE */ week_days[tm.tm_wday], tm.tm_mday, @@ -1075,6 +1081,7 @@ static void php_session_send_cookie(TSRMLS_D) { smart_str ncookie = {0}; char *date_fmt = NULL; + char *e_session_name, *e_id; if (SG(headers_sent)) { char *output_start_filename = php_get_output_start_filename(TSRMLS_C); @@ -1088,11 +1095,18 @@ static void php_session_send_cookie(TSRMLS_D) } return; } + + /* URL encode session_name and id because they might be user supplied */ + e_session_name = php_url_encode(PS(session_name), strlen(PS(session_name)), NULL); + e_id = php_url_encode(PS(id), strlen(PS(id)), NULL); smart_str_appends(&ncookie, COOKIE_SET_COOKIE); - smart_str_appends(&ncookie, PS(session_name)); + smart_str_appends(&ncookie, e_session_name); smart_str_appendc(&ncookie, '='); - smart_str_appends(&ncookie, PS(id)); + smart_str_appends(&ncookie, e_id); + + efree(e_session_name); + efree(e_id); if (PS(cookie_lifetime) > 0) { struct timeval tv; @@ -1207,10 +1221,7 @@ PHPAPI void php_session_start(TSRMLS_D) PS(apply_trans_sid) = PS(use_trans_sid); - PS(define_sid) = 1; - PS(send_cookie) = 1; if (PS(session_status) != php_session_none) { - if (PS(session_status) == php_session_disabled) { char *value; @@ -1227,6 +1238,9 @@ PHPAPI void php_session_start(TSRMLS_D) php_error(E_NOTICE, "A session had already been started - ignoring session_start()"); return; + } else { + PS(define_sid) = 1; + PS(send_cookie) = 1; } lensess = strlen(PS(session_name)); diff --git a/ext/session/tests/004.phpt b/ext/session/tests/004.phpt index 2040476bc..b9013cac7 100644 --- a/ext/session/tests/004.phpt +++ b/ext/session/tests/004.phpt @@ -13,7 +13,7 @@ session.serialize_handler=php error_reporting(E_ALL); class handler { - public $data = 'baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}'; + public $data = 'baz|O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}arr|a:1:{i:3;O:3:"foo":2:{s:3:"bar";s:2:"ok";s:3:"yes";i:1;}}'; function open($save_path, $session_name) { print "OPEN: $session_name\n"; diff --git a/ext/session/tests/020.phpt b/ext/session/tests/020.phpt index 455c7f720..82997a8f0 100644 --- a/ext/session/tests/020.phpt +++ b/ext/session/tests/020.phpt @@ -6,7 +6,7 @@ rewriter uses arg_seperator.output for modifying URLs session.use_cookies=0 session.cache_limiter= session.use_trans_sid=1 -arg_separator.output=& +arg_separator.output="&" session.name=PHPSESSID session.serialize_handler=php session.save_handler=files diff --git a/ext/session/tests/bug41600.phpt b/ext/session/tests/bug41600.phpt new file mode 100644 index 000000000..ba04fd9d9 --- /dev/null +++ b/ext/session/tests/bug41600.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #41600 (url rewriter tags doesn't work with namespaced tags) +--SKIPIF-- +<?php include('skipif.inc'); ?> +--INI-- +session.use_cookies=0 +session.cache_limiter= +session.use_trans_sid=1 +arg_separator.output=& +session.name=PHPSESSID +session.serialize_handler=php +session.save_handler=files +--FILE-- +<?php + +error_reporting(E_ALL); + +session_id("abtest"); +session_start(); +?> +<a href="link.php?a=b"> +<?php +session_destroy(); +?> +--EXPECT-- +<a href="link.php?a=b&PHPSESSID=abtest"> |
