0b9c8d337c8b8c53f795bf679103ca8a455d47f3
[platform/upstream/curl.git] / lib / cookie.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22
23 /***
24
25
26 RECEIVING COOKIE INFORMATION
27 ============================
28
29 struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
30                     const char *file, struct CookieInfo *inc, bool newsession);
31
32         Inits a cookie struct to store data in a local file. This is always
33         called before any cookies are set.
34
35 struct Cookie *Curl_cookie_add(struct SessionHandle *data,
36                  struct CookieInfo *c, bool httpheader, char *lineptr,
37                  const char *domain, const char *path);
38
39         The 'lineptr' parameter is a full "Set-cookie:" line as
40         received from a server.
41
42         The function need to replace previously stored lines that this new
43         line superceeds.
44
45         It may remove lines that are expired.
46
47         It should return an indication of success/error.
48
49
50 SENDING COOKIE INFORMATION
51 ==========================
52
53 struct Cookies *Curl_cookie_getlist(struct CookieInfo *cookie,
54                                     char *host, char *path, bool secure);
55
56         For a given host and path, return a linked list of cookies that
57         the client should send to the server if used now. The secure
58         boolean informs the cookie if a secure connection is achieved or
59         not.
60
61         It shall only return cookies that haven't expired.
62
63
64 Example set of cookies:
65
66     Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure
67     Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
68     domain=.fidelity.com; path=/ftgw; secure
69     Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
70     domain=.fidelity.com; path=/; secure
71     Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
72     domain=.fidelity.com; path=/; secure
73     Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
74     domain=.fidelity.com; path=/; secure
75     Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT;
76     domain=.fidelity.com; path=/; secure
77     Set-cookie:
78     Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday,
79     13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure
80 ****/
81
82
83 #include "curl_setup.h"
84
85 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
86
87 #define _MPRINTF_REPLACE
88 #include <curl/mprintf.h>
89
90 #include "urldata.h"
91 #include "cookie.h"
92 #include "strequal.h"
93 #include "strtok.h"
94 #include "sendf.h"
95 #include "slist.h"
96 #include "curl_memory.h"
97 #include "share.h"
98 #include "strtoofft.h"
99 #include "rawstr.h"
100 #include "curl_memrchr.h"
101 #include "inet_pton.h"
102
103 /* The last #include file should be: */
104 #include "memdebug.h"
105
106 static void freecookie(struct Cookie *co)
107 {
108   if(co->expirestr)
109     free(co->expirestr);
110   if(co->domain)
111     free(co->domain);
112   if(co->path)
113     free(co->path);
114   if(co->spath)
115     free(co->spath);
116   if(co->name)
117     free(co->name);
118   if(co->value)
119     free(co->value);
120   if(co->maxage)
121     free(co->maxage);
122   if(co->version)
123     free(co->version);
124
125   free(co);
126 }
127
128 static bool tailmatch(const char *cooke_domain, const char *hostname)
129 {
130   size_t cookie_domain_len = strlen(cooke_domain);
131   size_t hostname_len = strlen(hostname);
132
133   if(hostname_len < cookie_domain_len)
134     return FALSE;
135
136   if(!Curl_raw_equal(cooke_domain, hostname+hostname_len-cookie_domain_len))
137     return FALSE;
138
139   /* A lead char of cookie_domain is not '.'.
140      RFC6265 4.1.2.3. The Domain Attribute says:
141        For example, if the value of the Domain attribute is
142        "example.com", the user agent will include the cookie in the Cookie
143        header when making HTTP requests to example.com, www.example.com, and
144        www.corp.example.com.
145    */
146   if(hostname_len == cookie_domain_len)
147     return TRUE;
148   if('.' == *(hostname + hostname_len - cookie_domain_len - 1))
149     return TRUE;
150   return FALSE;
151 }
152
153 /*
154  * matching cookie path and url path
155  * RFC6265 5.1.4 Paths and Path-Match
156  */
157 static bool pathmatch(const char* cookie_path, const char* request_uri)
158 {
159   size_t cookie_path_len;
160   size_t uri_path_len;
161   char* uri_path = NULL;
162   char* pos;
163   bool ret = FALSE;
164
165   /* cookie_path must not have last '/' separator. ex: /sample */
166   cookie_path_len = strlen(cookie_path);
167   if(1 == cookie_path_len) {
168     /* cookie_path must be '/' */
169     return TRUE;
170   }
171
172   uri_path = strdup(request_uri);
173   if(!uri_path)
174     return FALSE;
175   pos = strchr(uri_path, '?');
176   if(pos)
177     *pos = 0x0;
178
179   /* #-fragments are already cut off! */
180   if(0 == strlen(uri_path) || uri_path[0] != '/') {
181     free(uri_path);
182     uri_path = strdup("/");
183     if(!uri_path)
184       return FALSE;
185   }
186
187   /* here, RFC6265 5.1.4 says
188      4. Output the characters of the uri-path from the first character up
189         to, but not including, the right-most %x2F ("/").
190      but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
191      without redirect.
192      Ignore this algorithm because /hoge is uri path for this case
193      (uri path is not /).
194    */
195
196   uri_path_len = strlen(uri_path);
197
198   if(uri_path_len < cookie_path_len) {
199     ret = FALSE;
200     goto pathmatched;
201   }
202
203   /* not using checkprefix() because matching should be case-sensitive */
204   if(strncmp(cookie_path, uri_path, cookie_path_len)) {
205     ret = FALSE;
206     goto pathmatched;
207   }
208
209   /* The cookie-path and the uri-path are identical. */
210   if(cookie_path_len == uri_path_len) {
211     ret = TRUE;
212     goto pathmatched;
213   }
214
215   /* here, cookie_path_len < url_path_len */
216   if(uri_path[cookie_path_len] == '/') {
217     ret = TRUE;
218     goto pathmatched;
219   }
220
221   ret = FALSE;
222
223 pathmatched:
224   free(uri_path);
225   return ret;
226 }
227
228 /*
229  * cookie path sanitize
230  */
231 static char *sanitize_cookie_path(const char *cookie_path)
232 {
233   size_t len;
234   char *new_path = strdup(cookie_path);
235   if(!new_path)
236     return NULL;
237
238   /* some stupid site sends path attribute with '"'. */
239   if(new_path[0] == '\"') {
240     memmove((void *)new_path, (const void *)(new_path + 1), strlen(new_path));
241   }
242   if(new_path[strlen(new_path) - 1] == '\"') {
243     new_path[strlen(new_path) - 1] = 0x0;
244   }
245
246   /* RFC6265 5.2.4 The Path Attribute */
247   if(new_path[0] != '/') {
248     /* Let cookie-path be the default-path. */
249     free(new_path);
250     new_path = strdup("/");
251     return new_path;
252   }
253
254   /* convert /hoge/ to /hoge */
255   len = strlen(new_path);
256   if(1 < len && new_path[len - 1] == '/') {
257     new_path[len - 1] = 0x0;
258   }
259
260   return new_path;
261 }
262
263 /*
264  * Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
265  *
266  * NOTE: OOM or cookie parsing failures are ignored.
267  */
268 void Curl_cookie_loadfiles(struct SessionHandle *data)
269 {
270   struct curl_slist *list = data->change.cookielist;
271   if(list) {
272     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
273     while(list) {
274       struct CookieInfo *newcookies = Curl_cookie_init(data,
275                                         list->data,
276                                         data->cookies,
277                                         data->set.cookiesession);
278       if(!newcookies)
279         /* Failure may be due to OOM or a bad cookie; both are ignored
280          * but only the first should be
281          */
282         infof(data, "ignoring failed cookie_init for %s\n", list->data);
283       else
284         data->cookies = newcookies;
285       list = list->next;
286     }
287     curl_slist_free_all(data->change.cookielist); /* clean up list */
288     data->change.cookielist = NULL; /* don't do this again! */
289     Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
290   }
291 }
292
293 /*
294  * strstore() makes a strdup() on the 'newstr' and if '*str' is non-NULL
295  * that will be freed before the allocated string is stored there.
296  *
297  * It is meant to easily replace strdup()
298  */
299 static void strstore(char **str, const char *newstr)
300 {
301   if(*str)
302     free(*str);
303   *str = strdup(newstr);
304 }
305
306 /*
307  * remove_expired() removes expired cookies.
308  */
309 static void remove_expired(struct CookieInfo *cookies)
310 {
311   struct Cookie *co, *nx, *pv;
312   curl_off_t now = (curl_off_t)time(NULL);
313
314   co = cookies->cookies;
315   pv = NULL;
316   while(co) {
317     nx = co->next;
318     if((co->expirestr || co->maxage) && co->expires < now) {
319       if(co == cookies->cookies) {
320         cookies->cookies = co->next;
321       }
322       else {
323         pv->next = co->next;
324       }
325       cookies->numcookies--;
326       freecookie(co);
327     }
328     else {
329       pv = co;
330     }
331     co = nx;
332   }
333 }
334
335 /*
336  * Return true if the given string is an IP(v4|v6) address.
337  */
338 static bool isip(const char *domain)
339 {
340   struct in_addr addr;
341 #ifdef ENABLE_IPV6
342   struct in6_addr addr6;
343 #endif
344
345   if(Curl_inet_pton(AF_INET, domain, &addr)
346 #ifdef ENABLE_IPV6
347      || Curl_inet_pton(AF_INET6, domain, &addr6)
348 #endif
349     ) {
350     /* domain name given as IP address */
351     return TRUE;
352   }
353
354   return FALSE;
355 }
356
357 /****************************************************************************
358  *
359  * Curl_cookie_add()
360  *
361  * Add a single cookie line to the cookie keeping object.
362  *
363  * Be aware that sometimes we get an IP-only host name, and that might also be
364  * a numerical IPv6 address.
365  *
366  * Returns NULL on out of memory or invalid cookie. This is suboptimal,
367  * as they should be treated separately.
368  ***************************************************************************/
369
370 struct Cookie *
371 Curl_cookie_add(struct SessionHandle *data,
372                 /* The 'data' pointer here may be NULL at times, and thus
373                    must only be used very carefully for things that can deal
374                    with data being NULL. Such as infof() and similar */
375
376                 struct CookieInfo *c,
377                 bool httpheader, /* TRUE if HTTP header-style line */
378                 char *lineptr,   /* first character of the line */
379                 const char *domain, /* default domain */
380                 const char *path)   /* full path used when this cookie is set,
381                                        used to get default path for the cookie
382                                        unless set */
383 {
384   struct Cookie *clist;
385   char name[MAX_NAME];
386   struct Cookie *co;
387   struct Cookie *lastc=NULL;
388   time_t now = time(NULL);
389   bool replace_old = FALSE;
390   bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
391
392 #ifdef CURL_DISABLE_VERBOSE_STRINGS
393   (void)data;
394 #endif
395
396   /* First, alloc and init a new struct for it */
397   co = calloc(1, sizeof(struct Cookie));
398   if(!co)
399     return NULL; /* bail out if we're this low on memory */
400
401   if(httpheader) {
402     /* This line was read off a HTTP-header */
403     const char *ptr;
404     const char *semiptr;
405     char *what;
406
407     what = malloc(MAX_COOKIE_LINE);
408     if(!what) {
409       free(co);
410       return NULL;
411     }
412
413     semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
414
415     while(*lineptr && ISBLANK(*lineptr))
416       lineptr++;
417
418     ptr = lineptr;
419     do {
420       /* we have a <what>=<this> pair or a stand-alone word here */
421       name[0]=what[0]=0; /* init the buffers */
422       if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n =]=%"
423                      MAX_COOKIE_LINE_TXT "[^;\r\n]",
424                      name, what)) {
425         /* Use strstore() below to properly deal with received cookie
426            headers that have the same string property set more than once,
427            and then we use the last one. */
428         const char *whatptr;
429         bool done = FALSE;
430         bool sep;
431         size_t len=strlen(what);
432         const char *endofn = &ptr[ strlen(name) ];
433
434         /* skip trailing spaces in name */
435         while(*endofn && ISBLANK(*endofn))
436           endofn++;
437
438         /* name ends with a '=' ? */
439         sep = (*endofn == '=')?TRUE:FALSE;
440
441         /* Strip off trailing whitespace from the 'what' */
442         while(len && ISBLANK(what[len-1])) {
443           what[len-1]=0;
444           len--;
445         }
446
447         /* Skip leading whitespace from the 'what' */
448         whatptr=what;
449         while(*whatptr && ISBLANK(*whatptr))
450           whatptr++;
451
452         if(!len) {
453           /* this was a "<name>=" with no content, and we must allow
454              'secure' and 'httponly' specified this weirdly */
455           done = TRUE;
456           if(Curl_raw_equal("secure", name))
457             co->secure = TRUE;
458           else if(Curl_raw_equal("httponly", name))
459             co->httponly = TRUE;
460           else if(sep)
461             /* there was a '=' so we're not done parsing this field */
462             done = FALSE;
463         }
464         if(done)
465           ;
466         else if(Curl_raw_equal("path", name)) {
467           strstore(&co->path, whatptr);
468           if(!co->path) {
469             badcookie = TRUE; /* out of memory bad */
470             break;
471           }
472           co->spath = sanitize_cookie_path(co->path);
473           if(!co->spath) {
474             badcookie = TRUE; /* out of memory bad */
475             break;
476           }
477         }
478         else if(Curl_raw_equal("domain", name)) {
479           bool is_ip;
480           const char *dotp;
481
482           /* Now, we make sure that our host is within the given domain,
483              or the given domain is not valid and thus cannot be set. */
484
485           if('.' == whatptr[0])
486             whatptr++; /* ignore preceding dot */
487
488           is_ip = isip(domain ? domain : whatptr);
489
490           /* check for more dots */
491           dotp = strchr(whatptr, '.');
492           if(!dotp)
493             domain=":";
494
495           if(!domain
496              || (is_ip && !strcmp(whatptr, domain))
497              || (!is_ip && tailmatch(whatptr, domain))) {
498             strstore(&co->domain, whatptr);
499             if(!co->domain) {
500               badcookie = TRUE;
501               break;
502             }
503             if(!is_ip)
504               co->tailmatch=TRUE; /* we always do that if the domain name was
505                                      given */
506           }
507           else {
508             /* we did not get a tailmatch and then the attempted set domain
509                is not a domain to which the current host belongs. Mark as
510                bad. */
511             badcookie=TRUE;
512             infof(data, "skipped cookie with bad tailmatch domain: %s\n",
513                   whatptr);
514           }
515         }
516         else if(Curl_raw_equal("version", name)) {
517           strstore(&co->version, whatptr);
518           if(!co->version) {
519             badcookie = TRUE;
520             break;
521           }
522         }
523         else if(Curl_raw_equal("max-age", name)) {
524           /* Defined in RFC2109:
525
526              Optional.  The Max-Age attribute defines the lifetime of the
527              cookie, in seconds.  The delta-seconds value is a decimal non-
528              negative integer.  After delta-seconds seconds elapse, the
529              client should discard the cookie.  A value of zero means the
530              cookie should be discarded immediately.
531
532           */
533           strstore(&co->maxage, whatptr);
534           if(!co->maxage) {
535             badcookie = TRUE;
536             break;
537           }
538         }
539         else if(Curl_raw_equal("expires", name)) {
540           strstore(&co->expirestr, whatptr);
541           if(!co->expirestr) {
542             badcookie = TRUE;
543             break;
544           }
545         }
546         else if(!co->name) {
547           co->name = strdup(name);
548           co->value = strdup(whatptr);
549           if(!co->name || !co->value) {
550             badcookie = TRUE;
551             break;
552           }
553         }
554         /*
555           else this is the second (or more) name we don't know
556           about! */
557       }
558       else {
559         /* this is an "illegal" <what>=<this> pair */
560       }
561
562       if(!semiptr || !*semiptr) {
563         /* we already know there are no more cookies */
564         semiptr = NULL;
565         continue;
566       }
567
568       ptr=semiptr+1;
569       while(*ptr && ISBLANK(*ptr))
570         ptr++;
571       semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
572
573       if(!semiptr && *ptr)
574         /* There are no more semicolons, but there's a final name=value pair
575            coming up */
576         semiptr=strchr(ptr, '\0');
577     } while(semiptr);
578
579     if(co->maxage) {
580       co->expires =
581         curlx_strtoofft((*co->maxage=='\"')?
582                         &co->maxage[1]:&co->maxage[0], NULL, 10);
583       if(CURL_OFF_T_MAX - now < co->expires)
584         /* avoid overflow */
585         co->expires = CURL_OFF_T_MAX;
586       else
587         co->expires += now;
588     }
589     else if(co->expirestr) {
590       /* Note that if the date couldn't get parsed for whatever reason,
591          the cookie will be treated as a session cookie */
592       co->expires = curl_getdate(co->expirestr, NULL);
593
594       /* Session cookies have expires set to 0 so if we get that back
595          from the date parser let's add a second to make it a
596          non-session cookie */
597       if(co->expires == 0)
598         co->expires = 1;
599       else if(co->expires < 0)
600         co->expires = 0;
601     }
602
603     if(!badcookie && !co->domain) {
604       if(domain) {
605         /* no domain was given in the header line, set the default */
606         co->domain=strdup(domain);
607         if(!co->domain)
608           badcookie = TRUE;
609       }
610     }
611
612     if(!badcookie && !co->path && path) {
613       /* No path was given in the header line, set the default.
614          Note that the passed-in path to this function MAY have a '?' and
615          following part that MUST not be stored as part of the path. */
616       char *queryp = strchr(path, '?');
617
618       /* queryp is where the interesting part of the path ends, so now we
619          want to the find the last */
620       char *endslash;
621       if(!queryp)
622         endslash = strrchr(path, '/');
623       else
624         endslash = memrchr(path, '/', (size_t)(queryp - path));
625       if(endslash) {
626         size_t pathlen = (size_t)(endslash-path+1); /* include ending slash */
627         co->path=malloc(pathlen+1); /* one extra for the zero byte */
628         if(co->path) {
629           memcpy(co->path, path, pathlen);
630           co->path[pathlen]=0; /* zero terminate */
631           co->spath = sanitize_cookie_path(co->path);
632           if(!co->spath)
633             badcookie = TRUE; /* out of memory bad */
634         }
635         else
636           badcookie = TRUE;
637       }
638     }
639
640     free(what);
641
642     if(badcookie || !co->name) {
643       /* we didn't get a cookie name or a bad one,
644          this is an illegal line, bail out */
645       freecookie(co);
646       return NULL;
647     }
648
649   }
650   else {
651     /* This line is NOT a HTTP header style line, we do offer support for
652        reading the odd netscape cookies-file format here */
653     char *ptr;
654     char *firstptr;
655     char *tok_buf=NULL;
656     int fields;
657
658     /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies
659        marked with httpOnly after the domain name are not accessible
660        from javascripts, but since curl does not operate at javascript
661        level, we include them anyway. In Firefox's cookie files, these
662        lines are preceded with #HttpOnly_ and then everything is
663        as usual, so we skip 10 characters of the line..
664     */
665     if(strncmp(lineptr, "#HttpOnly_", 10) == 0) {
666       lineptr += 10;
667       co->httponly = TRUE;
668     }
669
670     if(lineptr[0]=='#') {
671       /* don't even try the comments */
672       free(co);
673       return NULL;
674     }
675     /* strip off the possible end-of-line characters */
676     ptr=strchr(lineptr, '\r');
677     if(ptr)
678       *ptr=0; /* clear it */
679     ptr=strchr(lineptr, '\n');
680     if(ptr)
681       *ptr=0; /* clear it */
682
683     firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
684
685     /* Now loop through the fields and init the struct we already have
686        allocated */
687     for(ptr=firstptr, fields=0; ptr && !badcookie;
688         ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
689       switch(fields) {
690       case 0:
691         if(ptr[0]=='.') /* skip preceding dots */
692           ptr++;
693         co->domain = strdup(ptr);
694         if(!co->domain)
695           badcookie = TRUE;
696         break;
697       case 1:
698         /* This field got its explanation on the 23rd of May 2001 by
699            Andrés García:
700
701            flag: A TRUE/FALSE value indicating if all machines within a given
702            domain can access the variable. This value is set automatically by
703            the browser, depending on the value you set for the domain.
704
705            As far as I can see, it is set to true when the cookie says
706            .domain.com and to false when the domain is complete www.domain.com
707         */
708         co->tailmatch = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
709         break;
710       case 2:
711         /* It turns out, that sometimes the file format allows the path
712            field to remain not filled in, we try to detect this and work
713            around it! Andrés García made us aware of this... */
714         if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
715           /* only if the path doesn't look like a boolean option! */
716           co->path = strdup(ptr);
717           if(!co->path)
718             badcookie = TRUE;
719           else {
720             co->spath = sanitize_cookie_path(co->path);
721             if(!co->spath) {
722               badcookie = TRUE; /* out of memory bad */
723             }
724           }
725           break;
726         }
727         /* this doesn't look like a path, make one up! */
728         co->path = strdup("/");
729         if(!co->path)
730           badcookie = TRUE;
731         co->spath = strdup("/");
732         if(!co->spath)
733           badcookie = TRUE;
734         fields++; /* add a field and fall down to secure */
735         /* FALLTHROUGH */
736       case 3:
737         co->secure = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
738         break;
739       case 4:
740         co->expires = curlx_strtoofft(ptr, NULL, 10);
741         break;
742       case 5:
743         co->name = strdup(ptr);
744         if(!co->name)
745           badcookie = TRUE;
746         break;
747       case 6:
748         co->value = strdup(ptr);
749         if(!co->value)
750           badcookie = TRUE;
751         break;
752       }
753     }
754     if(6 == fields) {
755       /* we got a cookie with blank contents, fix it */
756       co->value = strdup("");
757       if(!co->value)
758         badcookie = TRUE;
759       else
760         fields++;
761     }
762
763     if(!badcookie && (7 != fields))
764       /* we did not find the sufficient number of fields */
765       badcookie = TRUE;
766
767     if(badcookie) {
768       freecookie(co);
769       return NULL;
770     }
771
772   }
773
774   if(!c->running &&    /* read from a file */
775      c->newsession &&  /* clean session cookies */
776      !co->expires) {   /* this is a session cookie since it doesn't expire! */
777     freecookie(co);
778     return NULL;
779   }
780
781   co->livecookie = c->running;
782
783   /* now, we have parsed the incoming line, we must now check if this
784      superceeds an already existing cookie, which it may if the previous have
785      the same domain and path as this */
786
787   /* at first, remove expired cookies */
788   remove_expired(c);
789
790   clist = c->cookies;
791   replace_old = FALSE;
792   while(clist) {
793     if(Curl_raw_equal(clist->name, co->name)) {
794       /* the names are identical */
795
796       if(clist->domain && co->domain) {
797         if(Curl_raw_equal(clist->domain, co->domain))
798           /* The domains are identical */
799           replace_old=TRUE;
800       }
801       else if(!clist->domain && !co->domain)
802         replace_old = TRUE;
803
804       if(replace_old) {
805         /* the domains were identical */
806
807         if(clist->spath && co->spath) {
808           if(Curl_raw_equal(clist->spath, co->spath)) {
809             replace_old = TRUE;
810           }
811           else
812             replace_old = FALSE;
813         }
814         else if(!clist->spath && !co->spath)
815           replace_old = TRUE;
816         else
817           replace_old = FALSE;
818
819       }
820
821       if(replace_old && !co->livecookie && clist->livecookie) {
822         /* Both cookies matched fine, except that the already present
823            cookie is "live", which means it was set from a header, while
824            the new one isn't "live" and thus only read from a file. We let
825            live cookies stay alive */
826
827         /* Free the newcomer and get out of here! */
828         freecookie(co);
829         return NULL;
830       }
831
832       if(replace_old) {
833         co->next = clist->next; /* get the next-pointer first */
834
835         /* then free all the old pointers */
836         free(clist->name);
837         if(clist->value)
838           free(clist->value);
839         if(clist->domain)
840           free(clist->domain);
841         if(clist->path)
842           free(clist->path);
843         if(clist->spath)
844           free(clist->spath);
845         if(clist->expirestr)
846           free(clist->expirestr);
847
848         if(clist->version)
849           free(clist->version);
850         if(clist->maxage)
851           free(clist->maxage);
852
853         *clist = *co;  /* then store all the new data */
854
855         free(co);   /* free the newly alloced memory */
856         co = clist; /* point to the previous struct instead */
857
858         /* We have replaced a cookie, now skip the rest of the list but
859            make sure the 'lastc' pointer is properly set */
860         do {
861           lastc = clist;
862           clist = clist->next;
863         } while(clist);
864         break;
865       }
866     }
867     lastc = clist;
868     clist = clist->next;
869   }
870
871   if(c->running)
872     /* Only show this when NOT reading the cookies from a file */
873     infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, "
874           "expire %" CURL_FORMAT_CURL_OFF_T "\n",
875           replace_old?"Replaced":"Added", co->name, co->value,
876           co->domain, co->path, co->expires);
877
878   if(!replace_old) {
879     /* then make the last item point on this new one */
880     if(lastc)
881       lastc->next = co;
882     else
883       c->cookies = co;
884     c->numcookies++; /* one more cookie in the jar */
885   }
886
887   return co;
888 }
889
890 /*****************************************************************************
891  *
892  * Curl_cookie_init()
893  *
894  * Inits a cookie struct to read data from a local file. This is always
895  * called before any cookies are set. File may be NULL.
896  *
897  * If 'newsession' is TRUE, discard all "session cookies" on read from file.
898  *
899  * Returns NULL on out of memory. Invalid cookies are ignored.
900  ****************************************************************************/
901 struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
902                                     const char *file,
903                                     struct CookieInfo *inc,
904                                     bool newsession)
905 {
906   struct CookieInfo *c;
907   FILE *fp = NULL;
908   bool fromfile=TRUE;
909   char *line = NULL;
910
911   if(NULL == inc) {
912     /* we didn't get a struct, create one */
913     c = calloc(1, sizeof(struct CookieInfo));
914     if(!c)
915       return NULL; /* failed to get memory */
916     c->filename = strdup(file?file:"none"); /* copy the name just in case */
917     if(!c->filename)
918       goto fail; /* failed to get memory */
919   }
920   else {
921     /* we got an already existing one, use that */
922     c = inc;
923   }
924   c->running = FALSE; /* this is not running, this is init */
925
926   if(file && strequal(file, "-")) {
927     fp = stdin;
928     fromfile=FALSE;
929   }
930   else if(file && !*file) {
931     /* points to a "" string */
932     fp = NULL;
933   }
934   else
935     fp = file?fopen(file, "r"):NULL;
936
937   c->newsession = newsession; /* new session? */
938
939   if(fp) {
940     char *lineptr;
941     bool headerline;
942
943     line = malloc(MAX_COOKIE_LINE);
944     if(!line)
945       goto fail;
946     while(fgets(line, MAX_COOKIE_LINE, fp)) {
947       if(checkprefix("Set-Cookie:", line)) {
948         /* This is a cookie line, get it! */
949         lineptr=&line[11];
950         headerline=TRUE;
951       }
952       else {
953         lineptr=line;
954         headerline=FALSE;
955       }
956       while(*lineptr && ISBLANK(*lineptr))
957         lineptr++;
958
959       Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
960     }
961     free(line); /* free the line buffer */
962
963     if(fromfile)
964       fclose(fp);
965   }
966
967   c->running = TRUE;          /* now, we're running */
968
969   return c;
970
971 fail:
972   Curl_safefree(line);
973   if(!inc)
974     /* Only clean up if we allocated it here, as the original could still be in
975      * use by a share handle */
976     Curl_cookie_cleanup(c);
977   if(fromfile && fp)
978     fclose(fp);
979   return NULL; /* out of memory */
980 }
981
982 /* sort this so that the longest path gets before the shorter path */
983 static int cookie_sort(const void *p1, const void *p2)
984 {
985   struct Cookie *c1 = *(struct Cookie **)p1;
986   struct Cookie *c2 = *(struct Cookie **)p2;
987   size_t l1, l2;
988
989   /* 1 - compare cookie path lengths */
990   l1 = c1->path ? strlen(c1->path) : 0;
991   l2 = c2->path ? strlen(c2->path) : 0;
992
993   if(l1 != l2)
994     return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
995
996   /* 2 - compare cookie domain lengths */
997   l1 = c1->domain ? strlen(c1->domain) : 0;
998   l2 = c2->domain ? strlen(c2->domain) : 0;
999
1000   if(l1 != l2)
1001     return (l2 > l1) ? 1 : -1 ;  /* avoid size_t <=> int conversions */
1002
1003   /* 3 - compare cookie names */
1004   if(c1->name && c2->name)
1005     return strcmp(c1->name, c2->name);
1006
1007   /* sorry, can't be more deterministic */
1008   return 0;
1009 }
1010
1011 /*****************************************************************************
1012  *
1013  * Curl_cookie_getlist()
1014  *
1015  * For a given host and path, return a linked list of cookies that the
1016  * client should send to the server if used now. The secure boolean informs
1017  * the cookie if a secure connection is achieved or not.
1018  *
1019  * It shall only return cookies that haven't expired.
1020  *
1021  ****************************************************************************/
1022
1023 struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
1024                                    const char *host, const char *path,
1025                                    bool secure)
1026 {
1027   struct Cookie *newco;
1028   struct Cookie *co;
1029   time_t now = time(NULL);
1030   struct Cookie *mainco=NULL;
1031   size_t matches = 0;
1032   bool is_ip;
1033
1034   if(!c || !c->cookies)
1035     return NULL; /* no cookie struct or no cookies in the struct */
1036
1037   /* at first, remove expired cookies */
1038   remove_expired(c);
1039
1040   /* check if host is an IP(v4|v6) address */
1041   is_ip = isip(host);
1042
1043   co = c->cookies;
1044
1045   while(co) {
1046     /* only process this cookie if it is not expired or had no expire
1047        date AND that if the cookie requires we're secure we must only
1048        continue if we are! */
1049     if((!co->expires || (co->expires > now)) &&
1050        (co->secure?secure:TRUE)) {
1051
1052       /* now check if the domain is correct */
1053       if(!co->domain ||
1054          (co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
1055          ((!co->tailmatch || is_ip) && Curl_raw_equal(host, co->domain)) ) {
1056         /* the right part of the host matches the domain stuff in the
1057            cookie data */
1058
1059         /* now check the left part of the path with the cookies path
1060            requirement */
1061         if(!co->spath || pathmatch(co->spath, path) ) {
1062
1063           /* and now, we know this is a match and we should create an
1064              entry for the return-linked-list */
1065
1066           newco = malloc(sizeof(struct Cookie));
1067           if(newco) {
1068             /* first, copy the whole source cookie: */
1069             memcpy(newco, co, sizeof(struct Cookie));
1070
1071             /* then modify our next */
1072             newco->next = mainco;
1073
1074             /* point the main to us */
1075             mainco = newco;
1076
1077             matches++;
1078           }
1079           else {
1080             fail:
1081             /* failure, clear up the allocated chain and return NULL */
1082             while(mainco) {
1083               co = mainco->next;
1084               free(mainco);
1085               mainco = co;
1086             }
1087
1088             return NULL;
1089           }
1090         }
1091       }
1092     }
1093     co = co->next;
1094   }
1095
1096   if(matches) {
1097     /* Now we need to make sure that if there is a name appearing more than
1098        once, the longest specified path version comes first. To make this
1099        the swiftest way, we just sort them all based on path length. */
1100     struct Cookie **array;
1101     size_t i;
1102
1103     /* alloc an array and store all cookie pointers */
1104     array = malloc(sizeof(struct Cookie *) * matches);
1105     if(!array)
1106       goto fail;
1107
1108     co = mainco;
1109
1110     for(i=0; co; co = co->next)
1111       array[i++] = co;
1112
1113     /* now sort the cookie pointers in path length order */
1114     qsort(array, matches, sizeof(struct Cookie *), cookie_sort);
1115
1116     /* remake the linked list order according to the new order */
1117
1118     mainco = array[0]; /* start here */
1119     for(i=0; i<matches-1; i++)
1120       array[i]->next = array[i+1];
1121     array[matches-1]->next = NULL; /* terminate the list */
1122
1123     free(array); /* remove the temporary data again */
1124   }
1125
1126   return mainco; /* return the new list */
1127 }
1128
1129 /*****************************************************************************
1130  *
1131  * Curl_cookie_clearall()
1132  *
1133  * Clear all existing cookies and reset the counter.
1134  *
1135  ****************************************************************************/
1136 void Curl_cookie_clearall(struct CookieInfo *cookies)
1137 {
1138   if(cookies) {
1139     Curl_cookie_freelist(cookies->cookies, TRUE);
1140     cookies->cookies = NULL;
1141     cookies->numcookies = 0;
1142   }
1143 }
1144
1145 /*****************************************************************************
1146  *
1147  * Curl_cookie_freelist()
1148  *
1149  * Free a list of cookies previously returned by Curl_cookie_getlist();
1150  *
1151  * The 'cookiestoo' argument tells this function whether to just free the
1152  * list or actually also free all cookies within the list as well.
1153  *
1154  ****************************************************************************/
1155
1156 void Curl_cookie_freelist(struct Cookie *co, bool cookiestoo)
1157 {
1158   struct Cookie *next;
1159   while(co) {
1160     next = co->next;
1161     if(cookiestoo)
1162       freecookie(co);
1163     else
1164       free(co); /* we only free the struct since the "members" are all just
1165                    pointed out in the main cookie list! */
1166     co = next;
1167   }
1168 }
1169
1170
1171 /*****************************************************************************
1172  *
1173  * Curl_cookie_clearsess()
1174  *
1175  * Free all session cookies in the cookies list.
1176  *
1177  ****************************************************************************/
1178 void Curl_cookie_clearsess(struct CookieInfo *cookies)
1179 {
1180   struct Cookie *first, *curr, *next, *prev = NULL;
1181
1182   if(!cookies || !cookies->cookies)
1183     return;
1184
1185   first = curr = prev = cookies->cookies;
1186
1187   for(; curr; curr = next) {
1188     next = curr->next;
1189     if(!curr->expires) {
1190       if(first == curr)
1191         first = next;
1192
1193       if(prev == curr)
1194         prev = next;
1195       else
1196         prev->next = next;
1197
1198       freecookie(curr);
1199       cookies->numcookies--;
1200     }
1201     else
1202       prev = curr;
1203   }
1204
1205   cookies->cookies = first;
1206 }
1207
1208
1209 /*****************************************************************************
1210  *
1211  * Curl_cookie_cleanup()
1212  *
1213  * Free a "cookie object" previous created with Curl_cookie_init().
1214  *
1215  ****************************************************************************/
1216 void Curl_cookie_cleanup(struct CookieInfo *c)
1217 {
1218   if(c) {
1219     if(c->filename)
1220       free(c->filename);
1221     Curl_cookie_freelist(c->cookies, TRUE);
1222     free(c); /* free the base struct as well */
1223   }
1224 }
1225
1226 /* get_netscape_format()
1227  *
1228  * Formats a string for Netscape output file, w/o a newline at the end.
1229  *
1230  * Function returns a char * to a formatted line. Has to be free()d
1231 */
1232 static char *get_netscape_format(const struct Cookie *co)
1233 {
1234   return aprintf(
1235     "%s"     /* httponly preamble */
1236     "%s%s\t" /* domain */
1237     "%s\t"   /* tailmatch */
1238     "%s\t"   /* path */
1239     "%s\t"   /* secure */
1240     "%" CURL_FORMAT_CURL_OFF_T "\t"   /* expires */
1241     "%s\t"   /* name */
1242     "%s",    /* value */
1243     co->httponly?"#HttpOnly_":"",
1244     /* Make sure all domains are prefixed with a dot if they allow
1245        tailmatching. This is Mozilla-style. */
1246     (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
1247     co->domain?co->domain:"unknown",
1248     co->tailmatch?"TRUE":"FALSE",
1249     co->path?co->path:"/",
1250     co->secure?"TRUE":"FALSE",
1251     co->expires,
1252     co->name,
1253     co->value?co->value:"");
1254 }
1255
1256 /*
1257  * cookie_output()
1258  *
1259  * Writes all internally known cookies to the specified file. Specify
1260  * "-" as file name to write to stdout.
1261  *
1262  * The function returns non-zero on write failure.
1263  */
1264 static int cookie_output(struct CookieInfo *c, const char *dumphere)
1265 {
1266   struct Cookie *co;
1267   FILE *out;
1268   bool use_stdout=FALSE;
1269
1270   if((NULL == c) || (0 == c->numcookies))
1271     /* If there are no known cookies, we don't write or even create any
1272        destination file */
1273     return 0;
1274
1275   /* at first, remove expired cookies */
1276   remove_expired(c);
1277
1278   if(strequal("-", dumphere)) {
1279     /* use stdout */
1280     out = stdout;
1281     use_stdout=TRUE;
1282   }
1283   else {
1284     out = fopen(dumphere, "w");
1285     if(!out)
1286       return 1; /* failure */
1287   }
1288
1289   if(c) {
1290     char *format_ptr;
1291
1292     fputs("# Netscape HTTP Cookie File\n"
1293           "# http://curl.haxx.se/docs/http-cookies.html\n"
1294           "# This file was generated by libcurl! Edit at your own risk.\n\n",
1295           out);
1296     co = c->cookies;
1297
1298     while(co) {
1299       format_ptr = get_netscape_format(co);
1300       if(format_ptr == NULL) {
1301         fprintf(out, "#\n# Fatal libcurl error\n");
1302         if(!use_stdout)
1303           fclose(out);
1304         return 1;
1305       }
1306       fprintf(out, "%s\n", format_ptr);
1307       free(format_ptr);
1308       co=co->next;
1309     }
1310   }
1311
1312   if(!use_stdout)
1313     fclose(out);
1314
1315   return 0;
1316 }
1317
1318 struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
1319 {
1320   struct curl_slist *list = NULL;
1321   struct curl_slist *beg;
1322   struct Cookie *c;
1323   char *line;
1324
1325   if((data->cookies == NULL) ||
1326       (data->cookies->numcookies == 0))
1327     return NULL;
1328
1329   c = data->cookies->cookies;
1330
1331   while(c) {
1332     /* fill the list with _all_ the cookies we know */
1333     line = get_netscape_format(c);
1334     if(!line) {
1335       curl_slist_free_all(list);
1336       return NULL;
1337     }
1338     beg = Curl_slist_append_nodup(list, line);
1339     if(!beg) {
1340       free(line);
1341       curl_slist_free_all(list);
1342       return NULL;
1343     }
1344     list = beg;
1345     c = c->next;
1346   }
1347
1348   return list;
1349 }
1350
1351 void Curl_flush_cookies(struct SessionHandle *data, int cleanup)
1352 {
1353   if(data->set.str[STRING_COOKIEJAR]) {
1354     if(data->change.cookielist) {
1355       /* If there is a list of cookie files to read, do it first so that
1356          we have all the told files read before we write the new jar.
1357          Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */
1358       Curl_cookie_loadfiles(data);
1359     }
1360
1361     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1362
1363     /* if we have a destination file for all the cookies to get dumped to */
1364     if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
1365       infof(data, "WARNING: failed to save cookies in %s\n",
1366             data->set.str[STRING_COOKIEJAR]);
1367   }
1368   else {
1369     if(cleanup && data->change.cookielist) {
1370       /* since nothing is written, we can just free the list of cookie file
1371          names */
1372       curl_slist_free_all(data->change.cookielist); /* clean up list */
1373       data->change.cookielist = NULL;
1374     }
1375     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1376   }
1377
1378   if(cleanup && (!data->share || (data->cookies != data->share->cookies))) {
1379     Curl_cookie_cleanup(data->cookies);
1380   }
1381   Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1382 }
1383
1384 #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */