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