changeset 1488:afe771c1d19f

cookie domains
author corvid <corvid@lavabit.com>
date Thu, 31 Dec 2009 22:48:28 +0000
parents a8c342191c16
children 56dcaa255396
files dpi/cookies.c
diffstat 1 files changed, 58 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/dpi/cookies.c	Thu Dec 31 09:25:56 2009 +0000
+++ b/dpi/cookies.c	Thu Dec 31 22:48:28 2009 +0000
@@ -1040,6 +1040,42 @@
 }
 
 /*
+ * Check whether host name A domain-matches host name B.
+ */
+static bool_t Cookies_domain_matches(char *A, char *B)
+{
+   int diff;
+
+   if (!A || !*A || !B || !*B)
+      return FALSE;
+
+   /* "Host A's name domain-matches host B's if their host name strings
+    * string-compare equal; or"...
+    */
+   if (!dStrcasecmp(A, B))
+      return TRUE;
+
+   /* ..."A is a HDN [host domain name] string and has the form NB, where N
+    * is a non-empty name string, B has the form .B', and B' is a HDN string.
+    */
+
+   if (*B != '.') {
+      return FALSE;
+   }
+
+   diff = strlen(A) - strlen(B);
+
+   if (diff > 0) {
+      return (dStrcasecmp(A + diff, B) == 0);
+   } else {
+      /* Consider A to domain-match B if B is of the form .A
+       * CONTRARY TO RFC
+       */
+      return (dStrcasecmp(A, B + 1) == 0);
+   }
+}
+
+/*
  * Validate cookies domain against some security checks.
  */
 static bool_t Cookies_validate_domain(CookieData_t *cookie, char *host,
@@ -1060,11 +1096,19 @@
    /* 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] != '.') {
+      if (cookie->domain) {
+         /* It may be necessary to handle these old-style domains. */
+         MSG("Ignoring cookie domain \'%s\' without leading dot.\n",
+             cookie->domain);
+      }
       dFree(cookie->domain);
       cookie->domain = dStrdup(host);
       return TRUE;
    }
 
+   if (!Cookies_domain_matches(host, cookie->domain))
+      return FALSE;
+
    /* Count the number of dots and also find out if it is an IP-address */
    is_ip = TRUE;
    for (i = 0, dots = 0; cookie->domain[i] != '\0'; i++) {
@@ -1074,13 +1118,24 @@
          is_ip = FALSE;
    }
 
-   /* A valid domain must have at least two dots in it */
-   /* NOTE: this breaks cookies on localhost... */
+   if (i > 0 && cookie->domain[i - 1] == '.') {
+       /* A trailing dot is a sneaky trick, but we won't fall for it. */
+      dots--;
+   }
+
+   /* A valid domain must have at least two dots in it
+    * NOTE: this breaks cookies on localhost...
+    *
+    * TODO: accept the publicsuffix.org list as an optional external file.
+    */
    if (dots < 2) {
       return FALSE;
    }
 
-   /* Now see if the url matches the domain */
+   /* Reject a cookie if the "request-host is a FQDN [fully-qualified domain
+    * name] (not IP address) and has the form HD, where D is the value of the
+    * Domain attribute, and H is a string that contains one or more dots.
+    */
    diff = strlen(host) - i;
    if (diff > 0) {
       if (dStrcasecmp(host + diff, cookie->domain))