diff options
Diffstat (limited to 'Utilities/cmcurl/lib/cookie.c')
-rw-r--r-- | Utilities/cmcurl/lib/cookie.c | 146 |
1 files changed, 88 insertions, 58 deletions
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c index 6b678ae..7fb596a 100644 --- a/Utilities/cmcurl/lib/cookie.c +++ b/Utilities/cmcurl/lib/cookie.c @@ -125,7 +125,7 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) if(hostname_len < cookie_domain_len) return FALSE; - if(!strcasecompare(cooke_domain, hostname+hostname_len-cookie_domain_len)) + if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len)) return FALSE; /* A lead char of cookie_domain is not '.'. @@ -375,9 +375,8 @@ Curl_cookie_add(struct Curl_easy *data, unless set */ { struct Cookie *clist; - char name[MAX_NAME]; struct Cookie *co; - struct Cookie *lastc=NULL; + struct Cookie *lastc = NULL; time_t now = time(NULL); bool replace_old = FALSE; bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */ @@ -397,17 +396,19 @@ Curl_cookie_add(struct Curl_easy *data, if(httpheader) { /* This line was read off a HTTP-header */ + char name[MAX_NAME]; + char what[MAX_NAME]; const char *ptr; const char *semiptr; - char *what; - what = malloc(MAX_COOKIE_LINE); - if(!what) { + size_t linelength = strlen(lineptr); + if(linelength > MAX_COOKIE_LINE) { + /* discard overly long lines at once */ free(co); return NULL; } - semiptr=strchr(lineptr, ';'); /* first, find a semicolon */ + semiptr = strchr(lineptr, ';'); /* first, find a semicolon */ while(*lineptr && ISBLANK(*lineptr)) lineptr++; @@ -415,9 +416,9 @@ Curl_cookie_add(struct Curl_easy *data, ptr = lineptr; do { /* we have a <what>=<this> pair or a stand-alone word here */ - name[0]=what[0]=0; /* init the buffers */ + name[0] = what[0] = 0; /* init the buffers */ if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%" - MAX_COOKIE_LINE_TXT "[^;\r\n]", + MAX_NAME_TXT "[^;\r\n]", name, what)) { /* Use strstore() below to properly deal with received cookie headers that have the same string property set more than once, @@ -425,10 +426,24 @@ Curl_cookie_add(struct Curl_easy *data, const char *whatptr; bool done = FALSE; bool sep; - size_t len=strlen(what); + size_t len = strlen(what); size_t nlen = strlen(name); const char *endofn = &ptr[ nlen ]; + infof(data, "cookie size: name/val %d + %d bytes\n", + nlen, len); + + if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) || + ((nlen + len) > MAX_NAME)) { + /* too long individual name or contents, or too long combination of + name + contents. Chrome and Firefox support 4095 or 4096 bytes + combo. */ + freecookie(co); + infof(data, "oversized cookie dropped, name/val %d + %d bytes\n", + nlen, len); + return NULL; + } + /* name ends with a '=' ? */ sep = (*endofn == '=')?TRUE:FALSE; @@ -440,18 +455,18 @@ Curl_cookie_add(struct Curl_easy *data, endofn--; nlen--; } - name[nlen]=0; /* new end of name */ + name[nlen] = 0; /* new end of name */ } } /* Strip off trailing whitespace from the 'what' */ while(len && ISBLANK(what[len-1])) { - what[len-1]=0; + what[len-1] = 0; len--; } /* Skip leading whitespace from the 'what' */ - whatptr=what; + whatptr = what; while(*whatptr && ISBLANK(*whatptr)) whatptr++; @@ -484,6 +499,7 @@ Curl_cookie_add(struct Curl_easy *data, badcookie = TRUE; /* out of memory bad */ break; } + free(co->spath); /* if this is set again */ co->spath = sanitize_cookie_path(co->path); if(!co->spath) { badcookie = TRUE; /* out of memory bad */ @@ -510,7 +526,7 @@ Curl_cookie_add(struct Curl_easy *data, /* check for more dots */ dotp = strchr(whatptr, '.'); if(!dotp && !strcasecompare("localhost", whatptr)) - domain=":"; + domain = ":"; } #endif @@ -525,14 +541,14 @@ Curl_cookie_add(struct Curl_easy *data, break; } if(!is_ip) - co->tailmatch=TRUE; /* we always do that if the domain name was - given */ + co->tailmatch = TRUE; /* we always do that if the domain name was + given */ } else { /* we did not get a tailmatch and then the attempted set domain is not a domain to which the current host belongs. Mark as bad. */ - badcookie=TRUE; + badcookie = TRUE; infof(data, "skipped cookie with bad tailmatch domain: %s\n", whatptr); } @@ -581,26 +597,32 @@ Curl_cookie_add(struct Curl_easy *data, continue; } - ptr=semiptr+1; + ptr = semiptr + 1; while(*ptr && ISBLANK(*ptr)) ptr++; - semiptr=strchr(ptr, ';'); /* now, find the next semicolon */ + semiptr = strchr(ptr, ';'); /* now, find the next semicolon */ if(!semiptr && *ptr) /* There are no more semicolons, but there's a final name=value pair coming up */ - semiptr=strchr(ptr, '\0'); + semiptr = strchr(ptr, '\0'); } while(semiptr); if(co->maxage) { - co->expires = - curlx_strtoofft((*co->maxage=='\"')? - &co->maxage[1]:&co->maxage[0], NULL, 10); - if(CURL_OFF_T_MAX - now < co->expires) - /* avoid overflow */ + CURLofft offt; + offt = curlx_strtoofft((*co->maxage == '\"')? + &co->maxage[1]:&co->maxage[0], NULL, 10, + &co->expires); + if(offt == CURL_OFFT_FLOW) + /* overflow, used max value */ co->expires = CURL_OFF_T_MAX; - else - co->expires += now; + else if(!offt) { + if(CURL_OFF_T_MAX - now < co->expires) + /* would overflow */ + co->expires = CURL_OFF_T_MAX; + else + co->expires += now; + } } else if(co->expirestr) { /* Note that if the date couldn't get parsed for whatever reason, @@ -619,7 +641,7 @@ Curl_cookie_add(struct Curl_easy *data, if(!badcookie && !co->domain) { if(domain) { /* no domain was given in the header line, set the default */ - co->domain=strdup(domain); + co->domain = strdup(domain); if(!co->domain) badcookie = TRUE; } @@ -639,11 +661,11 @@ Curl_cookie_add(struct Curl_easy *data, else endslash = memrchr(path, '/', (size_t)(queryp - path)); if(endslash) { - size_t pathlen = (size_t)(endslash-path+1); /* include ending slash */ - co->path=malloc(pathlen+1); /* one extra for the zero byte */ + size_t pathlen = (size_t)(endslash-path + 1); /* include end slash */ + co->path = malloc(pathlen + 1); /* one extra for the zero byte */ if(co->path) { memcpy(co->path, path, pathlen); - co->path[pathlen]=0; /* zero terminate */ + co->path[pathlen] = 0; /* zero terminate */ co->spath = sanitize_cookie_path(co->path); if(!co->spath) badcookie = TRUE; /* out of memory bad */ @@ -653,8 +675,6 @@ Curl_cookie_add(struct Curl_easy *data, } } - free(what); - if(badcookie || !co->name) { /* we didn't get a cookie name or a bad one, this is an illegal line, bail out */ @@ -668,7 +688,7 @@ Curl_cookie_add(struct Curl_easy *data, reading the odd netscape cookies-file format here */ char *ptr; char *firstptr; - char *tok_buf=NULL; + char *tok_buf = NULL; int fields; /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies @@ -689,19 +709,19 @@ Curl_cookie_add(struct Curl_easy *data, return NULL; } /* strip off the possible end-of-line characters */ - ptr=strchr(lineptr, '\r'); + ptr = strchr(lineptr, '\r'); if(ptr) - *ptr=0; /* clear it */ - ptr=strchr(lineptr, '\n'); + *ptr = 0; /* clear it */ + ptr = strchr(lineptr, '\n'); if(ptr) - *ptr=0; /* clear it */ + *ptr = 0; /* clear it */ - firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */ + firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */ /* Now loop through the fields and init the struct we already have allocated */ - for(ptr=firstptr, fields=0; ptr && !badcookie; - ptr=strtok_r(NULL, "\t", &tok_buf), fields++) { + for(ptr = firstptr, fields = 0; ptr && !badcookie; + ptr = strtok_r(NULL, "\t", &tok_buf), fields++) { switch(fields) { case 0: if(ptr[0]=='.') /* skip preceding dots */ @@ -712,7 +732,7 @@ Curl_cookie_add(struct Curl_easy *data, break; case 1: /* This field got its explanation on the 23rd of May 2001 by - Andrés García: + Andrés GarcÃa: flag: A TRUE/FALSE value indicating if all machines within a given domain can access the variable. This value is set automatically by @@ -726,7 +746,7 @@ Curl_cookie_add(struct Curl_easy *data, case 2: /* It turns out, that sometimes the file format allows the path field to remain not filled in, we try to detect this and work - around it! Andrés García made us aware of this... */ + around it! Andrés GarcÃa made us aware of this... */ if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) { /* only if the path doesn't look like a boolean option! */ co->path = strdup(ptr); @@ -753,7 +773,8 @@ Curl_cookie_add(struct Curl_easy *data, co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE; break; case 4: - co->expires = curlx_strtoofft(ptr, NULL, 10); + if(curlx_strtoofft(ptr, NULL, 10, &co->expires)) + badcookie = TRUE; break; case 5: co->name = strdup(ptr); @@ -828,7 +849,7 @@ Curl_cookie_add(struct Curl_easy *data, if(strcasecompare(clist->domain, co->domain) && (clist->tailmatch == co->tailmatch)) /* The domains are identical */ - replace_old=TRUE; + replace_old = TRUE; } else if(!clist->domain && !co->domain) replace_old = TRUE; @@ -957,7 +978,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, { struct CookieInfo *c; FILE *fp = NULL; - bool fromfile=TRUE; + bool fromfile = TRUE; char *line = NULL; if(NULL == inc) { @@ -977,7 +998,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, if(file && !strcmp(file, "-")) { fp = stdin; - fromfile=FALSE; + fromfile = FALSE; } else if(file && !*file) { /* points to a "" string */ @@ -998,12 +1019,12 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, while(get_line(line, MAX_COOKIE_LINE, fp)) { if(checkprefix("Set-Cookie:", line)) { /* This is a cookie line, get it! */ - lineptr=&line[11]; - headerline=TRUE; + lineptr = &line[11]; + headerline = TRUE; } else { - lineptr=line; - headerline=FALSE; + lineptr = line; + headerline = FALSE; } while(*lineptr && ISBLANK(*lineptr)) lineptr++; @@ -1113,7 +1134,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, struct Cookie *newco; struct Cookie *co; time_t now = time(NULL); - struct Cookie *mainco=NULL; + struct Cookie *mainco = NULL; size_t matches = 0; bool is_ip; @@ -1185,7 +1206,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, co = mainco; - for(i=0; co; co = co->next) + for(i = 0; co; co = co->next) array[i++] = co; /* now sort the cookie pointers in path length order */ @@ -1194,8 +1215,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, /* remake the linked list order according to the new order */ mainco = array[0]; /* start here */ - for(i=0; i<matches-1; i++) - array[i]->next = array[i+1]; + for(i = 0; i<matches-1; i++) + array[i]->next = array[i + 1]; array[matches-1]->next = NULL; /* terminate the list */ free(array); /* remove the temporary data again */ @@ -1335,7 +1356,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) { struct Cookie *co; FILE *out; - bool use_stdout=FALSE; + bool use_stdout = FALSE; char *format_ptr; if((NULL == c) || (0 == c->numcookies)) @@ -1349,7 +1370,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) if(!strcmp("-", dumphere)) { /* use stdout */ out = stdout; - use_stdout=TRUE; + use_stdout = TRUE; } else { out = fopen(dumphere, FOPEN_WRITETEXT); @@ -1382,7 +1403,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) return 0; } -struct curl_slist *Curl_cookie_list(struct Curl_easy *data) +static struct curl_slist *cookie_list(struct Curl_easy *data) { struct curl_slist *list = NULL; struct curl_slist *beg; @@ -1413,6 +1434,15 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data) return list; } +struct curl_slist *Curl_cookie_list(struct Curl_easy *data) +{ + struct curl_slist *list; + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + list = cookie_list(data); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + return list; +} + void Curl_flush_cookies(struct Curl_easy *data, int cleanup) { if(data->set.str[STRING_COOKIEJAR]) { |