diff options
author | Siwei Li <siwei.li@live.com> | 2023-01-16 12:31:10 -0800 |
---|---|---|
committer | Patrick Griffis <pgriffis@igalia.com> | 2023-01-16 20:42:46 -0600 |
commit | 8d85d110d9e79c0d04a0f09e384fe98e5f60db1e (patch) | |
tree | 078013e7199db36dbb16bfa9dcc0fa12c90908e3 | |
parent | 493e04bb007db1f0af5416e33f3912261e8afde6 (diff) | |
download | libsoup-8d85d110d9e79c0d04a0f09e384fe98e5f60db1e.tar.gz |
cookies: Add support for cookie prefixes
This is a spec that Firefox and Chrome implement:
https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00
Closes #349
Closes #326
Co-authored-by: Patrick Griffis <pgriffis@igalia.com>
-rw-r--r-- | libsoup/cookies/soup-cookie-jar.c | 20 | ||||
-rw-r--r-- | tests/cookies-test.c | 60 |
2 files changed, 80 insertions, 0 deletions
diff --git a/libsoup/cookies/soup-cookie-jar.c b/libsoup/cookies/soup-cookie-jar.c index 2cc1d410..f02a76c7 100644 --- a/libsoup/cookies/soup-cookie-jar.c +++ b/libsoup/cookies/soup-cookie-jar.c @@ -624,6 +624,26 @@ soup_cookie_jar_add_cookie_full (SoupCookieJar *jar, SoupCookie *cookie, GUri *u return; } + /* See https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00 for handling the prefixes, + * which has been implemented by Firefox and Chrome. */ +#define MATCH_PREFIX(name, prefix) (!g_ascii_strncasecmp (name, prefix, strlen(prefix))) + + /* Cookies with a "__Secure-" prefix should have Secure attribute set and it must be for a secure host. */ + if (MATCH_PREFIX (soup_cookie_get_name (cookie), "__Secure-") && (!soup_cookie_get_secure (cookie) || !uri)) { + soup_cookie_free (cookie); + return; + } + /* Path=/ and Secure attributes are required; Domain attribute must not be present. + Note that SoupCookie always sets the domain so we do exact host matches instead of subdomain matches. */ + if (MATCH_PREFIX (soup_cookie_get_name (cookie), "__Host-")) { + if ((!soup_cookie_get_secure (cookie) || !uri) || + strcmp (soup_cookie_get_path (cookie), "/") != 0 || + g_ascii_strcasecmp (soup_cookie_get_domain (cookie), g_uri_get_host (uri)) != 0) { + soup_cookie_free (cookie); + return; + } + } + g_mutex_lock (&priv->mutex); old_cookies = g_hash_table_lookup (priv->domains, soup_cookie_get_domain (cookie)); diff --git a/tests/cookies-test.c b/tests/cookies-test.c index 1b71ad48..91f6094e 100644 --- a/tests/cookies-test.c +++ b/tests/cookies-test.c @@ -286,6 +286,65 @@ do_cookies_strict_secure_test (void) g_object_unref (jar); } +static void +do_cookies_prefix_test (void) +{ + SoupCookieJar *jar; + GSList *cookies; + GUri *insecure_uri; + GUri *secure_uri; + + insecure_uri = g_uri_parse ("http://gnome.org", SOUP_HTTP_URI_FLAGS, NULL); + secure_uri = g_uri_parse ("https://gnome.org", SOUP_HTTP_URI_FLAGS, NULL); + jar = soup_cookie_jar_new (); + + soup_cookie_jar_add_cookie_full (jar, soup_cookie_parse ("__SeCuRe-Valid-1=1; Path=/; Secure", secure_uri), + secure_uri, NULL); + + /* Without Secure */ + soup_cookie_jar_add_cookie_full (jar, soup_cookie_parse ("__SeCuRe-Invalid-1=1;", secure_uri), + secure_uri, NULL); + + /* Insecure host */ + soup_cookie_jar_add_cookie_full (jar, soup_cookie_parse ("__SECURE-Invalid-2=1; Path=/Somethingelse; Secure", insecure_uri), + insecure_uri, NULL); + + soup_cookie_jar_add_cookie_full (jar, soup_cookie_parse ("__HoSt-Valid-1=1; Path=/; Secure", secure_uri), + secure_uri, NULL); + + /* Invalid Path */ + soup_cookie_jar_add_cookie_full (jar, soup_cookie_parse ("__HOST-Invalid-1=1; Path=/Somethingelse; Secure", secure_uri), + secure_uri, NULL); + + /* Without Secure */ + soup_cookie_jar_add_cookie_full (jar, soup_cookie_parse ("__host-Invalid-2=1; Path=/", secure_uri), + secure_uri, NULL); + + /* Domain forbidden */ + soup_cookie_jar_add_cookie_full (jar, soup_cookie_parse ("__HoSt-Invalid-3=1; Path=/; Secure; Domain=gnome.org", secure_uri), + secure_uri, NULL); + + /* Insecure host */ + soup_cookie_jar_add_cookie_full (jar, soup_cookie_parse ("__host-Invalid-4=1; Path=/; Secure", insecure_uri), + insecure_uri, NULL); + + cookies = soup_cookie_jar_all_cookies (jar); + + for (GSList *l = cookies; l; l = g_slist_next (l)) { + SoupCookie *cookie = l->data; + + g_assert_true (strstr (soup_cookie_get_name (cookie), "Valid") != NULL); + } + + /* In total we expect 2 valid cookies above. */ + g_assert_cmpuint (g_slist_length (cookies), ==, 2); + + g_slist_free_full (cookies, (GDestroyNotify)soup_cookie_free); + g_uri_unref (insecure_uri); + g_uri_unref (secure_uri); + g_object_unref (jar); +} + /* FIXME: moar tests! */ static void do_cookies_parsing_test (void) @@ -545,6 +604,7 @@ main (int argc, char **argv) g_test_add_func ("/cookies/get-cookies/empty-host", do_get_cookies_empty_host_test); g_test_add_func ("/cookies/remove-feature", do_remove_feature_test); g_test_add_func ("/cookies/secure-cookies", do_cookies_strict_secure_test); + g_test_add_func ("/cookies/prefix", do_cookies_prefix_test); g_test_add_func ("/cookies/threads", do_cookies_threads_test); ret = g_test_run (); |