diff options
author | Brad King <brad.king@kitware.com> | 2019-05-22 18:15:06 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2019-05-22 18:15:06 (GMT) |
commit | a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f (patch) | |
tree | a4d546a554025fb11ec6cc32e7491b150cde35f3 /Utilities/cmcurl/lib/cookie.c | |
parent | 2de8af0121c3ca64dcb82a1220d2ba255aab3553 (diff) | |
parent | b26487c663ec29d972fd61adc2b14ac5880b78c7 (diff) | |
download | CMake-a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f.zip CMake-a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f.tar.gz CMake-a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f.tar.bz2 |
Merge branch 'upstream-curl' into update-curl
* upstream-curl:
curl 2019-05-22 (885ce314)
Diffstat (limited to 'Utilities/cmcurl/lib/cookie.c')
-rw-r--r-- | Utilities/cmcurl/lib/cookie.c | 202 |
1 files changed, 129 insertions, 73 deletions
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c index a342c61..9a9e14d 100644 --- a/Utilities/cmcurl/lib/cookie.c +++ b/Utilities/cmcurl/lib/cookie.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -93,6 +93,7 @@ Example set of cookies: #include "share.h" #include "strtoofft.h" #include "strcase.h" +#include "curl_get_line.h" #include "curl_memrchr.h" #include "inet_pton.h" @@ -223,7 +224,7 @@ static bool pathmatch(const char *cookie_path, const char *request_uri) goto pathmatched; } - /* here, cookie_path_len < url_path_len */ + /* here, cookie_path_len < uri_path_len */ if(uri_path[cookie_path_len] == '/') { ret = TRUE; goto pathmatched; @@ -433,9 +434,10 @@ Curl_cookie_add(struct Curl_easy *data, bool noexpire, /* if TRUE, skip remove_expired() */ char *lineptr, /* first character of the line */ const char *domain, /* default domain */ - const char *path) /* full path used when this cookie is set, + const char *path, /* full path used when this cookie is set, used to get default path for the cookie unless set */ + bool secure) /* TRUE if connection is over secure origin */ { struct Cookie *clist; struct Cookie *co; @@ -527,6 +529,19 @@ Curl_cookie_add(struct Curl_easy *data, while(*whatptr && ISBLANK(*whatptr)) whatptr++; + /* + * Check if we have a reserved prefix set before anything else, as we + * otherwise have to test for the prefix in both the cookie name and + * "the rest". Prefixes must start with '__' and end with a '-', so + * only test for names where that can possibly be true. + */ + if(nlen > 3 && name[0] == '_' && name[1] == '_') { + if(strncasecompare("__Secure-", name, 9)) + co->prefix |= COOKIE_PREFIX__SECURE; + else if(strncasecompare("__Host-", name, 7)) + co->prefix |= COOKIE_PREFIX__HOST; + } + if(!co->name) { /* The very first name/value pair is the actual cookie name */ if(!sep) { @@ -546,8 +561,20 @@ Curl_cookie_add(struct Curl_easy *data, /* this was a "<name>=" with no content, and we must allow 'secure' and 'httponly' specified this weirdly */ done = TRUE; - if(strcasecompare("secure", name)) - co->secure = TRUE; + /* + * secure cookies are only allowed to be set when the connection is + * using a secure protocol, or when the cookie is being set by + * reading from file + */ + if(strcasecompare("secure", name)) { + if(secure || !c->running) { + co->secure = TRUE; + } + else { + badcookie = TRUE; + break; + } + } else if(strcasecompare("httponly", name)) co->httponly = TRUE; else if(sep) @@ -675,7 +702,10 @@ Curl_cookie_add(struct Curl_easy *data, /* overflow, used max value */ co->expires = CURL_OFF_T_MAX; else if(!offt) { - if(CURL_OFF_T_MAX - now < co->expires) + if(!co->expires) + /* already expired */ + co->expires = 1; + else if(CURL_OFF_T_MAX - now < co->expires) /* would overflow */ co->expires = CURL_OFF_T_MAX; else @@ -828,7 +858,13 @@ Curl_cookie_add(struct Curl_easy *data, fields++; /* add a field and fall down to secure */ /* FALLTHROUGH */ case 3: - co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE; + co->secure = FALSE; + if(strcasecompare(ptr, "TRUE")) { + if(secure || c->running) + co->secure = TRUE; + else + badcookie = TRUE; + } break; case 4: if(curlx_strtoofft(ptr, NULL, 10, &co->expires)) @@ -838,6 +874,13 @@ Curl_cookie_add(struct Curl_easy *data, co->name = strdup(ptr); if(!co->name) badcookie = TRUE; + else { + /* For Netscape file format cookies we check prefix on the name */ + if(strncasecompare("__Secure-", co->name, 9)) + co->prefix |= COOKIE_PREFIX__SECURE; + else if(strncasecompare("__Host-", co->name, 7)) + co->prefix |= COOKIE_PREFIX__HOST; + } break; case 6: co->value = strdup(ptr); @@ -866,6 +909,26 @@ Curl_cookie_add(struct Curl_easy *data, } + if(co->prefix & COOKIE_PREFIX__SECURE) { + /* The __Secure- prefix only requires that the cookie be set secure */ + if(!co->secure) { + freecookie(co); + return NULL; + } + } + if(co->prefix & COOKIE_PREFIX__HOST) { + /* + * The __Host- prefix requires the cookie to be secure, have a "/" path + * and not have a domain set. + */ + if(co->secure && co->path && strcmp(co->path, "/") == 0 && !co->tailmatch) + ; + else { + freecookie(co); + return NULL; + } + } + if(!c->running && /* read from a file */ c->newsession && /* clean session cookies */ !co->expires) { /* this is a session cookie since it doesn't expire! */ @@ -926,9 +989,31 @@ Curl_cookie_add(struct Curl_easy *data, /* the domains were identical */ if(clist->spath && co->spath) { - if(strcasecompare(clist->spath, co->spath)) { - replace_old = TRUE; + if(clist->secure && !co->secure && !secure) { + size_t cllen; + const char *sep; + + /* + * A non-secure cookie may not overlay an existing secure cookie. + * For an existing cookie "a" with path "/login", refuse a new + * cookie "a" with for example path "/login/en", while the path + * "/loginhelper" is ok. + */ + + sep = strchr(clist->spath + 1, '/'); + + if(sep) + cllen = sep - clist->spath; + else + cllen = strlen(clist->spath); + + if(strncasecompare(clist->spath, co->spath, cllen)) { + freecookie(co); + return NULL; + } } + else if(strcasecompare(clist->spath, co->spath)) + replace_old = TRUE; else replace_old = FALSE; } @@ -1003,33 +1088,6 @@ Curl_cookie_add(struct Curl_easy *data, return co; } -/* - * get_line() makes sure to only return complete whole lines that fit in 'len' - * bytes and end with a newline. - */ -static char *get_line(char *buf, int len, FILE *input) -{ - bool partial = FALSE; - while(1) { - char *b = fgets(buf, len, input); - if(b) { - size_t rlen = strlen(b); - if(rlen && (b[rlen-1] == '\n')) { - if(partial) { - partial = FALSE; - continue; - } - return b; - } - /* read a partial, discard the next piece that ends with newline */ - partial = TRUE; - } - else - break; - } - return NULL; -} - /***************************************************************************** * @@ -1087,7 +1145,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, line = malloc(MAX_COOKIE_LINE); if(!line) goto fail; - while(get_line(line, MAX_COOKIE_LINE, fp)) { + while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) { if(checkprefix("Set-Cookie:", line)) { /* This is a cookie line, get it! */ lineptr = &line[11]; @@ -1100,7 +1158,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, while(*lineptr && ISBLANK(*lineptr)) lineptr++; - Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL); + Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE); } free(line); /* free the line buffer */ remove_expired(c); /* run this once, not on every cookie */ @@ -1451,27 +1509,14 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) struct Cookie *co; FILE *out; bool use_stdout = FALSE; - char *format_ptr; - unsigned int i; - unsigned int j; - struct Cookie **array; - if((NULL == c) || (0 == c->numcookies)) - /* If there are no known cookies, we don't write or even create any - destination file */ + if(!c) + /* no cookie engine alive */ return 0; /* at first, remove expired cookies */ remove_expired(c); - /* make sure we still have cookies after expiration */ - if(0 == c->numcookies) - return 0; - - array = malloc(sizeof(struct Cookie *) * c->numcookies); - if(!array) - return 1; - if(!strcmp("-", dumphere)) { /* use stdout */ out = stdout; @@ -1480,7 +1525,6 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) else { out = fopen(dumphere, FOPEN_WRITETEXT); if(!out) { - free(array); return 1; /* failure */ } } @@ -1490,32 +1534,44 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) "# This file was generated by libcurl! Edit at your own risk.\n\n", out); - j = 0; - for(i = 0; i < COOKIE_HASH_SIZE; i++) { - for(co = c->cookies[i]; co; co = co->next) { - if(!co->domain) - continue; - array[j++] = co; - } - } - - qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct); + if(c->numcookies) { + unsigned int i; + unsigned int j; + struct Cookie **array; - for(i = 0; i < j; i++) { - format_ptr = get_netscape_format(array[i]); - if(format_ptr == NULL) { - fprintf(out, "#\n# Fatal libcurl error\n"); - free(array); + array = malloc(sizeof(struct Cookie *) * c->numcookies); + if(!array) { if(!use_stdout) fclose(out); return 1; } - fprintf(out, "%s\n", format_ptr); - free(format_ptr); - } - free(array); + j = 0; + for(i = 0; i < COOKIE_HASH_SIZE; i++) { + for(co = c->cookies[i]; co; co = co->next) { + if(!co->domain) + continue; + array[j++] = co; + } + } + + qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct); + for(i = 0; i < j; i++) { + char *format_ptr = get_netscape_format(array[i]); + if(format_ptr == NULL) { + fprintf(out, "#\n# Fatal libcurl error\n"); + free(array); + if(!use_stdout) + fclose(out); + return 1; + } + fprintf(out, "%s\n", format_ptr); + free(format_ptr); + } + + free(array); + } if(!use_stdout) fclose(out); |