]> sjero.net Git - wget/blob - src/cookies.c
Fix compiler warnings
[wget] / src / cookies.c
1 /* Support for cookies.
2    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3    2010, 2011 Free Software Foundation, Inc.
4
5 This file is part of GNU Wget.
6
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at
10 your option) any later version.
11
12 GNU Wget is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work.  */
30
31 /* Written by Hrvoje Niksic.  Parts are loosely inspired by the
32    cookie patch submitted by Tomasz Wegrzanowski.
33
34    This implements the client-side cookie support, as specified
35    (loosely) by Netscape's "preliminary specification", currently
36    available at:
37
38        http://wp.netscape.com/newsref/std/cookie_spec.html
39
40    rfc2109 is not supported because of its incompatibilities with the
41    above widely-used specification.  rfc2965 is entirely ignored,
42    since popular client software doesn't implement it, and even the
43    sites that do send Set-Cookie2 also emit Set-Cookie for
44    compatibility.  */
45
46 #include "wget.h"
47
48 #include <stdio.h>
49 #include <string.h>
50 #include <stdlib.h>
51 #include <assert.h>
52 #include <errno.h>
53 #include <time.h>
54 #include "utils.h"
55 #include "hash.h"
56 #include "cookies.h"
57 #include "http.h"               /* for http_atotm */
58 \f
59 /* Declarations of `struct cookie' and the most basic functions. */
60
61 /* Cookie jar serves as cookie storage and a means of retrieving
62    cookies efficiently.  All cookies with the same domain are stored
63    in a linked list called "chain".  A cookie chain can be reached by
64    looking up the domain in the cookie jar's chains_by_domain table.
65
66    For example, to reach all the cookies under google.com, one must
67    execute hash_table_get(jar->chains_by_domain, "google.com").  Of
68    course, when sending a cookie to `www.google.com', one must search
69    for cookies that belong to either `www.google.com' or `google.com'
70    -- but the point is that the code doesn't need to go through *all*
71    the cookies.  */
72
73 struct cookie_jar {
74   /* Cookie chains indexed by domain.  */
75   struct hash_table *chains;
76
77   int cookie_count;             /* number of cookies in the jar. */
78 };
79
80 /* Value set by entry point functions, so that the low-level
81    routines don't need to call time() all the time.  */
82 static time_t cookies_now;
83
84 struct cookie_jar *
85 cookie_jar_new (void)
86 {
87   struct cookie_jar *jar = xnew (struct cookie_jar);
88   jar->chains = make_nocase_string_hash_table (0);
89   jar->cookie_count = 0;
90   return jar;
91 }
92
93 struct cookie {
94   char *domain;                 /* domain of the cookie */
95   int port;                     /* port number */
96   char *path;                   /* path prefix of the cookie */
97
98   unsigned discard_requested :1; /* whether cookie was created to
99                                    request discarding another
100                                    cookie. */
101
102   unsigned secure :1;           /* whether cookie should be
103                                    transmitted over non-https
104                                    connections. */
105   unsigned domain_exact :1;     /* whether DOMAIN must match as a
106                                    whole. */
107
108   unsigned permanent :1;        /* whether the cookie should outlive
109                                    the session. */
110   time_t expiry_time;           /* time when the cookie expires, 0
111                                    means undetermined. */
112
113   char *attr;                   /* cookie attribute name */
114   char *value;                  /* cookie attribute value */
115
116   struct cookie *next;          /* used for chaining of cookies in the
117                                    same domain. */
118 };
119
120 #define PORT_ANY (-1)
121
122 /* Allocate and return a new, empty cookie structure. */
123
124 static struct cookie *
125 cookie_new (void)
126 {
127   struct cookie *cookie = xnew0 (struct cookie);
128
129   /* Both cookie->permanent and cookie->expiry_time are now 0.  This
130      means that the cookie doesn't expire, but is only valid for this
131      session (i.e. not written out to disk).  */
132
133   cookie->port = PORT_ANY;
134   return cookie;
135 }
136
137 /* Non-zero if the cookie has expired.  Assumes cookies_now has been
138    set by one of the entry point functions.  */
139
140 static bool
141 cookie_expired_p (const struct cookie *c)
142 {
143   return c->expiry_time != 0 && c->expiry_time < cookies_now;
144 }
145
146 /* Deallocate COOKIE and its components. */
147
148 static void
149 delete_cookie (struct cookie *cookie)
150 {
151   xfree_null (cookie->domain);
152   xfree_null (cookie->path);
153   xfree_null (cookie->attr);
154   xfree_null (cookie->value);
155   xfree (cookie);
156 }
157 \f
158 /* Functions for storing cookies.
159
160    All cookies can be reached beginning with jar->chains.  The key in
161    that table is the domain name, and the value is a linked list of
162    all cookies from that domain.  Every new cookie is placed on the
163    head of the list.  */
164
165 /* Find and return a cookie in JAR whose domain, path, and attribute
166    name correspond to COOKIE.  If found, PREVPTR will point to the
167    location of the cookie previous in chain, or NULL if the found
168    cookie is the head of a chain.
169
170    If no matching cookie is found, return NULL. */
171
172 static struct cookie *
173 find_matching_cookie (struct cookie_jar *jar, struct cookie *cookie,
174                       struct cookie **prevptr)
175 {
176   struct cookie *chain, *prev;
177
178   chain = hash_table_get (jar->chains, cookie->domain);
179   if (!chain)
180     goto nomatch;
181
182   prev = NULL;
183   for (; chain; prev = chain, chain = chain->next)
184     if (0 == strcmp (cookie->path, chain->path)
185         && 0 == strcmp (cookie->attr, chain->attr)
186         && cookie->port == chain->port)
187       {
188         *prevptr = prev;
189         return chain;
190       }
191
192  nomatch:
193   *prevptr = NULL;
194   return NULL;
195 }
196
197 /* Store COOKIE to the jar.
198
199    This is done by placing COOKIE at the head of its chain.  However,
200    if COOKIE matches a cookie already in memory, as determined by
201    find_matching_cookie, the old cookie is unlinked and destroyed.
202
203    The key of each chain's hash table entry is allocated only the
204    first time; next hash_table_put's reuse the same key.  */
205
206 static void
207 store_cookie (struct cookie_jar *jar, struct cookie *cookie)
208 {
209   struct cookie *chain_head;
210   char *chain_key;
211
212   if (hash_table_get_pair (jar->chains, cookie->domain,
213                            &chain_key, &chain_head))
214     {
215       /* A chain of cookies in this domain already exists.  Check for
216          duplicates -- if an extant cookie exactly matches our domain,
217          port, path, and name, replace it.  */
218       struct cookie *prev;
219       struct cookie *victim = find_matching_cookie (jar, cookie, &prev);
220
221       if (victim)
222         {
223           /* Remove VICTIM from the chain.  COOKIE will be placed at
224              the head. */
225           if (prev)
226             {
227               prev->next = victim->next;
228               cookie->next = chain_head;
229             }
230           else
231             {
232               /* prev is NULL; apparently VICTIM was at the head of
233                  the chain.  This place will be taken by COOKIE, so
234                  all we need to do is:  */
235               cookie->next = victim->next;
236             }
237           delete_cookie (victim);
238           --jar->cookie_count;
239           DEBUGP (("Deleted old cookie (to be replaced.)\n"));
240         }
241       else
242         cookie->next = chain_head;
243     }
244   else
245     {
246       /* We are now creating the chain.  Use a copy of cookie->domain
247          as the key for the life-time of the chain.  Using
248          cookie->domain would be unsafe because the life-time of the
249          chain may exceed the life-time of the cookie.  (Cookies may
250          be deleted from the chain by this very function.)  */
251       cookie->next = NULL;
252       chain_key = xstrdup (cookie->domain);
253     }
254
255   hash_table_put (jar->chains, chain_key, cookie);
256   ++jar->cookie_count;
257
258   IF_DEBUG
259     {
260       time_t exptime = cookie->expiry_time;
261       DEBUGP (("\nStored cookie %s %d%s %s <%s> <%s> [expiry %s] %s %s\n",
262                cookie->domain, cookie->port,
263                cookie->port == PORT_ANY ? " (ANY)" : "",
264                cookie->path,
265                cookie->permanent ? "permanent" : "session",
266                cookie->secure ? "secure" : "insecure",
267                cookie->expiry_time ? datetime_str (exptime) : "none",
268                cookie->attr, cookie->value));
269     }
270 }
271
272 /* Discard a cookie matching COOKIE's domain, port, path, and
273    attribute name.  This gets called when we encounter a cookie whose
274    expiry date is in the past, or whose max-age is set to 0.  The
275    former corresponds to netscape cookie spec, while the latter is
276    specified by rfc2109.  */
277
278 static void
279 discard_matching_cookie (struct cookie_jar *jar, struct cookie *cookie)
280 {
281   struct cookie *prev, *victim;
282
283   if (!hash_table_count (jar->chains))
284     /* No elements == nothing to discard. */
285     return;
286
287   victim = find_matching_cookie (jar, cookie, &prev);
288   if (victim)
289     {
290       if (prev)
291         /* Simply unchain the victim. */
292         prev->next = victim->next;
293       else
294         {
295           /* VICTIM was head of its chain.  We need to place a new
296              cookie at the head.  */
297           char *chain_key = NULL;
298           int res;
299
300           res = hash_table_get_pair (jar->chains, victim->domain,
301                                      &chain_key, NULL);
302           assert (res != 0);
303           if (!victim->next)
304             {
305               /* VICTIM was the only cookie in the chain.  Destroy the
306                  chain and deallocate the chain key.  */
307               hash_table_remove (jar->chains, victim->domain);
308               xfree (chain_key);
309             }
310           else
311             hash_table_put (jar->chains, chain_key, victim->next);
312         }
313       delete_cookie (victim);
314       DEBUGP (("Discarded old cookie.\n"));
315     }
316 }
317 \f
318 /* Functions for parsing the `Set-Cookie' header, and creating new
319    cookies from the wire.  */
320
321 #define TOKEN_IS(token, string_literal)                         \
322   BOUNDED_EQUAL_NO_CASE (token.b, token.e, string_literal)
323
324 #define TOKEN_NON_EMPTY(token) (token.b != NULL && token.b != token.e)
325
326 /* Parse the contents of the `Set-Cookie' header.  The header looks
327    like this:
328
329    name1=value1; name2=value2; ...
330
331    Trailing semicolon is optional; spaces are allowed between all
332    tokens.  Additionally, values may be quoted.
333
334    A new cookie is returned upon success, NULL otherwise.
335
336    The first name-value pair will be used to set the cookie's
337    attribute name and value.  Subsequent parameters will be checked
338    against field names such as `domain', `path', etc.  Recognized
339    fields will be parsed and the corresponding members of COOKIE
340    filled.  */
341
342 static struct cookie *
343 parse_set_cookie (const char *set_cookie, bool silent)
344 {
345   const char *ptr = set_cookie;
346   struct cookie *cookie = cookie_new ();
347   param_token name, value;
348
349   if (!extract_param (&ptr, &name, &value, ';', NULL))
350     goto error;
351   if (!value.b)
352     goto error;
353
354   /* If the value is quoted, do not modify it.  */
355   if (*(value.b - 1) == '"')
356     value.b--;
357   if (*value.e == '"')
358     value.e++;
359
360   cookie->attr = strdupdelim (name.b, name.e);
361   cookie->value = strdupdelim (value.b, value.e);
362
363   while (extract_param (&ptr, &name, &value, ';', NULL))
364     {
365       if (TOKEN_IS (name, "domain"))
366         {
367           if (!TOKEN_NON_EMPTY (value))
368             goto error;
369           xfree_null (cookie->domain);
370           /* Strictly speaking, we should set cookie->domain_exact if the
371              domain doesn't begin with a dot.  But many sites set the
372              domain to "foo.com" and expect "subhost.foo.com" to get the
373              cookie, and it apparently works in browsers.  */
374           if (*value.b == '.')
375             ++value.b;
376           cookie->domain = strdupdelim (value.b, value.e);
377         }
378       else if (TOKEN_IS (name, "path"))
379         {
380           if (!TOKEN_NON_EMPTY (value))
381             goto error;
382           xfree_null (cookie->path);
383           cookie->path = strdupdelim (value.b, value.e);
384         }
385       else if (TOKEN_IS (name, "expires"))
386         {
387           char *value_copy;
388           time_t expires;
389
390           if (!TOKEN_NON_EMPTY (value))
391             goto error;
392           BOUNDED_TO_ALLOCA (value.b, value.e, value_copy);
393
394           /* Check if expiration spec is valid.
395              If not, assume default (cookie doesn't expire, but valid only for
396              this session.) */
397           expires = http_atotm (value_copy);
398           if (expires != (time_t) -1)
399             {
400               cookie->permanent = 1;
401               cookie->expiry_time = expires;
402               /* According to netscape's specification, expiry time in
403                  the past means that discarding of a matching cookie
404                  is requested.  */
405               if (cookie->expiry_time < cookies_now)
406                 cookie->discard_requested = 1;
407             }
408         }
409       else if (TOKEN_IS (name, "max-age"))
410         {
411           double maxage = -1;
412           char *value_copy;
413
414           if (!TOKEN_NON_EMPTY (value))
415             goto error;
416           BOUNDED_TO_ALLOCA (value.b, value.e, value_copy);
417
418           sscanf (value_copy, "%lf", &maxage);
419           if (maxage == -1)
420             /* something went wrong. */
421             goto error;
422           cookie->permanent = 1;
423           cookie->expiry_time = cookies_now + maxage;
424
425           /* According to rfc2109, a cookie with max-age of 0 means that
426              discarding of a matching cookie is requested.  */
427           if (maxage == 0)
428             cookie->discard_requested = 1;
429         }
430       else if (TOKEN_IS (name, "secure"))
431         {
432           /* ignore value completely */
433           cookie->secure = 1;
434         }
435       /* else: Ignore unrecognized attribute. */
436     }
437   if (*ptr)
438     /* extract_param has encountered a syntax error */
439     goto error;
440
441   /* The cookie has been successfully constructed; return it. */
442   return cookie;
443
444  error:
445   if (!silent)
446     logprintf (LOG_NOTQUIET,
447                _("Syntax error in Set-Cookie: %s at position %d.\n"),
448                quotearg_style (escape_quoting_style, set_cookie),
449                (int) (ptr - set_cookie));
450   delete_cookie (cookie);
451   return NULL;
452 }
453
454 #undef TOKEN_IS
455 #undef TOKEN_NON_EMPTY
456 \f
457 /* Sanity checks.  These are important, otherwise it is possible for
458    mailcious attackers to destroy important cookie information and/or
459    violate your privacy.  */
460
461
462 #define REQUIRE_DIGITS(p) do {                  \
463   if (!c_isdigit (*p))                            \
464     return false;                               \
465   for (++p; c_isdigit (*p); p++)                  \
466     ;                                           \
467 } while (0)
468
469 #define REQUIRE_DOT(p) do {                     \
470   if (*p++ != '.')                              \
471     return false;                               \
472 } while (0)
473
474 /* Check whether ADDR matches <digits>.<digits>.<digits>.<digits>.
475
476    We don't want to call network functions like inet_addr() because
477    all we need is a check, preferrably one that is small, fast, and
478    well-defined.  */
479
480 static bool
481 numeric_address_p (const char *addr)
482 {
483   const char *p = addr;
484
485   REQUIRE_DIGITS (p);           /* A */
486   REQUIRE_DOT (p);              /* . */
487   REQUIRE_DIGITS (p);           /* B */
488   REQUIRE_DOT (p);              /* . */
489   REQUIRE_DIGITS (p);           /* C */
490   REQUIRE_DOT (p);              /* . */
491   REQUIRE_DIGITS (p);           /* D */
492
493   if (*p != '\0')
494     return false;
495   return true;
496 }
497
498 /* Check whether COOKIE_DOMAIN is an appropriate domain for HOST.
499    Originally I tried to make the check compliant with rfc2109, but
500    the sites deviated too often, so I had to fall back to "tail
501    matching", as defined by the original Netscape's cookie spec.  */
502
503 static bool
504 check_domain_match (const char *cookie_domain, const char *host)
505 {
506   DEBUGP (("cdm: 1"));
507
508   /* Numeric address requires exact match.  It also requires HOST to
509      be an IP address.  */
510   if (numeric_address_p (cookie_domain))
511     return 0 == strcmp (cookie_domain, host);
512
513   DEBUGP ((" 2"));
514
515   /* For the sake of efficiency, check for exact match first. */
516   if (0 == strcasecmp (cookie_domain, host))
517     return true;
518
519   DEBUGP ((" 3"));
520
521   /* HOST must match the tail of cookie_domain. */
522   if (!match_tail (host, cookie_domain, true))
523     return false;
524
525   /* We know that COOKIE_DOMAIN is a subset of HOST; however, we must
526      make sure that somebody is not trying to set the cookie for a
527      subdomain shared by many entities.  For example, "company.co.uk"
528      must not be allowed to set a cookie for ".co.uk".  On the other
529      hand, "sso.redhat.de" should be able to set a cookie for
530      ".redhat.de".
531
532      The only marginally sane way to handle this I can think of is to
533      reject on the basis of the length of the second-level domain name
534      (but when the top-level domain is unknown), with the assumption
535      that those of three or less characters could be reserved.  For
536      example:
537
538           .co.org -> works because the TLD is known
539            .co.uk -> doesn't work because "co" is only two chars long
540           .com.au -> doesn't work because "com" is only 3 chars long
541           .cnn.uk -> doesn't work because "cnn" is also only 3 chars long (ugh)
542           .cnn.de -> doesn't work for the same reason (ugh!!)
543          .abcd.de -> works because "abcd" is 4 chars long
544       .img.cnn.de -> works because it's not trying to set the 2nd level domain
545        .cnn.co.uk -> works for the same reason
546
547     That should prevent misuse, while allowing reasonable usage.  If
548     someone knows of a better way to handle this, please let me
549     know.  */
550   {
551     const char *p = cookie_domain;
552     int dccount = 1;            /* number of domain components */
553     int ldcl  = 0;              /* last domain component length */
554     int nldcl = 0;              /* next to last domain component length */
555     int out;
556     if (*p == '.')
557       /* Ignore leading period in this calculation. */
558       ++p;
559     DEBUGP ((" 4"));
560     for (out = 0; !out; p++)
561       switch (*p)
562         {
563         case '\0':
564           out = 1;
565           break;
566         case '.':
567           if (ldcl == 0)
568             /* Empty domain component found -- the domain is invalid. */
569             return false;
570           if (*(p + 1) == '\0')
571             {
572               /* Tolerate trailing '.' by not treating the domain as
573                  one ending with an empty domain component.  */
574               out = 1;
575               break;
576             }
577           nldcl = ldcl;
578           ldcl  = 0;
579           ++dccount;
580           break;
581         default:
582           ++ldcl;
583         }
584
585     DEBUGP ((" 5"));
586
587     if (dccount < 2)
588       return false;
589
590     DEBUGP ((" 6"));
591
592     if (dccount == 2)
593       {
594         size_t i;
595         int known_toplevel = false;
596         static const char *known_toplevel_domains[] = {
597           ".com", ".edu", ".net", ".org", ".gov", ".mil", ".int"
598         };
599         for (i = 0; i < countof (known_toplevel_domains); i++)
600           if (match_tail (cookie_domain, known_toplevel_domains[i], true))
601             {
602               known_toplevel = true;
603               break;
604             }
605         if (!known_toplevel && nldcl <= 3)
606           return false;
607       }
608   }
609
610   DEBUGP ((" 7"));
611
612   /* Don't allow the host "foobar.com" to set a cookie for domain
613      "bar.com".  */
614   if (*cookie_domain != '.')
615     {
616       int dlen = strlen (cookie_domain);
617       int hlen = strlen (host);
618       /* cookie host:    hostname.foobar.com */
619       /* desired domain:             bar.com */
620       /* '.' must be here in host-> ^        */
621       if (hlen > dlen && host[hlen - dlen - 1] != '.')
622         return false;
623     }
624
625   DEBUGP ((" 8"));
626
627   return true;
628 }
629
630 static int path_matches (const char *, const char *);
631
632 /* Check whether PATH begins with COOKIE_PATH. */
633
634 static bool
635 check_path_match (const char *cookie_path, const char *path)
636 {
637   return path_matches (path, cookie_path) != 0;
638 }
639
640 /* Prepend '/' to string S.  S is copied to fresh stack-allocated
641    space and its value is modified to point to the new location.  */
642
643 #define PREPEND_SLASH(s) do {                                   \
644   char *PS_newstr = (char *) alloca (1 + strlen (s) + 1);       \
645   *PS_newstr = '/';                                             \
646   strcpy (PS_newstr + 1, s);                                    \
647   s = PS_newstr;                                                \
648 } while (0)
649
650 \f
651 /* Process the HTTP `Set-Cookie' header.  This results in storing the
652    cookie or discarding a matching one, or ignoring it completely, all
653    depending on the contents.  */
654
655 void
656 cookie_handle_set_cookie (struct cookie_jar *jar,
657                           const char *host, int port,
658                           const char *path, const char *set_cookie)
659 {
660   struct cookie *cookie;
661   cookies_now = time (NULL);
662
663   /* Wget's paths don't begin with '/' (blame rfc1808), but cookie
664      usage assumes /-prefixed paths.  Until the rest of Wget is fixed,
665      simply prepend slash to PATH.  */
666   PREPEND_SLASH (path);
667
668   cookie = parse_set_cookie (set_cookie, false);
669   if (!cookie)
670     goto out;
671
672   /* Sanitize parts of cookie. */
673
674   if (!cookie->domain)
675     {
676       cookie->domain = xstrdup (host);
677       cookie->domain_exact = 1;
678       /* Set the port, but only if it's non-default. */
679       if (port != 80 && port != 443)
680         cookie->port = port;
681     }
682   else
683     {
684       if (!check_domain_match (cookie->domain, host))
685         {
686           logprintf (LOG_NOTQUIET,
687                      _("Cookie coming from %s attempted to set domain to "),
688                      quotearg_style (escape_quoting_style, host));
689           logprintf (LOG_NOTQUIET,
690                      _("%s\n"),
691                      quotearg_style (escape_quoting_style, cookie->domain));
692           cookie->discard_requested = true;
693         }
694     }
695
696   if (!cookie->path)
697     {
698       /* The cookie doesn't set path: set it to the URL path, sans the
699          file part ("/dir/file" truncated to "/dir/").  */
700       char *trailing_slash = strrchr (path, '/');
701       if (trailing_slash)
702         cookie->path = strdupdelim (path, trailing_slash + 1);
703       else
704         /* no slash in the string -- can this even happen? */
705         cookie->path = xstrdup (path);
706     }
707   else
708     {
709       /* The cookie sets its own path; verify that it is legal. */
710       if (!check_path_match (cookie->path, path))
711         {
712           DEBUGP (("Attempt to fake the path: %s, %s\n",
713                    cookie->path, path));
714           goto out;
715         }
716     }
717
718   /* Now store the cookie, or discard an existing cookie, if
719      discarding was requested.  */
720
721   if (cookie->discard_requested)
722     {
723       discard_matching_cookie (jar, cookie);
724       goto out;
725     }
726
727   store_cookie (jar, cookie);
728   return;
729
730  out:
731   if (cookie)
732     delete_cookie (cookie);
733 }
734 \f
735 /* Support for sending out cookies in HTTP requests, based on
736    previously stored cookies.  Entry point is
737    `build_cookies_request'.  */
738
739 /* Return a count of how many times CHR occurs in STRING. */
740
741 static int
742 count_char (const char *string, char chr)
743 {
744   const char *p;
745   int count = 0;
746   for (p = string; *p; p++)
747     if (*p == chr)
748       ++count;
749   return count;
750 }
751
752 /* Find the cookie chains whose domains match HOST and store them to
753    DEST.
754
755    A cookie chain is the head of a list of cookies that belong to a
756    host/domain.  Given HOST "img.search.xemacs.org", this function
757    will return the chains for "img.search.xemacs.org",
758    "search.xemacs.org", and "xemacs.org" -- those of them that exist
759    (if any), that is.
760
761    DEST should be large enough to accept (in the worst case) as many
762    elements as there are domain components of HOST.  */
763
764 static int
765 find_chains_of_host (struct cookie_jar *jar, const char *host,
766                      struct cookie *dest[])
767 {
768   int dest_count = 0;
769   int passes, passcnt;
770
771   /* Bail out quickly if there are no cookies in the jar.  */
772   if (!hash_table_count (jar->chains))
773     return 0;
774
775   if (numeric_address_p (host))
776     /* If host is an IP address, only check for the exact match. */
777     passes = 1;
778   else
779     /* Otherwise, check all the subdomains except the top-level (last)
780        one.  As a domain with N components has N-1 dots, the number of
781        passes equals the number of dots.  */
782     passes = count_char (host, '.');
783
784   passcnt = 0;
785
786   /* Find chains that match HOST, starting with exact match and
787      progressing to less specific domains.  For instance, given HOST
788      fly.srk.fer.hr, first look for fly.srk.fer.hr's chain, then
789      srk.fer.hr's, then fer.hr's.  */
790   while (1)
791     {
792       struct cookie *chain = hash_table_get (jar->chains, host);
793       if (chain)
794         dest[dest_count++] = chain;
795       if (++passcnt >= passes)
796         break;
797       host = strchr (host, '.') + 1;
798     }
799
800   return dest_count;
801 }
802
803 /* If FULL_PATH begins with PREFIX, return the length of PREFIX, zero
804    otherwise.  */
805
806 static int
807 path_matches (const char *full_path, const char *prefix)
808 {
809   int len = strlen (prefix);
810
811   if (0 != strncmp (full_path, prefix, len))
812     /* FULL_PATH doesn't begin with PREFIX. */
813     return 0;
814
815   /* Length of PREFIX determines the quality of the match. */
816   return len + 1;
817 }
818
819 /* Return true iff COOKIE matches the provided parameters of the URL
820    being downloaded: HOST, PORT, PATH, and SECFLAG.
821
822    If PATH_GOODNESS is non-NULL, store the "path goodness" value
823    there.  That value is a measure of how closely COOKIE matches PATH,
824    used for ordering cookies.  */
825
826 static bool
827 cookie_matches_url (const struct cookie *cookie,
828                     const char *host, int port, const char *path,
829                     bool secflag, int *path_goodness)
830 {
831   int pg;
832
833   if (cookie_expired_p (cookie))
834     /* Ignore stale cookies.  Don't bother unchaining the cookie at
835        this point -- Wget is a relatively short-lived application, and
836        stale cookies will not be saved by `save_cookies'.  On the
837        other hand, this function should be as efficient as
838        possible.  */
839     return false;
840
841   if (cookie->secure && !secflag)
842     /* Don't transmit secure cookies over insecure connections.  */
843     return false;
844   if (cookie->port != PORT_ANY && cookie->port != port)
845     return false;
846
847   /* If exact domain match is required, verify that cookie's domain is
848      equal to HOST.  If not, assume success on the grounds of the
849      cookie's chain having been found by find_chains_of_host.  */
850   if (cookie->domain_exact
851       && 0 != strcasecmp (host, cookie->domain))
852     return false;
853
854   pg = path_matches (path, cookie->path);
855   if (pg == 0)
856     return false;
857
858   if (path_goodness)
859     /* If the caller requested path_goodness, we return it.  This is
860        an optimization, so that the caller doesn't need to call
861        path_matches() again.  */
862     *path_goodness = pg;
863   return true;
864 }
865
866 /* A structure that points to a cookie, along with the additional
867    information about the cookie's "goodness".  This allows us to sort
868    the cookies when returning them to the server, as required by the
869    spec.  */
870
871 struct weighed_cookie {
872   struct cookie *cookie;
873   int domain_goodness;
874   int path_goodness;
875 };
876
877 /* Comparator used for uniquifying the list. */
878
879 static int
880 equality_comparator (const void *p1, const void *p2)
881 {
882   struct weighed_cookie *wc1 = (struct weighed_cookie *)p1;
883   struct weighed_cookie *wc2 = (struct weighed_cookie *)p2;
884
885   int namecmp  = strcmp (wc1->cookie->attr, wc2->cookie->attr);
886   int valuecmp = strcmp (wc1->cookie->value, wc2->cookie->value);
887
888   /* We only really care whether both name and value are equal.  We
889      return them in this order only for consistency...  */
890   return namecmp ? namecmp : valuecmp;
891 }
892
893 /* Eliminate duplicate cookies.  "Duplicate cookies" are any two
894    cookies with the same attr name and value.  Whenever a duplicate
895    pair is found, one of the cookies is removed.  */
896
897 static int
898 eliminate_dups (struct weighed_cookie *outgoing, int count)
899 {
900   struct weighed_cookie *h;     /* hare */
901   struct weighed_cookie *t;     /* tortoise */
902   struct weighed_cookie *end = outgoing + count;
903
904   /* We deploy a simple uniquify algorithm: first sort the array
905      according to our sort criteria, then copy it to itself, comparing
906      each cookie to its neighbor and ignoring the duplicates.  */
907
908   qsort (outgoing, count, sizeof (struct weighed_cookie), equality_comparator);
909
910   /* "Hare" runs through all the entries in the array, followed by
911      "tortoise".  If a duplicate is found, the hare skips it.
912      Non-duplicate entries are copied to the tortoise ptr.  */
913
914   for (h = t = outgoing; h < end; h++)
915     {
916       if (h != end - 1)
917         {
918           struct cookie *c0 = h[0].cookie;
919           struct cookie *c1 = h[1].cookie;
920           if (!strcmp (c0->attr, c1->attr) && !strcmp (c0->value, c1->value))
921             continue;           /* ignore the duplicate */
922         }
923
924       /* If the hare has advanced past the tortoise (because of
925          previous dups), make sure the values get copied.  Otherwise,
926          no copying is necessary.  */
927       if (h != t)
928         *t++ = *h;
929       else
930         t++;
931     }
932   return t - outgoing;
933 }
934
935 /* Comparator used for sorting by quality. */
936
937 static int
938 goodness_comparator (const void *p1, const void *p2)
939 {
940   struct weighed_cookie *wc1 = (struct weighed_cookie *)p1;
941   struct weighed_cookie *wc2 = (struct weighed_cookie *)p2;
942
943   /* Subtractions take `wc2' as the first argument becauase we want a
944      sort in *decreasing* order of goodness.  */
945   int dgdiff = wc2->domain_goodness - wc1->domain_goodness;
946   int pgdiff = wc2->path_goodness - wc1->path_goodness;
947
948   /* Sort by domain goodness; if these are the same, sort by path
949      goodness.  (The sorting order isn't really specified; maybe it
950      should be the other way around.)  */
951   return dgdiff ? dgdiff : pgdiff;
952 }
953
954 /* Generate a `Cookie' header for a request that goes to HOST:PORT and
955    requests PATH from the server.  The resulting string is allocated
956    with `malloc', and the caller is responsible for freeing it.  If no
957    cookies pertain to this request, i.e. no cookie header should be
958    generated, NULL is returned.  */
959
960 char *
961 cookie_header (struct cookie_jar *jar, const char *host,
962                int port, const char *path, bool secflag)
963 {
964   struct cookie **chains;
965   int chain_count;
966
967   struct cookie *cookie;
968   struct weighed_cookie *outgoing;
969   int count, i, ocnt;
970   char *result;
971   int result_size, pos;
972   PREPEND_SLASH (path);         /* see cookie_handle_set_cookie */
973
974   /* First, find the cookie chains whose domains match HOST. */
975
976   /* Allocate room for find_chains_of_host to write to.  The number of
977      chains can at most equal the number of subdomains, hence
978      1+<number of dots>.  */
979   chains = alloca_array (struct cookie *, 1 + count_char (host, '.'));
980   chain_count = find_chains_of_host (jar, host, chains);
981
982   /* No cookies for this host. */
983   if (!chain_count)
984     return NULL;
985
986   cookies_now = time (NULL);
987
988   /* Now extract from the chains those cookies that match our host
989      (for domain_exact cookies), port (for cookies with port other
990      than PORT_ANY), etc.  See matching_cookie for details.  */
991
992   /* Count the number of matching cookies. */
993   count = 0;
994   for (i = 0; i < chain_count; i++)
995     for (cookie = chains[i]; cookie; cookie = cookie->next)
996       if (cookie_matches_url (cookie, host, port, path, secflag, NULL))
997         ++count;
998   if (!count)
999     return NULL;                /* no cookies matched */
1000
1001   /* Allocate the array. */
1002   outgoing = alloca_array (struct weighed_cookie, count);
1003
1004   /* Fill the array with all the matching cookies from the chains that
1005      match HOST. */
1006   ocnt = 0;
1007   for (i = 0; i < chain_count; i++)
1008     for (cookie = chains[i]; cookie; cookie = cookie->next)
1009       {
1010         int pg;
1011         if (!cookie_matches_url (cookie, host, port, path, secflag, &pg))
1012           continue;
1013         outgoing[ocnt].cookie = cookie;
1014         outgoing[ocnt].domain_goodness = strlen (cookie->domain);
1015         outgoing[ocnt].path_goodness   = pg;
1016         ++ocnt;
1017       }
1018   assert (ocnt == count);
1019
1020   /* Eliminate duplicate cookies; that is, those whose name and value
1021      are the same.  */
1022   count = eliminate_dups (outgoing, count);
1023
1024   /* Sort the array so that best-matching domains come first, and
1025      that, within one domain, best-matching paths come first. */
1026   qsort (outgoing, count, sizeof (struct weighed_cookie), goodness_comparator);
1027
1028   /* Count the space the name=value pairs will take. */
1029   result_size = 0;
1030   for (i = 0; i < count; i++)
1031     {
1032       struct cookie *c = outgoing[i].cookie;
1033       /* name=value */
1034       result_size += strlen (c->attr) + 1 + strlen (c->value);
1035     }
1036
1037   /* Allocate output buffer:
1038      name=value pairs -- result_size
1039      "; " separators  -- (count - 1) * 2
1040      \0 terminator    -- 1 */
1041   result_size = result_size + (count - 1) * 2 + 1;
1042   result = xmalloc (result_size);
1043   pos = 0;
1044   for (i = 0; i < count; i++)
1045     {
1046       struct cookie *c = outgoing[i].cookie;
1047       int namlen = strlen (c->attr);
1048       int vallen = strlen (c->value);
1049
1050       memcpy (result + pos, c->attr, namlen);
1051       pos += namlen;
1052       result[pos++] = '=';
1053       memcpy (result + pos, c->value, vallen);
1054       pos += vallen;
1055       if (i < count - 1)
1056         {
1057           result[pos++] = ';';
1058           result[pos++] = ' ';
1059         }
1060     }
1061   result[pos++] = '\0';
1062   assert (pos == result_size);
1063   return result;
1064 }
1065 \f
1066 /* Support for loading and saving cookies.  The format used for
1067    loading and saving should be the format of the `cookies.txt' file
1068    used by Netscape and Mozilla, at least the Unix versions.
1069    (Apparently IE can export cookies in that format as well.)  The
1070    format goes like this:
1071
1072        DOMAIN DOMAIN-FLAG PATH SECURE-FLAG TIMESTAMP ATTR-NAME ATTR-VALUE
1073
1074      DOMAIN      -- cookie domain, optionally followed by :PORT
1075      DOMAIN-FLAG -- whether all hosts in the domain match
1076      PATH        -- cookie path
1077      SECURE-FLAG -- whether cookie requires secure connection
1078      TIMESTAMP   -- expiry timestamp, number of seconds since epoch
1079      ATTR-NAME   -- name of the cookie attribute
1080      ATTR-VALUE  -- value of the cookie attribute (empty if absent)
1081
1082    The fields are separated by TABs.  All fields are mandatory, except
1083    for ATTR-VALUE.  The `-FLAG' fields are boolean, their legal values
1084    being "TRUE" and "FALSE'.  Empty lines, lines consisting of
1085    whitespace only, and comment lines (beginning with # optionally
1086    preceded by whitespace) are ignored.
1087
1088    Example line from cookies.txt (split in two lines for readability):
1089
1090        .google.com      TRUE    /       FALSE   2147368447      \
1091        PREF     ID=34bb47565bbcd47b:LD=en:NR=20:TM=985172580:LM=985739012
1092
1093 */
1094
1095 /* If the region [B, E) ends with :<digits>, parse the number, return
1096    it, and store new boundary (location of the `:') to DOMAIN_E_PTR.
1097    If port is not specified, return 0.  */
1098
1099 static int
1100 domain_port (const char *domain_b, const char *domain_e,
1101              const char **domain_e_ptr)
1102 {
1103   int port = 0;
1104   const char *p;
1105   const char *colon = memchr (domain_b, ':', domain_e - domain_b);
1106   if (!colon)
1107     return 0;
1108   for (p = colon + 1; p < domain_e && c_isdigit (*p); p++)
1109     port = 10 * port + (*p - '0');
1110   if (p < domain_e)
1111     /* Garbage following port number. */
1112     return 0;
1113   *domain_e_ptr = colon;
1114   return port;
1115 }
1116
1117 #define GET_WORD(p, b, e) do {                  \
1118   b = p;                                        \
1119   while (*p && *p != '\t')                      \
1120     ++p;                                        \
1121   e = p;                                        \
1122   if (b == e || !*p)                            \
1123     goto next;                                  \
1124   ++p;                                          \
1125 } while (0)
1126
1127 /* Load cookies from FILE.  */
1128
1129 void
1130 cookie_jar_load (struct cookie_jar *jar, const char *file)
1131 {
1132   char *line = NULL;
1133   size_t bufsize = 0;
1134
1135   FILE *fp = fopen (file, "r");
1136   if (!fp)
1137     {
1138       logprintf (LOG_NOTQUIET, _("Cannot open cookies file %s: %s\n"),
1139                  quote (file), strerror (errno));
1140       return;
1141     }
1142
1143   cookies_now = time (NULL);
1144
1145   while (getline (&line, &bufsize, fp) > 0)
1146     {
1147       struct cookie *cookie;
1148       char *p = line;
1149
1150       double expiry;
1151       int port;
1152
1153       char *domain_b  = NULL, *domain_e  = NULL;
1154       char *domflag_b = NULL, *domflag_e = NULL;
1155       char *path_b    = NULL, *path_e    = NULL;
1156       char *secure_b  = NULL, *secure_e  = NULL;
1157       char *expires_b = NULL, *expires_e = NULL;
1158       char *name_b    = NULL, *name_e    = NULL;
1159       char *value_b   = NULL, *value_e   = NULL;
1160
1161       /* Skip leading white-space. */
1162       while (*p && c_isspace (*p))
1163         ++p;
1164       /* Ignore empty lines.  */
1165       if (!*p || *p == '#')
1166         continue;
1167
1168       GET_WORD (p, domain_b,  domain_e);
1169       GET_WORD (p, domflag_b, domflag_e);
1170       GET_WORD (p, path_b,    path_e);
1171       GET_WORD (p, secure_b,  secure_e);
1172       GET_WORD (p, expires_b, expires_e);
1173       GET_WORD (p, name_b,    name_e);
1174
1175       /* Don't use GET_WORD for value because it ends with newline,
1176          not TAB.  */
1177       value_b = p;
1178       value_e = p + strlen (p);
1179       if (value_e > value_b && value_e[-1] == '\n')
1180         --value_e;
1181       if (value_e > value_b && value_e[-1] == '\r')
1182         --value_e;
1183       /* Empty values are legal (I think), so don't bother checking. */
1184
1185       cookie = cookie_new ();
1186
1187       cookie->attr    = strdupdelim (name_b, name_e);
1188       cookie->value   = strdupdelim (value_b, value_e);
1189       cookie->path    = strdupdelim (path_b, path_e);
1190       cookie->secure  = BOUNDED_EQUAL (secure_b, secure_e, "TRUE");
1191
1192       /* Curl source says, quoting Andre Garcia: "flag: A TRUE/FALSE
1193          value indicating if all machines within a given domain can
1194          access the variable.  This value is set automatically by the
1195          browser, depending on the value set for the domain."  */
1196       cookie->domain_exact = !BOUNDED_EQUAL (domflag_b, domflag_e, "TRUE");
1197
1198       /* DOMAIN needs special treatment because we might need to
1199          extract the port.  */
1200       port = domain_port (domain_b, domain_e, (const char **)&domain_e);
1201       if (port)
1202         cookie->port = port;
1203
1204       if (*domain_b == '.')
1205         ++domain_b;             /* remove leading dot internally */
1206       cookie->domain  = strdupdelim (domain_b, domain_e);
1207
1208       /* safe default in case EXPIRES field is garbled. */
1209       expiry = (double)cookies_now - 1;
1210
1211       /* I don't like changing the line, but it's safe here.  (line is
1212          malloced.)  */
1213       *expires_e = '\0';
1214       sscanf (expires_b, "%lf", &expiry);
1215
1216       if (expiry == 0)
1217         {
1218           /* EXPIRY can be 0 for session cookies saved because the
1219              user specified `--keep-session-cookies' in the past.
1220              They remain session cookies, and will be saved only if
1221              the user has specified `keep-session-cookies' again.  */
1222         }
1223       else
1224         {
1225           if (expiry < cookies_now)
1226             goto abort_cookie;  /* ignore stale cookie. */
1227           cookie->expiry_time = expiry;
1228           cookie->permanent = 1;
1229         }
1230
1231       store_cookie (jar, cookie);
1232
1233     next:
1234       continue;
1235
1236     abort_cookie:
1237       delete_cookie (cookie);
1238     }
1239
1240   xfree(line);
1241   fclose (fp);
1242 }
1243
1244 /* Save cookies, in format described above, to FILE. */
1245
1246 void
1247 cookie_jar_save (struct cookie_jar *jar, const char *file)
1248 {
1249   FILE *fp;
1250   hash_table_iterator iter;
1251
1252   DEBUGP (("Saving cookies to %s.\n", file));
1253
1254   cookies_now = time (NULL);
1255
1256   fp = fopen (file, "w");
1257   if (!fp)
1258     {
1259       logprintf (LOG_NOTQUIET, _("Cannot open cookies file %s: %s\n"),
1260                  quote (file), strerror (errno));
1261       return;
1262     }
1263
1264   fputs ("# HTTP cookie file.\n", fp);
1265   fprintf (fp, "# Generated by Wget on %s.\n", datetime_str (cookies_now));
1266   fputs ("# Edit at your own risk.\n\n", fp);
1267
1268   for (hash_table_iterate (jar->chains, &iter);
1269        hash_table_iter_next (&iter);
1270        )
1271     {
1272       const char *domain = iter.key;
1273       struct cookie *cookie = iter.value;
1274       for (; cookie; cookie = cookie->next)
1275         {
1276           if (!cookie->permanent && !opt.keep_session_cookies)
1277             continue;
1278           if (cookie_expired_p (cookie))
1279             continue;
1280           if (!cookie->domain_exact)
1281             fputc ('.', fp);
1282           fputs (domain, fp);
1283           if (cookie->port != PORT_ANY)
1284             fprintf (fp, ":%d", cookie->port);
1285           fprintf (fp, "\t%s\t%s\t%s\t%.0f\t%s\t%s\n",
1286                    cookie->domain_exact ? "FALSE" : "TRUE",
1287                    cookie->path, cookie->secure ? "TRUE" : "FALSE",
1288                    (double)cookie->expiry_time,
1289                    cookie->attr, cookie->value);
1290           if (ferror (fp))
1291             goto out;
1292         }
1293     }
1294  out:
1295   if (ferror (fp))
1296     logprintf (LOG_NOTQUIET, _("Error writing to %s: %s\n"),
1297                quote (file), strerror (errno));
1298   if (fclose (fp) < 0)
1299     logprintf (LOG_NOTQUIET, _("Error closing %s: %s\n"),
1300                quote (file), strerror (errno));
1301
1302   DEBUGP (("Done saving cookies.\n"));
1303 }
1304 \f
1305 /* Clean up cookie-related data. */
1306
1307 void
1308 cookie_jar_delete (struct cookie_jar *jar)
1309 {
1310   /* Iterate over chains (indexed by domain) and free them. */
1311   hash_table_iterator iter;
1312   for (hash_table_iterate (jar->chains, &iter); hash_table_iter_next (&iter); )
1313     {
1314       struct cookie *chain = iter.value;
1315       xfree (iter.key);
1316       /* Then all cookies in this chain. */
1317       while (chain)
1318         {
1319           struct cookie *next = chain->next;
1320           delete_cookie (chain);
1321           chain = next;
1322         }
1323     }
1324   hash_table_destroy (jar->chains);
1325   xfree (jar);
1326 }
1327 \f
1328 /* Test cases.  Currently this is only tests parse_set_cookies.  To
1329    use, recompile Wget with -DTEST_COOKIES and call test_cookies()
1330    from main.  */
1331
1332 #ifdef TEST_COOKIES
1333 void
1334 test_cookies (void)
1335 {
1336   /* Tests expected to succeed: */
1337   static struct {
1338     const char *data;
1339     const char *results[10];
1340   } tests_succ[] = {
1341     { "arg=value", {"arg", "value", NULL} },
1342     { "arg1=value1;arg2=value2", {"arg1", "value1", "arg2", "value2", NULL} },
1343     { "arg1=value1; arg2=value2", {"arg1", "value1", "arg2", "value2", NULL} },
1344     { "arg1=value1;  arg2=value2;", {"arg1", "value1", "arg2", "value2", NULL} },
1345     { "arg1=value1;  arg2=value2;  ", {"arg1", "value1", "arg2", "value2", NULL} },
1346     { "arg1=\"value1\"; arg2=\"\"", {"arg1", "value1", "arg2", "", NULL} },
1347     { "arg=", {"arg", "", NULL} },
1348     { "arg1=; arg2=", {"arg1", "", "arg2", "", NULL} },
1349     { "arg1 = ; arg2= ", {"arg1", "", "arg2", "", NULL} },
1350   };
1351
1352   /* Tests expected to fail: */
1353   static char *tests_fail[] = {
1354     ";",
1355     "arg=\"unterminated",
1356     "=empty-name",
1357     "arg1=;=another-empty-name",
1358   };
1359   int i;
1360
1361   for (i = 0; i < countof (tests_succ); i++)
1362     {
1363       int ind;
1364       const char *data = tests_succ[i].data;
1365       const char **expected = tests_succ[i].results;
1366       struct cookie *c;
1367
1368       c = parse_set_cookie (data, true);
1369       if (!c)
1370         {
1371           printf ("NULL cookie returned for valid data: %s\n", data);
1372           continue;
1373         }
1374
1375       /* Test whether extract_param handles these cases correctly. */
1376       {
1377         param_token name, value;
1378         const char *ptr = data;
1379         int j = 0;
1380         while (extract_param (&ptr, &name, &value, ';', NULL))
1381           {
1382             char *n = strdupdelim (name.b, name.e);
1383             char *v = strdupdelim (value.b, value.e);
1384             if (!expected[j])
1385               {
1386                 printf ("Too many parameters for '%s'\n", data);
1387                 break;
1388               }
1389             if (0 != strcmp (expected[j], n))
1390               printf ("Invalid name %d for '%s' (expected '%s', got '%s')\n",
1391                       j / 2 + 1, data, expected[j], n);
1392             if (0 != strcmp (expected[j + 1], v))
1393               printf ("Invalid value %d for '%s' (expected '%s', got '%s')\n",
1394                       j / 2 + 1, data, expected[j + 1], v);
1395             j += 2;
1396             free (n);
1397             free (v);
1398           }
1399         if (expected[j])
1400           printf ("Too few parameters for '%s'\n", data);
1401       }
1402     }
1403
1404   for (i = 0; i < countof (tests_fail); i++)
1405     {
1406       struct cookie *c;
1407       char *data = tests_fail[i];
1408       c = parse_set_cookie (data, true);
1409       if (c)
1410         printf ("Failed to report error on invalid data: %s\n", data);
1411     }
1412 }
1413 #endif /* TEST_COOKIES */