Fork 0

cookies: Properly handle cookie path= equal to request path

The code in cookies.c would arrange that c->path would always contain
a string ending in "/".  This may have been an attempt to make it
easier to do a proper subpath check in is_path_prefix.

Howver, the overall result is wrong in the case
   Set-Cookie: ....;path=/some/thing
and then later

c->path gets set to "/some/thing/" which doesn't pass the test in

The precise required algorithm is described in RFC6265 5.1.4.  The
existing code fails to implement the first of the three bulleted
conditions at the end of 5.1.4.

The trailing "/" is actually not so helpful for this.  It is more
convenient to change is_path_prefix to do subpath matching directly:
we change it to insist that the supposed path prefix is a textual
prefix of the request path, *and* that this happens at a path segment
boundary: ie at '/' or end of string.[1]

Accordingly, we no longer add "/" to the cookie path.  When we strip
the final path element we strip the "/" too.  We still insert a "/" if
the path was empty.

[1] It is not 100% clear to me what "path" (URI_PATH) is but I think
it does not include any query parameters.  If I am wrong about that
then '?' should be tolerated too.

CC: Mark Wooding <mdw@distorted.org.uk>
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
This commit is contained in:
Ian Jackson 2020-05-02 19:40:06 +01:00 committed by أحمد المحمودي (Ahmed El-Mahmoudy)
parent eb46577ccb
commit 9bb3415811
1 changed files with 3 additions and 4 deletions

View File

@ -356,8 +356,7 @@ set_cookie(struct uri *uri, unsigned char *str)
unsigned char *path_end;
if (!path[0]
|| path[strlen(path) - 1] != '/')
if (!path[0])
add_to_strn(&path, "/");
if (path[0] != '/') {
@ -374,7 +373,7 @@ set_cookie(struct uri *uri, unsigned char *str)
path_end = strrchr((const char *)path, '/');
if (path_end)
path_end[1] = '\0';
path_end[0] = '\0';
default: /* error */
@ -615,7 +614,7 @@ is_path_prefix(unsigned char *d, unsigned char *s)
if (dl > strlen(s)) return 0;
return !memcmp(d, s, dl);
return !memcmp(d, s, dl) && (s[dl] == '\0' || s[dl] == '/');