-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[RFC] SameSite cookie option #3398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ext/session/session.c
Outdated
samesite = Z_STR_P(value); | ||
found++; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should maybe error if key not string?
ext/session/session.c
Outdated
convert_to_string_ex(lifetime); | ||
found++; | ||
} else if(!strcasecmp("path", ZSTR_VAL(key))) { | ||
path = Z_STR_P(value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're assuming here that the path
is a string. Either you need to explicitly check this, or use something like zval_get_string
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried to use zval_get_string
for all of these, however, I'm missing something as it is currently leaking on ext/session/tests/session_set_cookie_params_error.phpt
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, you have to zend_string_release
all strings obtained by using zval_get_string
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that they are all covered at the moment. The test uses the same variable for all the parameters in sequence. And I think that that's the cause of the leak (as it doesn't leak on any other test where the parameters are constants).
ext/session/session.c
Outdated
} else if(!strcasecmp("samesite", ZSTR_VAL(key))) { | ||
samesite = Z_STR_P(value); | ||
found++; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should an unknown option generate a warning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added the warning and the error. Thanks
ext/standard/head.c
Outdated
} ZEND_HASH_FOREACH_END(); | ||
|
||
/* Array is not empty but no valid keys were found */ | ||
if (found == 0 && Z_ARRVAL_P(options)->nNumUsed > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use zend_hash_num_elements()
instead of nNumUsed
.
ext/session/session.c
Outdated
ZVAL_DEREF(value); | ||
if(!strcasecmp("lifetime", ZSTR_VAL(key))) { | ||
lifetime = value; | ||
convert_to_string_ex(lifetime); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to modify the array in-place. Either this should have a strict type check, or use zval_get_string
(with appropriate refcount management for the other case).
I've fixed the pending issues and implemented the suggestions. Thanks for the feedback |
ext/session/session.c
Outdated
php_error_docref(NULL, E_WARNING, "Unrecognized key '%s' found in the options array", ZSTR_VAL(key)); | ||
} | ||
} else { | ||
php_error_docref(NULL, E_ERROR, "The options array must only use string keys"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also be just E_WARNING. E_ERROR is a fatal error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, downgraded to warning.
ext/session/session.c
Outdated
RETURN_FALSE; | ||
} | ||
} else { | ||
convert_to_string_ex(lifetime_or_options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The convert_to_string_ex call can be dropped if this uses zval_get_string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although unnecessary, I left it behind as the old code was modifying the variable in place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The in-place modification is not externally visible though, so it's safe to drop it.
ext/session/session.c
Outdated
} | ||
if (samesite) { | ||
ini_name = zend_string_init("session.cookie_samesite", sizeof("session.cookie_samesite") - 1, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Indentation
ext/standard/head.c
Outdated
RETVAL_TRUE; | ||
} else { | ||
RETVAL_FALSE; | ||
} | ||
|
||
cleanup: | ||
if (path) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this cause double releases for the non-array codepath?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would indeed, thanks
Z_PARAM_STR(path) | ||
Z_PARAM_STR(domain) | ||
Z_PARAM_BOOL_EX(secure, secure_null, 1, 0) | ||
Z_PARAM_BOOL_EX(httponly, httponly_null, 1, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we want to add SameSite
here too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, samesite will only be supported in the new array forms of these functions, not the (now legacy) multi-argument variant.
httponly_null = 0; | ||
found++; | ||
} else if(!strcasecmp("samesite", ZSTR_VAL(key))) { | ||
samesite = zval_get_string(value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we want to check that value
is either Strict
or Lax
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, but that falls a bit out of the scope here. No other values are sanitized at this moment. It would probably be a good proposal to validate all values (ie. check if the domain is actually a domain) but I'd keep that a separate discussion.
if (found == 0 && zend_hash_num_elements(Z_ARRVAL_P(options)) > 0) { | ||
php_error_docref(NULL, E_WARNING, "No valid options were found in the given array"); | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This warning seems a bit redundant. Isn't it only thrown if one of the above warnings already triggered?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it's true that it will only trigger when one of the others also triggered, I think it has some usefulness to distinguish between some keys being invalid and all keys being invalid. OTOH, it does feel a bit redundant given that it will only show paired with one of the above. If we remove the warning, should we also remove the return 0;
? As it stands, the cookie won't be set when this warning is shown.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the internals discussion, I believe we have enough consensus to land this with the implementation proposed here.
Allows using an alternative array argument with support for the samesite option on the following functions: setcookie setrawcookie session_set_cookie_params
Okay, I'm going to merge this PR. However, we'll likely have to work on this as soon as possible, since currently it seems to be possible to pass additional parameters after the options array, e.g.: <?php
session_set_cookie_params(array('path'=>'/foo/'), 'bar', 'www.example.com');
var_dump(session_get_cookie_params()); outputs:
|
For the record, the Snuffleupagus module provides support for the Thank you for pushing this feature upstream ♥ |
This PR is an implementation of the winning vote in the samesite cookie RFC: https://wiki.php.net/rfc/same-site-cookie
This PR supersedes #2613.
Any feedback on the implementation is welcome.