Skip to content

Commit 832ea24

Browse files
committed
Add support for ext/session
1 parent 744fd4c commit 832ea24

8 files changed

+151
-11
lines changed

ext/session/php_session.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ typedef struct _php_ps_globals {
149149
zend_string *cookie_samesite;
150150
bool cookie_secure;
151151
bool cookie_httponly;
152+
bool cookie_partitioned;
152153
const ps_module *mod;
153154
const ps_module *default_mod;
154155
void *mod_data;

ext/session/session.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ PHP_INI_BEGIN()
898898
STD_PHP_INI_ENTRY("session.cookie_path", "/", PHP_INI_ALL, OnUpdateSessionStr, cookie_path, php_ps_globals, ps_globals)
899899
STD_PHP_INI_ENTRY("session.cookie_domain", "", PHP_INI_ALL, OnUpdateSessionStr, cookie_domain, php_ps_globals, ps_globals)
900900
STD_PHP_INI_BOOLEAN("session.cookie_secure", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_secure, php_ps_globals, ps_globals)
901+
STD_PHP_INI_BOOLEAN("session.cookie_partitioned","0", PHP_INI_ALL, OnUpdateSessionBool, cookie_partitioned, php_ps_globals, ps_globals)
901902
STD_PHP_INI_BOOLEAN("session.cookie_httponly", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals)
902903
STD_PHP_INI_ENTRY("session.cookie_samesite", "", PHP_INI_ALL, OnUpdateSessionStr, cookie_samesite, php_ps_globals, ps_globals)
903904
STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateSessionBool, use_cookies, php_ps_globals, ps_globals)
@@ -1388,6 +1389,12 @@ static zend_result php_session_send_cookie(void)
13881389
return FAILURE;
13891390
}
13901391

1392+
/* Check for invalid settings combinations */
1393+
if (UNEXPECTED(PS(cookie_partitioned) && !PS(cookie_secure))) {
1394+
php_error_docref(NULL, E_WARNING, "Partitioned session cookie cannot be used without also configuring it as secure");
1395+
return FAILURE;
1396+
}
1397+
13911398
ZEND_ASSERT(strpbrk(ZSTR_VAL(PS(session_name)), SESSION_FORBIDDEN_CHARS) == NULL);
13921399

13931400
/* URL encode id because it might be user supplied */
@@ -1432,6 +1439,10 @@ static zend_result php_session_send_cookie(void)
14321439
smart_str_appends(&ncookie, COOKIE_SECURE);
14331440
}
14341441

