Package: elinks
Version: 0.13.1-1
Tags: patch

I found that elinks was not able to work with my installation of a
(not in Debian) web service, disorder [1].  This is because disorder
sends a path= attribute in its Set-Cookie header which is precisely
equal to the path in all of its URLs.

After some debugging, and some source diving, I discovered that the
cause was that elinks mishandles this case.  Patch attached.

Thanks for your attention.

If you have a good relationship with upstream I would appreciate it if
you'd pass it on.  If you would prefer me to do that I can look up how
to do it.

The patch applies cleanly as far back as buster, at least.

Regards,
Ian.

[1] https://www.greenend.org.uk/rjk/disorder/

>From a36579b07058b6bfcb5f7472e404c354bfa2813d Mon Sep 17 00:00:00 2001
From: Ian Jackson <[email protected]>
Date: Sat, 2 May 2020 19:40:06 +0100
Subject: [PATCH] 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
   http://site.example.com/some/thing

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

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 <[email protected]>
Signed-off-by: Ian Jackson <[email protected]>
---
 src/cookies/cookies.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/cookies/cookies.c b/src/cookies/cookies.c
index 993437d..ce30159 100644
--- a/src/cookies/cookies.c
+++ b/src/cookies/cookies.c
@@ -356,8 +356,7 @@ set_cookie(struct uri *uri, unsigned char *str)
                unsigned char *path_end;
 
        case HEADER_PARAM_FOUND:
-               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';
                break;
 
        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] == '/');
 }
 
 
-- 
2.11.0

-- 
Ian Jackson <[email protected]>   These opinions are my own.

If I emailed you from an address @fyvzl.net or @evade.org.uk, that is
a private address which bypasses my fierce spamfilter.

Reply via email to