diff options
author | corvid <corvid@lavabit.com> | 2009-12-31 05:56:39 +0000 |
---|---|---|
committer | corvid <corvid@lavabit.com> | 2009-12-31 05:56:39 +0000 |
commit | 023dbdb29d2976f731fd73225d5e28478f5c34ce (patch) | |
tree | 24a8952e1a48db38733d59d0420f19d8a70cadeb /dpi | |
parent | 8e9f32b0e94670410c2b390f7ba9e06ca0a78a76 (diff) |
cookie paths
Diffstat (limited to 'dpi')
-rw-r--r-- | dpi/cookies.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/dpi/cookies.c b/dpi/cookies.c index 785e4282..b1685b47 100644 --- a/dpi/cookies.c +++ b/dpi/cookies.c @@ -1016,20 +1016,60 @@ static int Cookies_cmp(const void *a, const void *b) } /* + * Check whether 'prefix' is a prefix of 'path'. + */ +static bool_t Cookies_path_is_prefix(const char *prefix, const char *path) +{ + bool_t ret = TRUE; + + if (!prefix || !path) + return FALSE; + + /* + * The original Netscape cookie spec states 'The path "/foo" would match + * "/foobar" and "/foo/bar.html"', so when the RFCs say "prefix", they + * apparently really do mean prefix, however utterly bizarre that might be. + * + * (On the other hand, http://testsuites.opera.com/cookies/302/302.php + * takes quite some interest in the prefix as a genuine path.) + */ + if (strncmp(prefix, path, strlen(prefix))) + ret = FALSE; + + return ret; +} + +/* * Validate cookies domain against some security checks. */ static bool_t Cookies_validate_domain(CookieData_t *cookie, char *host, char *url_path) { int dots, diff, i; - bool_t is_ip; + bool_t ret, is_ip; + char *path = Cookies_strip_path(url_path); /* Make sure that the path is set to something */ if (!cookie->path || cookie->path[0] != '/') { + uint_t pathlen; + dFree(cookie->path); - cookie->path = Cookies_strip_path(url_path); + cookie->path = dStrdup(path); + + /* RFC 2109 does not want a trailing '/', but RFC 2965 does. Since the + * world has taken little notice of 2965 and cookie paths consistently + * lack a trailing '/', let's remove it. + */ + pathlen = strlen(cookie->path); + if (pathlen > 1 && cookie->path[pathlen - 1] == '/') + cookie->path[pathlen - 1] = '\0'; } + ret = Cookies_path_is_prefix(cookie->path, path); + dFree(path); + if (!ret) + return FALSE; + /* If the server never set a domain, or set one without a leading * dot (which isn't allowed), we use the calling URL's hostname. */ if (cookie->domain == NULL || cookie->domain[0] != '.') { @@ -1072,7 +1112,7 @@ static bool_t Cookies_validate_domain(CookieData_t *cookie, char *host, } /* - * Strip of the filename from a full path + * Strip the filename from a full path. */ static char *Cookies_strip_path(const char *path) { @@ -1144,8 +1184,8 @@ static bool_t Cookies_match(CookieData_t *cookie, int port, if (cookie->secure && !is_ssl) return FALSE; - /* Check that the cookie path is a subpath of the current path */ - if (strncmp(cookie->path, path, strlen(cookie->path)) != 0) + /* Check that the cookie path is a prefix of the current path */ + if (!Cookies_path_is_prefix(cookie->path, path)) return FALSE; /* Check if the port of the request URL matches any |