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