summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiwei Li <siwei.li@live.com>2023-01-16 12:31:10 -0800
committerPatrick Griffis <pgriffis@igalia.com>2023-01-16 20:42:46 -0600
commit8d85d110d9e79c0d04a0f09e384fe98e5f60db1e (patch)
tree078013e7199db36dbb16bfa9dcc0fa12c90908e3
parent493e04bb007db1f0af5416e33f3912261e8afde6 (diff)
downloadlibsoup-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.c20
-rw-r--r--tests/cookies-test.c60
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 ();