mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Cleanup and clarify session.c (#19631)
This commit is contained in:
committed by
GitHub
parent
f4f6e89a1a
commit
8eac05f747
@@ -102,6 +102,7 @@ zend_class_entry *php_session_update_timestamp_iface_entry;
|
||||
|
||||
static zend_result php_session_send_cookie(void);
|
||||
static zend_result php_session_abort(void);
|
||||
static void proposed_session_id_to_session_id(zval *proposed_session_id);
|
||||
|
||||
/* Initialized in MINIT, readonly otherwise. */
|
||||
static int my_module_number = 0;
|
||||
@@ -369,7 +370,7 @@ PHPAPI zend_string *php_session_create_id(PS_CREATE_SID_ARGS)
|
||||
* ps_modules appropriately */
|
||||
PHPAPI zend_result php_session_valid_key(const char *key)
|
||||
{
|
||||
size_t len;
|
||||
size_t key_len;
|
||||
const char *p;
|
||||
char c;
|
||||
|
||||
@@ -384,11 +385,11 @@ PHPAPI zend_result php_session_valid_key(const char *key)
|
||||
}
|
||||
}
|
||||
|
||||
len = p - key;
|
||||
key_len = p - key;
|
||||
|
||||
/* Somewhat arbitrary length limit here, but should be way more than
|
||||
anyone needs and avoids file-level warnings later on if we exceed MAX_PATH */
|
||||
if (len == 0 || len > PS_MAX_SID_LENGTH) {
|
||||
if (key_len == 0 || key_len > PS_MAX_SID_LENGTH) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@@ -398,20 +399,21 @@ PHPAPI zend_result php_session_valid_key(const char *key)
|
||||
|
||||
static zend_long php_session_gc(bool immediate)
|
||||
{
|
||||
zend_long num = -1;
|
||||
zend_long sessions_deleted = -1;
|
||||
bool collect = immediate;
|
||||
|
||||
/* GC must be done before reading session data. */
|
||||
if ((PS(mod_data) || PS(mod_user_implemented))) {
|
||||
/* Use probability-based GC if not forced and probability is configured */
|
||||
if (!collect && PS(gc_probability) > 0) {
|
||||
collect = php_random_range(PS(random), 0, PS(gc_divisor) - 1) < PS(gc_probability);
|
||||
}
|
||||
|
||||
if (collect) {
|
||||
PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &num);
|
||||
PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &sessions_deleted);
|
||||
}
|
||||
}
|
||||
return num;
|
||||
return sessions_deleted;
|
||||
}
|
||||
|
||||
static zend_result php_session_initialize(void)
|
||||
@@ -1441,37 +1443,132 @@ static zend_result php_session_send_cookie(void)
|
||||
|
||||
PHPAPI const ps_module *_php_find_ps_module(const char *name)
|
||||
{
|
||||
const ps_module *ret = NULL;
|
||||
const ps_module **mod;
|
||||
int i;
|
||||
const ps_module *found_module = NULL;
|
||||
const ps_module **current_module;
|
||||
int module_index;
|
||||
|
||||
for (i = 0, mod = ps_modules; i < MAX_MODULES; i++, mod++) {
|
||||
if (*mod && !strcasecmp(name, (*mod)->s_name)) {
|
||||
ret = *mod;
|
||||
for (module_index = 0, current_module = ps_modules; module_index < MAX_MODULES; module_index++, current_module++) {
|
||||
if (*current_module && !strcasecmp(name, (*current_module)->s_name)) {
|
||||
found_module = *current_module;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return found_module;
|
||||
}
|
||||
|
||||
PHPAPI const ps_serializer *_php_find_ps_serializer(const char *name)
|
||||
{
|
||||
const ps_serializer *ret = NULL;
|
||||
const ps_serializer *mod;
|
||||
const ps_serializer *found_serializer = NULL;
|
||||
const ps_serializer *current_serializer;
|
||||
|
||||
for (mod = ps_serializers; mod->name; mod++) {
|
||||
if (!strcasecmp(name, mod->name)) {
|
||||
ret = mod;
|
||||
for (current_serializer = ps_serializers; current_serializer->name; current_serializer++) {
|
||||
if (!strcasecmp(name, current_serializer->name)) {
|
||||
found_serializer = current_serializer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return found_serializer;
|
||||
}
|
||||
|
||||
static void ppid2sid(zval *ppid) {
|
||||
ZVAL_DEREF(ppid);
|
||||
if (Z_TYPE_P(ppid) == IS_STRING) {
|
||||
PS(id) = zend_string_copy(Z_STR_P(ppid));
|
||||
static bool should_invalidate_session_for_external_referer(void)
|
||||
{
|
||||
zval *referer_data;
|
||||
|
||||
/* No external referer check configured */
|
||||
if (!PS(id) || PS(extern_referer_chk)[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* No SERVER globals available */
|
||||
if (Z_ISUNDEF(PG(http_globals)[TRACK_VARS_SERVER])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get HTTP_REFERER header */
|
||||
referer_data = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZEND_STRL("HTTP_REFERER"));
|
||||
if (!referer_data || Z_TYPE_P(referer_data) != IS_STRING || Z_STRLEN_P(referer_data) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check if referer contains expected string */
|
||||
return strstr(Z_STRVAL_P(referer_data), PS(extern_referer_chk)) == NULL;
|
||||
}
|
||||
|
||||
static void try_find_session_id_in_global(const char *global_name, size_t global_name_len)
|
||||
{
|
||||
zval *global_data, *potential_session_id;
|
||||
|
||||
if (PS(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
global_data = zend_hash_str_find(&EG(symbol_table), global_name, global_name_len);
|
||||
if (!global_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZVAL_DEREF(global_data);
|
||||
if (Z_TYPE_P(global_data) != IS_ARRAY) {
|
||||
return;
|
||||
}
|
||||
|
||||
potential_session_id = zend_hash_find(Z_ARRVAL_P(global_data), PS(session_name));
|
||||
if (potential_session_id) {
|
||||
proposed_session_id_to_session_id(potential_session_id);
|
||||
}
|
||||
}
|
||||
|
||||
static bool php_can_change_session_setting(const char *setting_name, bool check_cookies)
|
||||
{
|
||||
if (PS(session_status) == php_session_active) {
|
||||
char error_msg[256];
|
||||
snprintf(error_msg, sizeof(error_msg), "Session %s cannot be changed when a session is active", setting_name);
|
||||
php_session_session_already_started_error(E_WARNING, error_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SG(headers_sent) && (!check_cookies || PS(use_cookies))) {
|
||||
char error_msg[256];
|
||||
snprintf(error_msg, sizeof(error_msg), "Session %s cannot be changed after headers have already been sent", setting_name);
|
||||
php_session_headers_already_sent_error(E_WARNING, error_msg);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void try_find_session_id_in_cookies(void)
|
||||
{
|
||||
zval *cookie_data, *potential_session_id;
|
||||
|
||||
if (!PS(use_cookies) || PS(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cookie_data = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_COOKIE"));
|
||||
if (!cookie_data) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZVAL_DEREF(cookie_data);
|
||||
if (Z_TYPE_P(cookie_data) != IS_ARRAY) {
|
||||
return;
|
||||
}
|
||||
|
||||
potential_session_id = zend_hash_find(Z_ARRVAL_P(cookie_data), PS(session_name));
|
||||
if (potential_session_id) {
|
||||
proposed_session_id_to_session_id(potential_session_id);
|
||||
PS(send_cookie) = 0;
|
||||
PS(define_sid) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void proposed_session_id_to_session_id(zval *proposed_session_id) {
|
||||
ZVAL_DEREF(proposed_session_id);
|
||||
if (Z_TYPE_P(proposed_session_id) == IS_STRING) {
|
||||
PS(id) = zend_string_copy(Z_STR_P(proposed_session_id));
|
||||
PS(send_cookie) = 0;
|
||||
} else {
|
||||
PS(id) = NULL;
|
||||
@@ -1483,7 +1580,7 @@ static void ppid2sid(zval *ppid) {
|
||||
PHPAPI zend_result php_session_reset_id(void)
|
||||
{
|
||||
int module_number = PS(module_number);
|
||||
zval *sid, *data, *ppid;
|
||||
zval *sid, *data, *potential_session_id;
|
||||
bool apply_trans_sid;
|
||||
|
||||
if (!PS(id)) {
|
||||
@@ -1545,8 +1642,8 @@ PHPAPI zend_result php_session_reset_id(void)
|
||||
(data = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_COOKIE")))) {
|
||||
ZVAL_DEREF(data);
|
||||
if (Z_TYPE_P(data) == IS_ARRAY &&
|
||||
(ppid = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) {
|
||||
ZVAL_DEREF(ppid);
|
||||
(potential_session_id = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) {
|
||||
ZVAL_DEREF(potential_session_id);
|
||||
apply_trans_sid = 0;
|
||||
}
|
||||
}
|
||||
@@ -1561,8 +1658,6 @@ PHPAPI zend_result php_session_reset_id(void)
|
||||
|
||||
PHPAPI zend_result php_session_start(void)
|
||||
{
|
||||
zval *ppid;
|
||||
zval *data;
|
||||
char *value;
|
||||
|
||||
switch (PS(session_status)) {
|
||||
@@ -1607,37 +1702,13 @@ PHPAPI zend_result php_session_start(void)
|
||||
*/
|
||||
|
||||
if (!PS(id)) {
|
||||
if (PS(use_cookies) && (data = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_COOKIE")))) {
|
||||
ZVAL_DEREF(data);
|
||||
if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) {
|
||||
ppid2sid(ppid);
|
||||
PS(send_cookie) = 0;
|
||||
PS(define_sid) = 0;
|
||||
}
|
||||
}
|
||||
/* Initialize session ID from non cookie values */
|
||||
try_find_session_id_in_cookies();
|
||||
|
||||
if (!PS(use_only_cookies)) {
|
||||
if (!PS(id) && (data = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_GET")))) {
|
||||
ZVAL_DEREF(data);
|
||||
if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) {
|
||||
ppid2sid(ppid);
|
||||
}
|
||||
}
|
||||
if (!PS(id) && (data = zend_hash_str_find(&EG(symbol_table), ZEND_STRL("_POST")))) {
|
||||
ZVAL_DEREF(data);
|
||||
if (Z_TYPE_P(data) == IS_ARRAY && (ppid = zend_hash_find(Z_ARRVAL_P(data), PS(session_name)))) {
|
||||
ppid2sid(ppid);
|
||||
}
|
||||
}
|
||||
/* Check whether the current request was referred to by
|
||||
* an external site which invalidates the previously found id. */
|
||||
if (PS(id) && PS(extern_referer_chk)[0] != '\0' &&
|
||||
!Z_ISUNDEF(PG(http_globals)[TRACK_VARS_SERVER]) &&
|
||||
(data = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZEND_STRL("HTTP_REFERER"))) &&
|
||||
Z_TYPE_P(data) == IS_STRING &&
|
||||
Z_STRLEN_P(data) != 0 &&
|
||||
strstr(Z_STRVAL_P(data), PS(extern_referer_chk)) == NULL
|
||||
) {
|
||||
try_find_session_id_in_global(ZEND_STRL("_GET"));
|
||||
try_find_session_id_in_global(ZEND_STRL("_POST"));
|
||||
|
||||
if (should_invalidate_session_for_external_referer()) {
|
||||
zend_string_release_ex(PS(id), 0);
|
||||
PS(id) = NULL;
|
||||
}
|
||||
@@ -1923,13 +1994,7 @@ PHP_FUNCTION(session_name)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (name && PS(session_status) == php_session_active) {
|
||||
php_session_session_already_started_error(E_WARNING, "Session name cannot be changed when a session is active");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (name && SG(headers_sent)) {
|
||||
php_session_headers_already_sent_error(E_WARNING, "Session name cannot be changed after headers have already been sent");
|
||||
if (name && !php_can_change_session_setting("name", false)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -1952,13 +2017,7 @@ PHP_FUNCTION(session_module_name)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (name && PS(session_status) == php_session_active) {
|
||||
php_session_session_already_started_error(E_WARNING, "Session save handler module cannot be changed when a session is active");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (name && SG(headers_sent)) {
|
||||
php_session_headers_already_sent_error(E_WARNING, "Session save handler module cannot be changed after headers have already been sent");
|
||||
if (name && !php_can_change_session_setting("save handler module", false)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -2227,13 +2286,7 @@ PHP_FUNCTION(session_save_path)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (name && PS(session_status) == php_session_active) {
|
||||
php_session_session_already_started_error(E_WARNING, "Session save path cannot be changed when a session is active");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (name && SG(headers_sent)) {
|
||||
php_session_headers_already_sent_error(E_WARNING, "Session save path cannot be changed after headers have already been sent");
|
||||
if (name && !php_can_change_session_setting("save path", false)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -2255,13 +2308,7 @@ PHP_FUNCTION(session_id)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (name && PS(session_status) == php_session_active) {
|
||||
php_session_session_already_started_error(E_WARNING, "Session ID cannot be changed when a session is active");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (name && PS(use_cookies) && SG(headers_sent)) {
|
||||
php_session_headers_already_sent_error(E_WARNING, "Session ID cannot be changed after headers have already been sent");
|
||||
if (name && !php_can_change_session_setting("ID", true)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -2962,24 +3009,24 @@ static PHP_MSHUTDOWN_FUNCTION(session)
|
||||
|
||||
static PHP_MINFO_FUNCTION(session)
|
||||
{
|
||||
const ps_module **mod;
|
||||
ps_serializer *ser;
|
||||
const ps_module **current_save_handler;
|
||||
ps_serializer *current_serializer;
|
||||
smart_str save_handlers = {0};
|
||||
smart_str ser_handlers = {0};
|
||||
int i;
|
||||
int handler_index;
|
||||
|
||||
/* Get save handlers */
|
||||
for (i = 0, mod = ps_modules; i < MAX_MODULES; i++, mod++) {
|
||||
if (*mod && (*mod)->s_name) {
|
||||
smart_str_appends(&save_handlers, (*mod)->s_name);
|
||||
/* Collect names of all available save handlers */
|
||||
for (handler_index = 0, current_save_handler = ps_modules; handler_index < MAX_MODULES; handler_index++, current_save_handler++) {
|
||||
if (*current_save_handler && (*current_save_handler)->s_name) {
|
||||
smart_str_appends(&save_handlers, (*current_save_handler)->s_name);
|
||||
smart_str_appendc(&save_handlers, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
/* Get serializer handlers */
|
||||
for (i = 0, ser = ps_serializers; i < MAX_SERIALIZERS; i++, ser++) {
|
||||
if (ser->name) {
|
||||
smart_str_appends(&ser_handlers, ser->name);
|
||||
/* Collect names of all available serializers */
|
||||
for (handler_index = 0, current_serializer = ps_serializers; handler_index < MAX_SERIALIZERS; handler_index++, current_serializer++) {
|
||||
if (current_serializer->name) {
|
||||
smart_str_appends(&ser_handlers, current_serializer->name);
|
||||
smart_str_appendc(&ser_handlers, ' ');
|
||||
}
|
||||
}
|
||||
@@ -3019,16 +3066,16 @@ static const zend_module_dep session_deps[] = {
|
||||
|
||||
static bool early_find_sid_in(zval *dest, int where, php_session_rfc1867_progress *progress)
|
||||
{
|
||||
zval *ppid;
|
||||
zval *potential_session_id;
|
||||
|
||||
if (Z_ISUNDEF(PG(http_globals)[where])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ppid = zend_hash_find(Z_ARRVAL(PG(http_globals)[where]), PS(session_name)))
|
||||
&& Z_TYPE_P(ppid) == IS_STRING) {
|
||||
if ((potential_session_id = zend_hash_find(Z_ARRVAL(PG(http_globals)[where]), PS(session_name)))
|
||||
&& Z_TYPE_P(potential_session_id) == IS_STRING) {
|
||||
zval_ptr_dtor(dest);
|
||||
ZVAL_COPY_DEREF(dest, ppid);
|
||||
ZVAL_COPY_DEREF(dest, potential_session_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user