1442+
if (PS(cookie_partitioned)) {
1443+
smart_str_appends(&ncookie, COOKIE_PARTITIONED);
1444+
}
1445+
14351446
if (PS(cookie_httponly)) {
14361447
smart_str_appends(&ncookie, COOKIE_HTTPONLY);
14371448
}
@@ -1725,6 +1736,7 @@ PHP_FUNCTION(session_set_cookie_params)
17251736
zend_string *lifetime = NULL, *path = NULL, *domain = NULL, *samesite = NULL;
17261737
bool secure = 0, secure_null = 1;
17271738
bool httponly = 0, httponly_null = 1;
1739+
bool partitioned = false, partitioned_null = true;
17281740
zend_string *ini_name;
17291741
zend_result result;
17301742
int found = 0;
@@ -1792,6 +1804,10 @@ PHP_FUNCTION(session_set_cookie_params)
17921804
secure = zval_is_true(value);
17931805
secure_null = 0;
17941806
found++;
1807+
} else if (zend_string_equals_literal_ci(key, "partitioned")) {
1808+
partitioned = zval_is_true(value);
1809+
partitioned_null = 0;
1810+
found++;
17951811
} else if (zend_string_equals_literal_ci(key, "httponly")) {
17961812
httponly = zval_is_true(value);
17971813
httponly_null = 0;
@@ -1856,6 +1872,15 @@ PHP_FUNCTION(session_set_cookie_params)
18561872
goto cleanup;
18571873
}
18581874
}
1875+
if (!partitioned_null) {
1876+
ini_name = ZSTR_INIT_LITERAL("session.cookie_partitioned", 0);
1877+
result = zend_alter_ini_entry_chars(ini_name, partitioned ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
1878+
zend_string_release_ex(ini_name, 0);
1879+
if (result == FAILURE) {
1880+
RETVAL_FALSE;
1881+
goto cleanup;
1882+
}
1883+
}
18591884
if (!httponly_null) {
18601885
ini_name = ZSTR_INIT_LITERAL("session.cookie_httponly", 0);
18611886
result = zend_alter_ini_entry_chars(ini_name, httponly ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
@@ -1898,6 +1923,7 @@ PHP_FUNCTION(session_get_cookie_params)
18981923
add_assoc_str(return_value, "path", zend_string_dup(PS(cookie_path), false));
18991924
add_assoc_str(return_value, "domain", zend_string_dup(PS(cookie_domain), false));
19001925
add_assoc_bool(return_value, "secure", PS(cookie_secure));
1926+
add_assoc_bool(return_value, "partitioned", PS(cookie_partitioned));
19011927
add_assoc_bool(return_value, "httponly", PS(cookie_httponly));
19021928
add_assoc_str(return_value, "samesite", zend_string_dup(PS(cookie_samesite), false));
19031929
}

ext/session/tests/session_get_cookie_params_basic.phpt

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ session.cookie_lifetime=0
99
session.cookie_path="/"
1010
session.cookie_domain=""
1111
session.cookie_secure=0
12+
session.cookie_partitioned=0
1213
session.cookie_httponly=0
1314
session.cookie_samesite=""
1415
--FILE--
@@ -31,13 +32,17 @@ var_dump(session_set_cookie_params([
3132
"httponly" => FALSE,
3233
"samesite" => "please"]));
3334
var_dump(session_get_cookie_params());
35+
var_dump(session_set_cookie_params([
36+
"secure" => TRUE,
37+
"partitioned" => TRUE]));
38+
var_dump(session_get_cookie_params());
3439

3540
echo "Done";
3641
ob_end_flush();
3742
?>
3843
--EXPECTF--
3944
*** Testing session_get_cookie_params() : basic functionality ***
40-
array(6) {
45+
array(7) {
4146
["lifetime"]=>
4247
int(0)
4348
["path"]=>
@@ -46,13 +51,15 @@ array(6) {
4651
string(0) ""
4752
["secure"]=>
4853
bool(false)
54+
["partitioned"]=>
55+
bool(false)
4956
["httponly"]=>
5057
bool(false)
5158
["samesite"]=>
5259
string(0) ""
5360
}
5461
bool(true)
55-
array(6) {
62+
array(7) {
5663
["lifetime"]=>
5764
int(3600)
5865
["path"]=>
@@ -61,13 +68,15 @@ array(6) {
6168
string(4) "blah"
6269
["secure"]=>
6370
bool(false)
71+
["partitioned"]=>
72+
bool(false)
6473
["httponly"]=>
6574
bool(false)
6675
["samesite"]=>
6776
string(0) ""
6877
}
6978
bool(true)
70-
array(6) {
79+
array(7) {
7180
["lifetime"]=>
7281
int(%d)
7382
["path"]=>
@@ -76,13 +85,15 @@ array(6) {
7685
string(3) "foo"
7786
["secure"]=>
7887
bool(true)
88+
["partitioned"]=>
89+
bool(false)
7990
["httponly"]=>
8091
bool(true)
8192
["samesite"]=>
8293
string(0) ""
8394
}
8495
bool(true)
85-
array(6) {
96+
array(7) {
8697
["lifetime"]=>
8798
int(123)
8899
["path"]=>
@@ -91,6 +102,25 @@ array(6) {
91102
string(3) "baz"
92103
["secure"]=>
93104
bool(false)
105+
["partitioned"]=>
106+
bool(false)
107+
["httponly"]=>
108+
bool(false)
109+
["samesite"]=>
110+
string(6) "please"
111+
}
112+
bool(true)
113+
array(7) {
114+
["lifetime"]=>
115+
int(123)
116+
["path"]=>
117+
string(4) "/bar"
118+
["domain"]=>
119+
string(3) "baz"
120+
["secure"]=>
121+
bool(true)
122+
["partitioned"]=>
123+
bool(true)
94124
["httponly"]=>
95125
bool(false)
96126
["samesite"]=>

ext/session/tests/session_get_cookie_params_variation1.phpt

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ session.cookie_lifetime=0
99
session.cookie_path="/"
1010
session.cookie_domain=""
1111
session.cookie_secure=0
12+
session.cookie_partitioned=0
1213
session.cookie_httponly=0
1314
session.cookie_samesite=""
1415
--FILE--
@@ -31,13 +32,15 @@ ini_set("session.cookie_httponly", TRUE);
3132
var_dump(session_get_cookie_params());
3233
ini_set("session.cookie_samesite", "foo");
3334
var_dump(session_get_cookie_params());
35+
ini_set("session.cookie_partitioned", TRUE);
36+
var_dump(session_get_cookie_params());
3437

3538
echo "Done";
3639
ob_end_flush();
3740
?>
3841
--EXPECT--
3942
*** Testing session_get_cookie_params() : variation ***
40-
array(6) {
43+
array(7) {
4144
["lifetime"]=>
4245
int(0)
4346
["path"]=>
@@ -46,12 +49,14 @@ array(6) {
4649
string(0) ""
4750
["secure"]=>
4851
bool(false)
52+
["partitioned"]=>
53+
bool(false)
4954
["httponly"]=>
5055
bool(false)
5156
["samesite"]=>
5257
string(0) ""
5358
}
54-
array(6) {
59+
array(7) {
5560
["lifetime"]=>
5661
int(3600)
5762
["path"]=>
@@ -60,12 +65,14 @@ array(6) {
6065
string(0) ""
6166
["secure"]=>
6267
bool(false)
68+
["partitioned"]=>
69+
bool(false)
6370
["httponly"]=>
6471
bool(false)
6572
["samesite"]=>
6673
string(0) ""
6774
}
68-
array(6) {
75+
array(7) {
6976
["lifetime"]=>
7077
int(3600)
7178
["path"]=>
@@ -74,12 +81,14 @@ array(6) {
7481
string(0) ""
7582
["secure"]=>
7683
bool(false)
84+
["partitioned"]=>
85+
bool(false)
7786
["httponly"]=>
7887
bool(false)
7988
["samesite"]=>
8089
string(0) ""
8190
}
82-
array(6) {
91+
array(7) {
8392
["lifetime"]=>
8493
int(3600)
8594
["path"]=>
@@ -88,12 +97,14 @@ array(6) {
8897
string(3) "foo"
8998
["secure"]=>
9099
bool(false)
100+
["partitioned"]=>
101+
bool(false)
91102
["httponly"]=>
92103
bool(false)
93104
["samesite"]=>
94105
string(0) ""
95106
}
96-
array(6) {
107+
array(7) {
97108
["lifetime"]=>
98109
int(3600)
99110
["path"]=>
@@ -102,12 +113,14 @@ array(6) {
102113
string(3) "foo"
103114
["secure"]=>
104115
bool(true)
116+
["partitioned"]=>
117+
bool(false)
105118
["httponly"]=>
106119
bool(false)
107120
["samesite"]=>
108121
string(0) ""
109122
}
110-
array(6) {
123+
array(7) {
111124
["lifetime"]=>
112125
int(3600)
113126
["path"]=>
@@ -116,12 +129,30 @@ array(6) {
116129
string(3) "foo"
117130
["secure"]=>
118131
bool(true)
132+
["partitioned"]=>
133+
bool(false)
119134
["httponly"]=>
120135
bool(true)
121136
["samesite"]=>
122137
string(0) ""
123138
}
124-
array(6) {
139+
array(7) {
140+
["lifetime"]=>
141+
int(3600)
142+
["path"]=>
143+
string(5) "/path"
144+
["domain"]=>
145+
string(3) "foo"
146+
["secure"]=>
147+
bool(true)
148+
["partitioned"]=>
149+
bool(false)
150+
["httponly"]=>
151+
bool(true)
152+
["samesite"]=>
153+
string(3) "foo"
154+
}
155+
array(7) {
125156
["lifetime"]=>
126157
int(3600)
127158
["path"]=>
@@ -130,6 +161,8 @@ array(6) {
130161
string(3) "foo"
131162
["secure"]=>
132163
bool(true)
164+
["partitioned"]=>
165+
bool(true)
133166
["httponly"]=>
134167
bool(true)
135168
["samesite"]=>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
session_start() with partitioned cookies
3+
--INI--
4+
session.use_strict_mode=0
5+
session.save_handler=files
6+
session.save_path=
7+
session.cookie_secure=0
8+
session.cookie_partitioned=0
9+
--EXTENSIONS--
10+
session
11+
--SKIPIF--
12+
<?php include('skipif.inc'); ?>
13+
--FILE--
14+
<?php
15+
16+
ob_start();
17+
18+
var_dump(session_start(['cookie_partitioned' => true]));
19+
var_dump(session_start(['cookie_partitioned' => true, 'cookie_secure' => false]));
20+
var_dump(session_start(['cookie_partitioned' => true, 'cookie_secure' => true]));
21+
22+
ob_end_flush();
23+
24+
?>
25+
--EXPECTF--
26+
Warning: session_start(): Partitioned session cookie cannot be used without also configuring it as secure in %s on line %d
27+
bool(false)
28+
29+
Warning: session_start(): Partitioned session cookie cannot be used without also configuring it as secure in %s on line %d
30+
bool(false)
31+
bool(true)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
session_start() with partitioned cookies - header test
3+
--EXTENSIONS--
4+
session
5+
--FILE--
6+
<?php
7+
session_id('12345');
8+
session_set_cookie_params(["secure" => true, "partitioned" => true]);
9+
session_start();
10+
?>
11+
--EXPECTHEADERS--
12+
Set-Cookie: PHPSESSID=12345; path=/; secure; Partitioned
13+
--EXPECT--

php.ini-development

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,9 @@ session.use_cookies = 1
13241324
; https://php.net/session.cookie-secure
13251325
;session.cookie_secure =
13261326

1327+
; https://php.net/session.cookie-partitioned
1328+
;session.cookie_partitioned = 0
1329+
13271330
; This option forces PHP to fetch and use a cookie for storing and maintaining
13281331
; the session id. We encourage this operation as it's very helpful in combating
13291332
; session hijacking when not specifying and managing your own session id. It is

php.ini-production

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,9 @@ session.use_cookies = 1
13261326
; https://php.net/session.cookie-secure
13271327
;session.cookie_secure =
13281328

1329+
; https://php.net/session.cookie-partitioned
1330+
;session.cookie_partitioned = 0
1331+
13291332
; This option forces PHP to fetch and use a cookie for storing and maintaining
13301333
; the session id. We encourage this operation as it's very helpful in combating
13311334
; session hijacking when not specifying and managing your own session id. It is

0 commit comments

Comments
 (0)