Imported Upstream version 7.59.0
[platform/upstream/curl.git] / lib / cookie.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2018, 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(!pv) {
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   struct Cookie *co;
379   struct Cookie *lastc = NULL;
380   time_t now = time(NULL);
381   bool replace_old = FALSE;
382   bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
383
384 #ifdef USE_LIBPSL
385   const psl_ctx_t *psl;
386 #endif
387
388 #ifdef CURL_DISABLE_VERBOSE_STRINGS
389   (void)data;
390 #endif
391
392   /* First, alloc and init a new struct for it */
393   co = calloc(1, sizeof(struct Cookie));
394   if(!co)
395     return NULL; /* bail out if we're this low on memory */
396
397   if(httpheader) {
398     /* This line was read off a HTTP-header */
399     char name[MAX_NAME];
400     char what[MAX_NAME];
401     const char *ptr;
402     const char *semiptr;
403
404     size_t linelength = strlen(lineptr);
405     if(linelength > MAX_COOKIE_LINE) {
406       /* discard overly long lines at once */
407       free(co);
408       return NULL;
409     }
410
411     semiptr = strchr(lineptr, ';'); /* first, find a semicolon */
412
413     while(*lineptr && ISBLANK(*lineptr))
414       lineptr++;
415
416     ptr = lineptr;
417     do {
418       /* we have a <what>=<this> pair or a stand-alone word here */
419       name[0] = what[0] = 0; /* init the buffers */
420       if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%"
421                      MAX_NAME_TXT "[^;\r\n]",
422                      name, what)) {
423         /* Use strstore() below to properly deal with received cookie
424            headers that have the same string property set more than once,
425            and then we use the last one. */
426         const char *whatptr;
427         bool done = FALSE;
428         bool sep;
429         size_t len = strlen(what);
430         size_t nlen = strlen(name);
431         const char *endofn = &ptr[ nlen ];
432
433         if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
434            ((nlen + len) > MAX_NAME)) {
435           /* too long individual name or contents, or too long combination of
436              name + contents. Chrome and Firefox support 4095 or 4096 bytes
437              combo. */
438           freecookie(co);
439           infof(data, "oversized cookie dropped, name/val %d + %d bytes\n",
440                 nlen, len);
441           return NULL;
442         }
443
444         /* name ends with a '=' ? */
445         sep = (*endofn == '=')?TRUE:FALSE;
446
447         if(nlen) {
448           endofn--; /* move to the last character */
449           if(ISBLANK(*endofn)) {
450             /* skip trailing spaces in name */
451             while(*endofn && ISBLANK(*endofn) && nlen) {
452               endofn--;
453               nlen--;
454             }
455             name[nlen] = 0; /* new end of name */
456           }
457         }
458
459         /* Strip off trailing whitespace from the 'what' */
460         while(len && ISBLANK(what[len-1])) {
461           what[len-1] = 0;
462           len--;
463         }
464
465         /* Skip leading whitespace from the 'what' */
466         whatptr = what;
467         while(*whatptr && ISBLANK(*whatptr))
468           whatptr++;
469
470         if(!co->name && sep) {
471           /* The very first name/value pair is the actual cookie name */
472           co->name = strdup(name);
473           co->value = strdup(whatptr);
474           if(!co->name || !co->value) {
475             badcookie = TRUE;
476             break;
477           }
478         }
479         else if(!len) {
480           /* this was a "<name>=" with no content, and we must allow
481              'secure' and 'httponly' specified this weirdly */
482           done = TRUE;
483           if(strcasecompare("secure", name))
484             co->secure = TRUE;
485           else if(strcasecompare("httponly", name))
486             co->httponly = TRUE;
487           else if(sep)
488             /* there was a '=' so we're not done parsing this field */
489             done = FALSE;
490         }
491         if(done)
492           ;
493         else if(strcasecompare("path", name)) {
494           strstore(&co->path, whatptr);
495           if(!co->path) {
496             badcookie = TRUE; /* out of memory bad */
497             break;
498           }
499           free(co->spath); /* if this is set again */
500           co->spath = sanitize_cookie_path(co->path);
501           if(!co->spath) {
502             badcookie = TRUE; /* out of memory bad */
503             break;
504           }
505         }
506         else if(strcasecompare("domain", name)) {
507           bool is_ip;
508
509           /* Now, we make sure that our host is within the given domain,
510              or the given domain is not valid and thus cannot be set. */
511
512           if('.' == whatptr[0])
513             whatptr++; /* ignore preceding dot */
514
515 #ifndef USE_LIBPSL
516           /*
517            * Without PSL we don't know when the incoming cookie is set on a
518            * TLD or otherwise "protected" suffix. To reduce risk, we require a
519            * dot OR the exact host name being "localhost".
520            */
521           {
522             const char *dotp;
523             /* check for more dots */
524             dotp = strchr(whatptr, '.');
525             if(!dotp && !strcasecompare("localhost", whatptr))
526               domain = ":";
527           }
528 #endif
529
530           is_ip = isip(domain ? domain : whatptr);
531
532           if(!domain
533              || (is_ip && !strcmp(whatptr, domain))
534              || (!is_ip && tailmatch(whatptr, domain))) {
535             strstore(&co->domain, whatptr);
536             if(!co->domain) {
537               badcookie = TRUE;
538               break;
539             }
540             if(!is_ip)
541               co->tailmatch = TRUE; /* we always do that if the domain name was
542                                        given */
543           }
544           else {
545             /* we did not get a tailmatch and then the attempted set domain
546                is not a domain to which the current host belongs. Mark as
547                bad. */
548             badcookie = TRUE;
549             infof(data, "skipped cookie with bad tailmatch domain: %s\n",
550                   whatptr);
551           }
552         }
553         else if(strcasecompare("version", name)) {
554           strstore(&co->version, whatptr);
555           if(!co->version) {
556             badcookie = TRUE;
557             break;
558           }
559         }
560         else if(strcasecompare("max-age", name)) {
561           /* Defined in RFC2109:
562
563              Optional.  The Max-Age attribute defines the lifetime of the
564              cookie, in seconds.  The delta-seconds value is a decimal non-
565              negative integer.  After delta-seconds seconds elapse, the
566              client should discard the cookie.  A value of zero means the
567              cookie should be discarded immediately.
568
569           */
570           strstore(&co->maxage, whatptr);
571           if(!co->maxage) {
572             badcookie = TRUE;
573             break;
574           }
575         }
576         else if(strcasecompare("expires", name)) {
577           strstore(&co->expirestr, whatptr);
578           if(!co->expirestr) {
579             badcookie = TRUE;
580             break;
581           }
582         }
583         /*
584           else this is the second (or more) name we don't know
585           about! */
586       }
587       else {
588         /* this is an "illegal" <what>=<this> pair */
589       }
590
591       if(!semiptr || !*semiptr) {
592         /* we already know there are no more cookies */
593         semiptr = NULL;
594         continue;
595       }
596
597       ptr = semiptr + 1;
598       while(*ptr && ISBLANK(*ptr))
599         ptr++;
600       semiptr = strchr(ptr, ';'); /* now, find the next semicolon */
601
602       if(!semiptr && *ptr)
603         /* There are no more semicolons, but there's a final name=value pair
604            coming up */
605         semiptr = strchr(ptr, '\0');
606     } while(semiptr);
607
608     if(co->maxage) {
609       CURLofft offt;
610       offt = curlx_strtoofft((*co->maxage == '\"')?
611                              &co->maxage[1]:&co->maxage[0], NULL, 10,
612                              &co->expires);
613       if(offt == CURL_OFFT_FLOW)
614         /* overflow, used max value */
615         co->expires = CURL_OFF_T_MAX;
616       else if(!offt) {
617         if(CURL_OFF_T_MAX - now < co->expires)
618           /* would overflow */
619           co->expires = CURL_OFF_T_MAX;
620         else
621           co->expires += now;
622       }
623     }
624     else if(co->expirestr) {
625       /* Note that if the date couldn't get parsed for whatever reason,
626          the cookie will be treated as a session cookie */
627       co->expires = curl_getdate(co->expirestr, NULL);
628
629       /* Session cookies have expires set to 0 so if we get that back
630          from the date parser let's add a second to make it a
631          non-session cookie */
632       if(co->expires == 0)
633         co->expires = 1;
634       else if(co->expires < 0)
635         co->expires = 0;
636     }
637
638     if(!badcookie && !co->domain) {
639       if(domain) {
640         /* no domain was given in the header line, set the default */
641         co->domain = strdup(domain);
642         if(!co->domain)
643           badcookie = TRUE;
644       }
645     }
646
647     if(!badcookie && !co->path && path) {
648       /* No path was given in the header line, set the default.
649          Note that the passed-in path to this function MAY have a '?' and
650          following part that MUST not be stored as part of the path. */
651       char *queryp = strchr(path, '?');
652
653       /* queryp is where the interesting part of the path ends, so now we
654          want to the find the last */
655       char *endslash;
656       if(!queryp)
657         endslash = strrchr(path, '/');
658       else
659         endslash = memrchr(path, '/', (size_t)(queryp - path));
660       if(endslash) {
661         size_t pathlen = (size_t)(endslash-path + 1); /* include end slash */
662         co->path = malloc(pathlen + 1); /* one extra for the zero byte */
663         if(co->path) {
664           memcpy(co->path, path, pathlen);
665           co->path[pathlen] = 0; /* zero terminate */
666           co->spath = sanitize_cookie_path(co->path);
667           if(!co->spath)
668             badcookie = TRUE; /* out of memory bad */
669         }
670         else
671           badcookie = TRUE;
672       }
673     }
674
675     if(badcookie || !co->name) {
676       /* we didn't get a cookie name or a bad one,
677          this is an illegal line, bail out */
678       freecookie(co);
679       return NULL;
680     }
681
682   }
683   else {
684     /* This line is NOT a HTTP header style line, we do offer support for
685        reading the odd netscape cookies-file format here */
686     char *ptr;
687     char *firstptr;
688     char *tok_buf = NULL;
689     int fields;
690
691     /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies
692        marked with httpOnly after the domain name are not accessible
693        from javascripts, but since curl does not operate at javascript
694        level, we include them anyway. In Firefox's cookie files, these
695        lines are preceded with #HttpOnly_ and then everything is
696        as usual, so we skip 10 characters of the line..
697     */
698     if(strncmp(lineptr, "#HttpOnly_", 10) == 0) {
699       lineptr += 10;
700       co->httponly = TRUE;
701     }
702
703     if(lineptr[0]=='#') {
704       /* don't even try the comments */
705       free(co);
706       return NULL;
707     }
708     /* strip off the possible end-of-line characters */
709     ptr = strchr(lineptr, '\r');
710     if(ptr)
711       *ptr = 0; /* clear it */
712     ptr = strchr(lineptr, '\n');
713     if(ptr)
714       *ptr = 0; /* clear it */
715
716     firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
717
718     /* Now loop through the fields and init the struct we already have
719        allocated */
720     for(ptr = firstptr, fields = 0; ptr && !badcookie;
721         ptr = strtok_r(NULL, "\t", &tok_buf), fields++) {
722       switch(fields) {
723       case 0:
724         if(ptr[0]=='.') /* skip preceding dots */
725           ptr++;
726         co->domain = strdup(ptr);
727         if(!co->domain)
728           badcookie = TRUE;
729         break;
730       case 1:
731         /* This field got its explanation on the 23rd of May 2001 by
732            Andrés García:
733
734            flag: A TRUE/FALSE value indicating if all machines within a given
735            domain can access the variable. This value is set automatically by
736            the browser, depending on the value you set for the domain.
737
738            As far as I can see, it is set to true when the cookie says
739            .domain.com and to false when the domain is complete www.domain.com
740         */
741         co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
742         break;
743       case 2:
744         /* It turns out, that sometimes the file format allows the path
745            field to remain not filled in, we try to detect this and work
746            around it! Andrés García made us aware of this... */
747         if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
748           /* only if the path doesn't look like a boolean option! */
749           co->path = strdup(ptr);
750           if(!co->path)
751             badcookie = TRUE;
752           else {
753             co->spath = sanitize_cookie_path(co->path);
754             if(!co->spath) {
755               badcookie = TRUE; /* out of memory bad */
756             }
757           }
758           break;
759         }
760         /* this doesn't look like a path, make one up! */
761         co->path = strdup("/");
762         if(!co->path)
763           badcookie = TRUE;
764         co->spath = strdup("/");
765         if(!co->spath)
766           badcookie = TRUE;
767         fields++; /* add a field and fall down to secure */
768         /* FALLTHROUGH */
769       case 3:
770         co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
771         break;
772       case 4:
773         if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
774           badcookie = TRUE;
775         break;
776       case 5:
777         co->name = strdup(ptr);
778         if(!co->name)
779           badcookie = TRUE;
780         break;
781       case 6:
782         co->value = strdup(ptr);
783         if(!co->value)
784           badcookie = TRUE;
785         break;
786       }
787     }
788     if(6 == fields) {
789       /* we got a cookie with blank contents, fix it */
790       co->value = strdup("");
791       if(!co->value)
792         badcookie = TRUE;
793       else
794         fields++;
795     }
796
797     if(!badcookie && (7 != fields))
798       /* we did not find the sufficient number of fields */
799       badcookie = TRUE;
800
801     if(badcookie) {
802       freecookie(co);
803       return NULL;
804     }
805
806   }
807
808   if(!c->running &&    /* read from a file */
809      c->newsession &&  /* clean session cookies */
810      !co->expires) {   /* this is a session cookie since it doesn't expire! */
811     freecookie(co);
812     return NULL;
813   }
814
815   co->livecookie = c->running;
816
817   /* now, we have parsed the incoming line, we must now check if this
818      superceeds an already existing cookie, which it may if the previous have
819      the same domain and path as this */
820
821   /* at first, remove expired cookies */
822   remove_expired(c);
823
824 #ifdef USE_LIBPSL
825   /* Check if the domain is a Public Suffix and if yes, ignore the cookie.
826      This needs a libpsl compiled with builtin data. */
827   if(domain && co->domain && !isip(co->domain)) {
828     psl = psl_builtin();
829     if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
830       infof(data,
831             "cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n",
832             co->name, domain, co->domain);
833       freecookie(co);
834       return NULL;
835     }
836   }
837 #endif
838
839   clist = c->cookies;
840   replace_old = FALSE;
841   while(clist) {
842     if(strcasecompare(clist->name, co->name)) {
843       /* the names are identical */
844
845       if(clist->domain && co->domain) {
846         if(strcasecompare(clist->domain, co->domain) &&
847           (clist->tailmatch == co->tailmatch))
848           /* The domains are identical */
849           replace_old = TRUE;
850       }
851       else if(!clist->domain && !co->domain)
852         replace_old = TRUE;
853
854       if(replace_old) {
855         /* the domains were identical */
856
857         if(clist->spath && co->spath) {
858           if(strcasecompare(clist->spath, co->spath)) {
859             replace_old = TRUE;
860           }
861           else
862             replace_old = FALSE;
863         }
864         else if(!clist->spath && !co->spath)
865           replace_old = TRUE;
866         else
867           replace_old = FALSE;
868
869       }
870
871       if(replace_old && !co->livecookie && clist->livecookie) {
872         /* Both cookies matched fine, except that the already present
873            cookie is "live", which means it was set from a header, while
874            the new one isn't "live" and thus only read from a file. We let
875            live cookies stay alive */
876
877         /* Free the newcomer and get out of here! */
878         freecookie(co);
879         return NULL;
880       }
881
882       if(replace_old) {
883         co->next = clist->next; /* get the next-pointer first */
884
885         /* then free all the old pointers */
886         free(clist->name);
887         free(clist->value);
888         free(clist->domain);
889         free(clist->path);
890         free(clist->spath);
891         free(clist->expirestr);
892         free(clist->version);
893         free(clist->maxage);
894
895         *clist = *co;  /* then store all the new data */
896
897         free(co);   /* free the newly alloced memory */
898         co = clist; /* point to the previous struct instead */
899
900         /* We have replaced a cookie, now skip the rest of the list but
901            make sure the 'lastc' pointer is properly set */
902         do {
903           lastc = clist;
904           clist = clist->next;
905         } while(clist);
906         break;
907       }
908     }
909     lastc = clist;
910     clist = clist->next;
911   }
912
913   if(c->running)
914     /* Only show this when NOT reading the cookies from a file */
915     infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, "
916           "expire %" CURL_FORMAT_CURL_OFF_T "\n",
917           replace_old?"Replaced":"Added", co->name, co->value,
918           co->domain, co->path, co->expires);
919
920   if(!replace_old) {
921     /* then make the last item point on this new one */
922     if(lastc)
923       lastc->next = co;
924     else
925       c->cookies = co;
926     c->numcookies++; /* one more cookie in the jar */
927   }
928
929   return co;
930 }
931
932 /*
933  * get_line() makes sure to only return complete whole lines that fit in 'len'
934  * bytes and end with a newline.
935  */
936 static char *get_line(char *buf, int len, FILE *input)
937 {
938   bool partial = FALSE;
939   while(1) {
940     char *b = fgets(buf, len, input);
941     if(b) {
942       size_t rlen = strlen(b);
943       if(rlen && (b[rlen-1] == '\n')) {
944         if(partial) {
945           partial = FALSE;
946           continue;
947         }
948         return b;
949       }
950       /* read a partial, discard the next piece that ends with newline */
951       partial = TRUE;
952     }
953     else
954       break;
955   }
956   return NULL;
957 }
958
959
960 /*****************************************************************************
961  *
962  * Curl_cookie_init()
963  *
964  * Inits a cookie struct to read data from a local file. This is always
965  * called before any cookies are set. File may be NULL.
966  *
967  * If 'newsession' is TRUE, discard all "session cookies" on read from file.
968  *
969  * Returns NULL on out of memory. Invalid cookies are ignored.
970  ****************************************************************************/
971 struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
972                                     const char *file,
973                                     struct CookieInfo *inc,
974                                     bool newsession)
975 {
976   struct CookieInfo *c;
977   FILE *fp = NULL;
978   bool fromfile = TRUE;
979   char *line = NULL;
980
981   if(NULL == inc) {
982     /* we didn't get a struct, create one */
983     c = calloc(1, sizeof(struct CookieInfo));
984     if(!c)
985       return NULL; /* failed to get memory */
986     c->filename = strdup(file?file:"none"); /* copy the name just in case */
987     if(!c->filename)
988       goto fail; /* failed to get memory */
989   }
990   else {
991     /* we got an already existing one, use that */
992     c = inc;
993   }
994   c->running = FALSE; /* this is not running, this is init */
995
996   if(file && !strcmp(file, "-")) {
997     fp = stdin;
998     fromfile = FALSE;
999   }
1000   else if(file && !*file) {
1001     /* points to a "" string */
1002     fp = NULL;
1003   }
1004   else
1005     fp = file?fopen(file, FOPEN_READTEXT):NULL;
1006
1007   c->newsession = newsession; /* new session? */
1008
1009   if(fp) {
1010     char *lineptr;
1011     bool headerline;
1012
1013     line = malloc(MAX_COOKIE_LINE);
1014     if(!line)
1015       goto fail;
1016     while(get_line(line, MAX_COOKIE_LINE, fp)) {
1017       if(checkprefix("Set-Cookie:", line)) {
1018         /* This is a cookie line, get it! */
1019         lineptr = &line[11];
1020         headerline = TRUE;
1021       }
1022       else {
1023         lineptr = line;
1024         headerline = FALSE;
1025       }
1026       while(*lineptr && ISBLANK(*lineptr))
1027         lineptr++;
1028
1029       Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
1030     }
1031     free(line); /* free the line buffer */
1032
1033     if(fromfile)
1034       fclose(fp);
1035   }
1036
1037   c->running = TRUE;          /* now, we're running */
1038
1039   return c;
1040
1041 fail:
1042   free(line);
1043   if(!inc)
1044     /* Only clean up if we allocated it here, as the original could still be in
1045      * use by a share handle */
1046     Curl_cookie_cleanup(c);
1047   if(fromfile && fp)
1048     fclose(fp);
1049   return NULL; /* out of memory */
1050 }
1051
1052 /* sort this so that the longest path gets before the shorter path */
1053 static int cookie_sort(const void *p1, const void *p2)
1054 {
1055   struct Cookie *c1 = *(struct Cookie **)p1;
1056   struct Cookie *c2 = *(struct Cookie **)p2;
1057   size_t l1, l2;
1058
1059   /* 1 - compare cookie path lengths */
1060   l1 = c1->path ? strlen(c1->path) : 0;
1061   l2 = c2->path ? strlen(c2->path) : 0;
1062
1063   if(l1 != l2)
1064     return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
1065
1066   /* 2 - compare cookie domain lengths */
1067   l1 = c1->domain ? strlen(c1->domain) : 0;
1068   l2 = c2->domain ? strlen(c2->domain) : 0;
1069
1070   if(l1 != l2)
1071     return (l2 > l1) ? 1 : -1 ;  /* avoid size_t <=> int conversions */
1072
1073   /* 3 - compare cookie names */
1074   if(c1->name && c2->name)
1075     return strcmp(c1->name, c2->name);
1076
1077   /* sorry, can't be more deterministic */
1078   return 0;
1079 }
1080
1081 #define CLONE(field)                     \
1082   do {                                   \
1083     if(src->field) {                     \
1084       d->field = strdup(src->field);     \
1085       if(!d->field)                      \
1086         goto fail;                       \
1087     }                                    \
1088   } while(0)
1089
1090 static struct Cookie *dup_cookie(struct Cookie *src)
1091 {
1092   struct Cookie *d = calloc(sizeof(struct Cookie), 1);
1093   if(d) {
1094     CLONE(expirestr);
1095     CLONE(domain);
1096     CLONE(path);
1097     CLONE(spath);
1098     CLONE(name);
1099     CLONE(value);
1100     CLONE(maxage);
1101     CLONE(version);
1102     d->expires = src->expires;
1103     d->tailmatch = src->tailmatch;
1104     d->secure = src->secure;
1105     d->livecookie = src->livecookie;
1106     d->httponly = src->httponly;
1107   }
1108   return d;
1109
1110   fail:
1111   freecookie(d);
1112   return NULL;
1113 }
1114
1115 /*****************************************************************************
1116  *
1117  * Curl_cookie_getlist()
1118  *
1119  * For a given host and path, return a linked list of cookies that the
1120  * client should send to the server if used now. The secure boolean informs
1121  * the cookie if a secure connection is achieved or not.
1122  *
1123  * It shall only return cookies that haven't expired.
1124  *
1125  ****************************************************************************/
1126
1127 struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
1128                                    const char *host, const char *path,
1129                                    bool secure)
1130 {
1131   struct Cookie *newco;
1132   struct Cookie *co;
1133   time_t now = time(NULL);
1134   struct Cookie *mainco = NULL;
1135   size_t matches = 0;
1136   bool is_ip;
1137
1138   if(!c || !c->cookies)
1139     return NULL; /* no cookie struct or no cookies in the struct */
1140
1141   /* at first, remove expired cookies */
1142   remove_expired(c);
1143
1144   /* check if host is an IP(v4|v6) address */
1145   is_ip = isip(host);
1146
1147   co = c->cookies;
1148
1149   while(co) {
1150     /* only process this cookie if it is not expired or had no expire
1151        date AND that if the cookie requires we're secure we must only
1152        continue if we are! */
1153     if((!co->expires || (co->expires > now)) &&
1154        (co->secure?secure:TRUE)) {
1155
1156       /* now check if the domain is correct */
1157       if(!co->domain ||
1158          (co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
1159          ((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) {
1160         /* the right part of the host matches the domain stuff in the
1161            cookie data */
1162
1163         /* now check the left part of the path with the cookies path
1164            requirement */
1165         if(!co->spath || pathmatch(co->spath, path) ) {
1166
1167           /* and now, we know this is a match and we should create an
1168              entry for the return-linked-list */
1169
1170           newco = dup_cookie(co);
1171           if(newco) {
1172             /* then modify our next */
1173             newco->next = mainco;
1174
1175             /* point the main to us */
1176             mainco = newco;
1177
1178             matches++;
1179           }
1180           else {
1181             fail:
1182             /* failure, clear up the allocated chain and return NULL */
1183             Curl_cookie_freelist(mainco);
1184             return NULL;
1185           }
1186         }
1187       }
1188     }
1189     co = co->next;
1190   }
1191
1192   if(matches) {
1193     /* Now we need to make sure that if there is a name appearing more than
1194        once, the longest specified path version comes first. To make this
1195        the swiftest way, we just sort them all based on path length. */
1196     struct Cookie **array;
1197     size_t i;
1198
1199     /* alloc an array and store all cookie pointers */
1200     array = malloc(sizeof(struct Cookie *) * matches);
1201     if(!array)
1202       goto fail;
1203
1204     co = mainco;
1205
1206     for(i = 0; co; co = co->next)
1207       array[i++] = co;
1208
1209     /* now sort the cookie pointers in path length order */
1210     qsort(array, matches, sizeof(struct Cookie *), cookie_sort);
1211
1212     /* remake the linked list order according to the new order */
1213
1214     mainco = array[0]; /* start here */
1215     for(i = 0; i<matches-1; i++)
1216       array[i]->next = array[i + 1];
1217     array[matches-1]->next = NULL; /* terminate the list */
1218
1219     free(array); /* remove the temporary data again */
1220   }
1221
1222   return mainco; /* return the new list */
1223 }
1224
1225 /*****************************************************************************
1226  *
1227  * Curl_cookie_clearall()
1228  *
1229  * Clear all existing cookies and reset the counter.
1230  *
1231  ****************************************************************************/
1232 void Curl_cookie_clearall(struct CookieInfo *cookies)
1233 {
1234   if(cookies) {
1235     Curl_cookie_freelist(cookies->cookies);
1236     cookies->cookies = NULL;
1237     cookies->numcookies = 0;
1238   }
1239 }
1240
1241 /*****************************************************************************
1242  *
1243  * Curl_cookie_freelist()
1244  *
1245  * Free a list of cookies previously returned by Curl_cookie_getlist();
1246  *
1247  ****************************************************************************/
1248
1249 void Curl_cookie_freelist(struct Cookie *co)
1250 {
1251   struct Cookie *next;
1252   while(co) {
1253     next = co->next;
1254     freecookie(co);
1255     co = next;
1256   }
1257 }
1258
1259
1260 /*****************************************************************************
1261  *
1262  * Curl_cookie_clearsess()
1263  *
1264  * Free all session cookies in the cookies list.
1265  *
1266  ****************************************************************************/
1267 void Curl_cookie_clearsess(struct CookieInfo *cookies)
1268 {
1269   struct Cookie *first, *curr, *next, *prev = NULL;
1270
1271   if(!cookies || !cookies->cookies)
1272     return;
1273
1274   first = curr = prev = cookies->cookies;
1275
1276   for(; curr; curr = next) {
1277     next = curr->next;
1278     if(!curr->expires) {
1279       if(first == curr)
1280         first = next;
1281
1282       if(prev == curr)
1283         prev = next;
1284       else
1285         prev->next = next;
1286
1287       freecookie(curr);
1288       cookies->numcookies--;
1289     }
1290     else
1291       prev = curr;
1292   }
1293
1294   cookies->cookies = first;
1295 }
1296
1297
1298 /*****************************************************************************
1299  *
1300  * Curl_cookie_cleanup()
1301  *
1302  * Free a "cookie object" previous created with Curl_cookie_init().
1303  *
1304  ****************************************************************************/
1305 void Curl_cookie_cleanup(struct CookieInfo *c)
1306 {
1307   if(c) {
1308     free(c->filename);
1309     Curl_cookie_freelist(c->cookies);
1310     free(c); /* free the base struct as well */
1311   }
1312 }
1313
1314 /* get_netscape_format()
1315  *
1316  * Formats a string for Netscape output file, w/o a newline at the end.
1317  *
1318  * Function returns a char * to a formatted line. Has to be free()d
1319 */
1320 static char *get_netscape_format(const struct Cookie *co)
1321 {
1322   return aprintf(
1323     "%s"     /* httponly preamble */
1324     "%s%s\t" /* domain */
1325     "%s\t"   /* tailmatch */
1326     "%s\t"   /* path */
1327     "%s\t"   /* secure */
1328     "%" CURL_FORMAT_CURL_OFF_T "\t"   /* expires */
1329     "%s\t"   /* name */
1330     "%s",    /* value */
1331     co->httponly?"#HttpOnly_":"",
1332     /* Make sure all domains are prefixed with a dot if they allow
1333        tailmatching. This is Mozilla-style. */
1334     (co->tailmatch && co->domain && co->domain[0] != '.')? ".":"",
1335     co->domain?co->domain:"unknown",
1336     co->tailmatch?"TRUE":"FALSE",
1337     co->path?co->path:"/",
1338     co->secure?"TRUE":"FALSE",
1339     co->expires,
1340     co->name,
1341     co->value?co->value:"");
1342 }
1343
1344 /*
1345  * cookie_output()
1346  *
1347  * Writes all internally known cookies to the specified file. Specify
1348  * "-" as file name to write to stdout.
1349  *
1350  * The function returns non-zero on write failure.
1351  */
1352 static int cookie_output(struct CookieInfo *c, const char *dumphere)
1353 {
1354   struct Cookie *co;
1355   FILE *out;
1356   bool use_stdout = FALSE;
1357   char *format_ptr;
1358
1359   if((NULL == c) || (0 == c->numcookies))
1360     /* If there are no known cookies, we don't write or even create any
1361        destination file */
1362     return 0;
1363
1364   /* at first, remove expired cookies */
1365   remove_expired(c);
1366
1367   if(!strcmp("-", dumphere)) {
1368     /* use stdout */
1369     out = stdout;
1370     use_stdout = TRUE;
1371   }
1372   else {
1373     out = fopen(dumphere, FOPEN_WRITETEXT);
1374     if(!out)
1375       return 1; /* failure */
1376   }
1377
1378   fputs("# Netscape HTTP Cookie File\n"
1379         "# https://curl.haxx.se/docs/http-cookies.html\n"
1380         "# This file was generated by libcurl! Edit at your own risk.\n\n",
1381         out);
1382
1383   for(co = c->cookies; co; co = co->next) {
1384     if(!co->domain)
1385       continue;
1386     format_ptr = get_netscape_format(co);
1387     if(format_ptr == NULL) {
1388       fprintf(out, "#\n# Fatal libcurl error\n");
1389       if(!use_stdout)
1390         fclose(out);
1391       return 1;
1392     }
1393     fprintf(out, "%s\n", format_ptr);
1394     free(format_ptr);
1395   }
1396
1397   if(!use_stdout)
1398     fclose(out);
1399
1400   return 0;
1401 }
1402
1403 static struct curl_slist *cookie_list(struct Curl_easy *data)
1404 {
1405   struct curl_slist *list = NULL;
1406   struct curl_slist *beg;
1407   struct Cookie *c;
1408   char *line;
1409
1410   if((data->cookies == NULL) ||
1411       (data->cookies->numcookies == 0))
1412     return NULL;
1413
1414   for(c = data->cookies->cookies; c; c = c->next) {
1415     if(!c->domain)
1416       continue;
1417     line = get_netscape_format(c);
1418     if(!line) {
1419       curl_slist_free_all(list);
1420       return NULL;
1421     }
1422     beg = Curl_slist_append_nodup(list, line);
1423     if(!beg) {
1424       free(line);
1425       curl_slist_free_all(list);
1426       return NULL;
1427     }
1428     list = beg;
1429   }
1430
1431   return list;
1432 }
1433
1434 struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
1435 {
1436   struct curl_slist *list;
1437   Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1438   list = cookie_list(data);
1439   Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1440   return list;
1441 }
1442
1443 void Curl_flush_cookies(struct Curl_easy *data, int cleanup)
1444 {
1445   if(data->set.str[STRING_COOKIEJAR]) {
1446     if(data->change.cookielist) {
1447       /* If there is a list of cookie files to read, do it first so that
1448          we have all the told files read before we write the new jar.
1449          Curl_cookie_loadfiles() LOCKS and UNLOCKS the share itself! */
1450       Curl_cookie_loadfiles(data);
1451     }
1452
1453     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1454
1455     /* if we have a destination file for all the cookies to get dumped to */
1456     if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
1457       infof(data, "WARNING: failed to save cookies in %s\n",
1458             data->set.str[STRING_COOKIEJAR]);
1459   }
1460   else {
1461     if(cleanup && data->change.cookielist) {
1462       /* since nothing is written, we can just free the list of cookie file
1463          names */
1464       curl_slist_free_all(data->change.cookielist); /* clean up list */
1465       data->change.cookielist = NULL;
1466     }
1467     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1468   }
1469
1470   if(cleanup && (!data->share || (data->cookies != data->share->cookies))) {
1471     Curl_cookie_cleanup(data->cookies);
1472   }
1473   Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1474 }
1475
1476 #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */