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