diff options
author | Haibo Huang <hhb@google.com> | 2019-03-27 15:37:23 -0700 |
---|---|---|
committer | Haibo Huang <hhb@google.com> | 2019-03-27 17:05:52 -0700 |
commit | 65021c717cb61b56266f98a37e3b5fdf301eed9c (patch) | |
tree | 9753361771934a45d695227eb73f3a6411457c53 /lib | |
parent | 55493b7b1e7467e4c477d77221cd4ea9bf259ae1 (diff) | |
download | external_curl-65021c717cb61b56266f98a37e3b5fdf301eed9c.tar.gz external_curl-65021c717cb61b56266f98a37e3b5fdf301eed9c.tar.bz2 external_curl-65021c717cb61b56266f98a37e3b5fdf301eed9c.zip |
Upgrade curl to 7.64.1
Test: build
Change-Id: I31c820b646e6b7ef71e5f8763071f18d8933cb28
Diffstat (limited to 'lib')
94 files changed, 2608 insertions, 1753 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index f2034a2f..7c258b3f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -131,9 +131,14 @@ include Makefile.inc libcurl_la_SOURCES = $(CSOURCES) $(HHEADERS) libcurlu_la_SOURCES = $(CSOURCES) $(HHEADERS) +CHECKSRC = $(CS_$(V)) +CS_0 = @echo " RUN " $@; +CS_1 = +CS_ = $(CS_0) + checksrc: - @PERL@ $(srcdir)/checksrc.pl -D$(srcdir) -W$(srcdir)/curl_config.h \ - $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch] + $(CHECKSRC)(@PERL@ $(srcdir)/checksrc.pl -D$(srcdir) -W$(srcdir)/curl_config.h \ + $(srcdir)/*.[ch] $(srcdir)/vauth/*.[ch] $(srcdir)/vtls/*.[ch]) if CURLDEBUG # for debug builds, we scan the sources on all regular make invokes diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 54acd6ce..6c47bcda 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -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 @@ -30,11 +30,11 @@ LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \ vtls/polarssl.c vtls/polarssl_threadlock.c \ vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c \ - vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c + vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \ vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \ - vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h \ + vtls/cyassl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \ vtls/mbedtls.h vtls/mesalink.h LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ @@ -55,7 +55,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \ x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \ mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \ - doh.c urlapi.c + doh.c urlapi.c altsvc.c LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ @@ -75,7 +75,8 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \ x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \ - curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h + curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ + altsvc.h LIB_RCFILES = libcurl.rc diff --git a/lib/altsvc.c b/lib/altsvc.c new file mode 100644 index 00000000..16434664 --- /dev/null +++ b/lib/altsvc.c @@ -0,0 +1,571 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 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 + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + * The Alt-Svc: header is defined in RFC 7838: + * https://tools.ietf.org/html/rfc7838 + */ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) +#include <curl/curl.h> +#include "urldata.h" +#include "altsvc.h" +#include "cookie.h" /* for Curl_get_line() */ +#include "strcase.h" +#include "parsedate.h" +#include "sendf.h" +#include "warnless.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#define MAX_ALTSVC_LINE 4095 +#define MAX_ALTSVC_DATELENSTR "64" +#define MAX_ALTSVC_DATELEN 64 +#define MAX_ALTSVC_HOSTLENSTR "512" +#define MAX_ALTSVC_HOSTLEN 512 +#define MAX_ALTSVC_ALPNLENSTR "10" +#define MAX_ALTSVC_ALPNLEN 10 + +static enum alpnid alpn2alpnid(char *name) +{ + if(strcasecompare(name, "h1")) + return ALPN_h1; + if(strcasecompare(name, "h2")) + return ALPN_h2; + if(strcasecompare(name, "h2c")) + return ALPN_h2c; + if(strcasecompare(name, "h3")) + return ALPN_h3; + return ALPN_none; /* unknown, probably rubbish input */ +} + +/* Given the ALPN ID, return the name */ +const char *Curl_alpnid2str(enum alpnid id) +{ + switch(id) { + case ALPN_h1: + return "h1"; + case ALPN_h2: + return "h2"; + case ALPN_h2c: + return "h2c"; + case ALPN_h3: + return "h3"; + default: + return ""; /* bad */ + } +} + + +static void altsvc_free(struct altsvc *as) +{ + free(as->srchost); + free(as->dsthost); + free(as); +} + +static struct altsvc *altsvc_createid(const char *srchost, + const char *dsthost, + enum alpnid srcalpnid, + enum alpnid dstalpnid, + unsigned int srcport, + unsigned int dstport) +{ + struct altsvc *as = calloc(sizeof(struct altsvc), 1); + if(!as) + return NULL; + + as->srchost = strdup(srchost); + if(!as->srchost) + goto error; + as->dsthost = strdup(dsthost); + if(!as->dsthost) + goto error; + + as->srcalpnid = srcalpnid; + as->dstalpnid = dstalpnid; + as->srcport = curlx_ultous(srcport); + as->dstport = curlx_ultous(dstport); + + return as; + error: + altsvc_free(as); + return NULL; +} + +static struct altsvc *altsvc_create(char *srchost, + char *dsthost, + char *srcalpn, + char *dstalpn, + unsigned int srcport, + unsigned int dstport) +{ + enum alpnid dstalpnid = alpn2alpnid(dstalpn); + enum alpnid srcalpnid = alpn2alpnid(srcalpn); + if(!srcalpnid || !dstalpnid) + return NULL; + return altsvc_createid(srchost, dsthost, srcalpnid, dstalpnid, + srcport, dstport); +} + +/* only returns SERIOUS errors */ +static CURLcode altsvc_add(struct altsvcinfo *asi, char *line) +{ + /* Example line: + h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1 + */ + char srchost[MAX_ALTSVC_HOSTLEN + 1]; + char dsthost[MAX_ALTSVC_HOSTLEN + 1]; + char srcalpn[MAX_ALTSVC_ALPNLEN + 1]; + char dstalpn[MAX_ALTSVC_ALPNLEN + 1]; + char date[MAX_ALTSVC_DATELEN + 1]; + unsigned int srcport; + unsigned int dstport; + unsigned int prio; + unsigned int persist; + int rc; + + rc = sscanf(line, + "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u " + "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u " + "\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u", + srcalpn, srchost, &srcport, + dstalpn, dsthost, &dstport, + date, &persist, &prio); + if(9 == rc) { + struct altsvc *as; + time_t expires = curl_getdate(date, NULL); + as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport); + if(as) { + as->expires = expires; + as->prio = prio; + as->persist = persist ? 1 : 0; + Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); + asi->num++; /* one more entry */ + } + } + + return CURLE_OK; +} + +/* + * Load alt-svc entries from the given file. The text based line-oriented file + * format is documented here: + * https://github.com/curl/curl/wiki/QUIC-implementation + * + * This function only returns error on major problems that prevents alt-svc + * handling to work completely. It will ignore individual syntactical errors + * etc. + */ +static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file) +{ + CURLcode result = CURLE_OK; + char *line = NULL; + FILE *fp = fopen(file, FOPEN_READTEXT); + if(fp) { + line = malloc(MAX_ALTSVC_LINE); + if(!line) + goto fail; + while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) { + char *lineptr = line; + while(*lineptr && ISBLANK(*lineptr)) + lineptr++; + if(*lineptr == '#') + /* skip commented lines */ + continue; + + altsvc_add(asi, lineptr); + } + free(line); /* free the line buffer */ + fclose(fp); + } + return result; + + fail: + free(line); + fclose(fp); + return CURLE_OUT_OF_MEMORY; +} + +/* + * Write this single altsvc entry to a single output line + */ + +static CURLcode altsvc_out(struct altsvc *as, FILE *fp) +{ + struct tm stamp; + CURLcode result = Curl_gmtime(as->expires, &stamp); + if(result) + return result; + + fprintf(fp, + "%s %s %u " + "%s %s %u " + "\"%d%02d%02d " + "%02d:%02d:%02d\" " + "%u %d\n", + Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport, + Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport, + stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, + stamp.tm_hour, stamp.tm_min, stamp.tm_sec, + as->persist, as->prio); + return CURLE_OK; +} + +/* ---- library-wide functions below ---- */ + +/* + * Curl_altsvc_init() creates a new altsvc cache. + * It returns the new instance or NULL if something goes wrong. + */ +struct altsvcinfo *Curl_altsvc_init(void) +{ + struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1); + if(!asi) + return NULL; + Curl_llist_init(&asi->list, NULL); + + /* set default behavior */ + asi->flags = CURLALTSVC_H1 +#ifdef USE_NGHTTP2 + | CURLALTSVC_H2 +#endif +#ifdef USE_HTTP3 + /* TODO: adjust when known */ + | CURLALTSVC_H3 +#endif + ; + return asi; +} + +/* + * Curl_altsvc_load() loads alt-svc from file. + */ +CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file) +{ + CURLcode result; + DEBUGASSERT(asi); + result = altsvc_load(asi, file); + return result; +} + +/* + * Curl_altsvc_ctrl() passes on the external bitmask. + */ +CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl) +{ + DEBUGASSERT(asi); + if(!ctrl) + /* unexpected */ + return CURLE_BAD_FUNCTION_ARGUMENT; + asi->flags = ctrl; + return CURLE_OK; +} + +/* + * Curl_altsvc_cleanup() frees an altsvc cache instance and all associated + * resources. + */ +void Curl_altsvc_cleanup(struct altsvcinfo *altsvc) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + if(altsvc) { + for(e = altsvc->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + altsvc_free(as); + } + free(altsvc); + } +} + +/* + * Curl_altsvc_save() writes the altsvc cache to a file. + */ +CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + CURLcode result = CURLE_OK; + FILE *out; + + if(!altsvc) + /* no cache activated */ + return CURLE_OK; + + if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file[0]) + /* marked as read-only or zero length file name */ + return CURLE_OK; + out = fopen(file, FOPEN_WRITETEXT); + if(!out) + return CURLE_WRITE_ERROR; + fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n" + "# This file was generated by libcurl! Edit at your own risk.\n", + out); + for(e = altsvc->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + result = altsvc_out(as, out); + if(result) + break; + } + fclose(out); + return result; +} + +static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen) +{ + size_t len; + const char *protop; + const char *p = *ptr; + while(*p && ISBLANK(*p)) + p++; + protop = p; + while(*p && ISALNUM(*p)) + p++; + len = p - protop; + + if(!len || (len >= buflen)) + return CURLE_BAD_FUNCTION_ARGUMENT; /* TODO: improve error code */ + memcpy(alpnbuf, protop, len); + alpnbuf[len] = 0; + *ptr = p; + return CURLE_OK; +} + +/* altsvc_flush() removes all alternatives for this source origin from the + list */ +static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid, + const char *srchost, unsigned short srcport) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + for(e = asi->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + if((srcalpnid == as->srcalpnid) && + (srcport == as->srcport) && + strcasecompare(srchost, as->srchost)) { + Curl_llist_remove(&asi->list, e, NULL); + altsvc_free(as); + asi->num--; + } + } +} + +#ifdef DEBUGBUILD +/* to play well with debug builds, we can *set* a fixed time this will + return */ +static time_t debugtime(void *unused) +{ + char *timestr = getenv("CURL_TIME"); + (void)unused; + if(timestr) { + unsigned long val = strtol(timestr, NULL, 10); + return (time_t)val; + } + return time(NULL); +} +#define time(x) debugtime(x) +#endif + +/* + * Curl_altsvc_parse() takes an incoming alt-svc response header and stores + * the data correctly in the cache. + * + * 'value' points to the header *value*. That's contents to the right of the + * header name. + */ +CURLcode Curl_altsvc_parse(struct Curl_easy *data, + struct altsvcinfo *asi, const char *value, + enum alpnid srcalpnid, const char *srchost, + unsigned short srcport) +{ + const char *p = value; + size_t len; + enum alpnid dstalpnid = srcalpnid; /* the same by default */ + char namebuf[MAX_ALTSVC_HOSTLEN] = ""; + char alpnbuf[MAX_ALTSVC_ALPNLEN] = ""; + struct altsvc *as; + unsigned short dstport = srcport; /* the same by default */ + const char *semip; + time_t maxage = 24 * 3600; /* default is 24 hours */ + bool persist = FALSE; + CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf)); + if(result) + return result; + + DEBUGASSERT(asi); + + /* Flush all cached alternatives for this source origin, if any */ + altsvc_flush(asi, srcalpnid, srchost, srcport); + + /* "clear" is a magic keyword */ + if(strcasecompare(alpnbuf, "clear")) { + /* TODO: clear whatever it is it should clear */ + return CURLE_OK; + } + + /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives + but are set after the list on the line. Scan for the semicolons and get + those fields first! */ + semip = p; + do { + semip = strchr(semip, ';'); + if(semip) { + char option[32]; + unsigned long num; + char *end_ptr; + semip++; /* pass the semicolon */ + result = getalnum(&semip, option, sizeof(option)); + if(result) + break; + while(*semip && ISBLANK(*semip)) + semip++; + if(*semip != '=') + continue; + semip++; + num = strtoul(semip, &end_ptr, 10); + if(num < ULONG_MAX) { + if(strcasecompare("ma", option)) + maxage = num; + else if(strcasecompare("persist", option) && (num == 1)) + persist = TRUE; + } + semip = end_ptr; + } + } while(semip); + + do { + if(*p == '=') { + /* [protocol]="[host][:port]" */ + dstalpnid = alpn2alpnid(alpnbuf); + if(!dstalpnid) { + infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf); + return CURLE_OK; + } + p++; + if(*p == '\"') { + const char *dsthost; + p++; + if(*p != ':') { + /* host name starts here */ + const char *hostp = p; + while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-'))) + p++; + len = p - hostp; + if(!len || (len >= MAX_ALTSVC_HOSTLEN)) + return CURLE_BAD_FUNCTION_ARGUMENT; /* TODO: improve error code */ + memcpy(namebuf, hostp, len); + namebuf[len] = 0; + dsthost = namebuf; + } + else { + /* no destination name, use source host */ + dsthost = srchost; + } + if(*p == ':') { + /* a port number */ + char *end_ptr; + unsigned long port = strtoul(++p, &end_ptr, 10); + if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') { + infof(data, "Unknown alt-svc port number, ignoring...\n"); + return CURLE_OK; + } + p = end_ptr; + dstport = curlx_ultous(port); + } + if(*p++ != '\"') + return CURLE_BAD_FUNCTION_ARGUMENT; + as = altsvc_createid(srchost, dsthost, + srcalpnid, dstalpnid, + srcport, dstport); + if(as) { + /* TODO: the expires time also needs to take the Age: value (if any) + into account. [See RFC 7838 section 3.1] */ + as->expires = maxage + time(NULL); + as->persist = persist; + Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); + asi->num++; /* one more entry */ + infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport, + Curl_alpnid2str(dstalpnid)); + } + } + /* after the double quote there can be a comma if there's another + string or a semicolon if no more */ + if(*p == ',') { + /* comma means another alternative is presented */ + p++; + result = getalnum(&p, alpnbuf, sizeof(alpnbuf)); + if(result) + /* failed to parse, but since we already did at least one host we + return OK */ + return CURLE_OK; + } + } + } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r')); + + return CURLE_OK; +} + +/* + * Return TRUE on a match + */ +bool Curl_altsvc_lookup(struct altsvcinfo *asi, + enum alpnid srcalpnid, const char *srchost, + int srcport, + enum alpnid *dstalpnid, const char **dsthost, + int *dstport) +{ + struct curl_llist_element *e; + struct curl_llist_element *n; + time_t now = time(NULL); + DEBUGASSERT(asi); + DEBUGASSERT(srchost); + DEBUGASSERT(dsthost); + + for(e = asi->list.head; e; e = n) { + struct altsvc *as = e->ptr; + n = e->next; + if(as->expires < now) { + /* an expired entry, remove */ + altsvc_free(as); + continue; + } + if((as->srcalpnid == srcalpnid) && + strcasecompare(as->srchost, srchost) && + as->srcport == srcport) { + /* match */ + *dstalpnid = as->dstalpnid; + *dsthost = as->dsthost; + *dstport = as->dstport; + return TRUE; + } + } + return FALSE; +} + +#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ diff --git a/lib/altsvc.h b/lib/altsvc.h new file mode 100644 index 00000000..eefb45bf --- /dev/null +++ b/lib/altsvc.h @@ -0,0 +1,77 @@ +#ifndef HEADER_CURL_ALTSVC_H +#define HEADER_CURL_ALTSVC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 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 + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) +#include <curl/curl.h> +#include "llist.h" + +enum alpnid { + ALPN_none, + ALPN_h1, + ALPN_h2, + ALPN_h2c, + ALPN_h3 +}; + +struct altsvc { + char *srchost; + char *dsthost; + unsigned short srcport; + unsigned short dstport; + enum alpnid srcalpnid; + enum alpnid dstalpnid; + time_t expires; + bool persist; + int prio; + struct curl_llist_element node; +}; + +struct altsvcinfo { + char *filename; + struct curl_llist list; /* list of entries */ + size_t num; /* number of alt-svc entries */ + long flags; /* the publicly set bitmask */ +}; + +const char *Curl_alpnid2str(enum alpnid id); +struct altsvcinfo *Curl_altsvc_init(void); +CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file); +CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file); +CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl); +void Curl_altsvc_cleanup(struct altsvcinfo *altsvc); +CURLcode Curl_altsvc_parse(struct Curl_easy *data, + struct altsvcinfo *altsvc, const char *value, + enum alpnid srcalpn, const char *srchost, + unsigned short srcport); +bool Curl_altsvc_lookup(struct altsvcinfo *asi, + enum alpnid srcalpnid, const char *srchost, + int srcport, + enum alpnid *dstalpnid, const char **dsthost, + int *dstport); +#else +/* disabled */ +#define Curl_altsvc_save(a,b) +#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ +#endif /* HEADER_CURL_ALTSVC_H */ diff --git a/lib/amigaos.c b/lib/amigaos.c index 4f55b30e..cf44bdc8 100644 --- a/lib/amigaos.c +++ b/lib/amigaos.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, 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 @@ -22,17 +22,26 @@ #include "curl_setup.h" -#if defined(__AMIGA__) && !defined(__ixemul__) - -#include <amitcp/socketbasetags.h> +#ifdef __AMIGA__ +# include "amigaos.h" +# if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL) +# include <amitcp/socketbasetags.h> +# endif +# ifdef __libnix__ +# include <stabs.h> +# endif +#endif -#include "amigaos.h" +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" +#ifdef __AMIGA__ +#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL) struct Library *SocketBase = NULL; extern int errno, h_errno; #ifdef __libnix__ -#include <stabs.h> void __request(const char *msg); #else # define __request(msg) Printf(msg "\n\a") @@ -74,4 +83,13 @@ bool Curl_amiga_init() ADD2EXIT(Curl_amiga_cleanup, -50); #endif -#endif /* __AMIGA__ && ! __ixemul__ */ +#endif /* HAVE_PROTO_BSDSOCKET_H */ + +#ifdef USE_AMISSL +void Curl_amiga_X509_free(X509 *a) +{ + X509_free(a); +} +#endif /* USE_AMISSL */ +#endif /* __AMIGA__ */ + diff --git a/lib/amigaos.h b/lib/amigaos.h index 7c0926cc..c776c9c9 100644 --- a/lib/amigaos.h +++ b/lib/amigaos.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, 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 @@ -23,7 +23,7 @@ ***************************************************************************/ #include "curl_setup.h" -#if defined(__AMIGA__) && !defined(__ixemul__) +#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL) bool Curl_amiga_init(); void Curl_amiga_cleanup(); @@ -35,4 +35,10 @@ void Curl_amiga_cleanup(); #endif +#ifdef USE_AMISSL +#include <openssl/x509v3.h> +void Curl_amiga_X509_free(X509 *a); +#endif /* USE_AMISSL */ + #endif /* HEADER_CURL_AMIGAOS_H */ + diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index a9679d06..55e0811c 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -461,6 +461,42 @@ static CURLcode resolver_error(struct connectdata *conn) return result; } +static CURLcode thread_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **entry, + bool report) +{ + struct thread_data *td = (struct thread_data*) conn->async.os_specific; + CURLcode result = CURLE_OK; + + DEBUGASSERT(conn && td); + DEBUGASSERT(td->thread_hnd != curl_thread_t_null); + + /* wait for the thread to resolve the name */ + if(Curl_thread_join(&td->thread_hnd)) { + if(entry) + result = getaddrinfo_complete(conn); + } + else + DEBUGASSERT(0); + + conn->async.done = TRUE; + + if(entry) + *entry = conn->async.dns; + + if(!conn->async.dns && report) + /* a name was not resolved, report error */ + result = resolver_error(conn); + + destroy_async_data(&conn->async); + + if(!conn->async.dns && report) + connclose(conn, "asynch resolve failed"); + + return result; +} + + /* * Until we gain a way to signal the resolver threads to stop early, we must * simply wait for them and ignore their results. @@ -473,7 +509,7 @@ void Curl_resolver_kill(struct connectdata *conn) unfortunately. Otherwise, we can simply cancel to clean up any resolver data. */ if(td && td->thread_hnd != curl_thread_t_null) - (void)Curl_resolver_wait_resolv(conn, NULL); + (void)thread_wait_resolv(conn, NULL, FALSE); else Curl_resolver_cancel(conn); } @@ -494,35 +530,7 @@ void Curl_resolver_kill(struct connectdata *conn) CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, struct Curl_dns_entry **entry) { - struct thread_data *td = (struct thread_data*) conn->async.os_specific; - CURLcode result = CURLE_OK; - - DEBUGASSERT(conn && td); - DEBUGASSERT(td->thread_hnd != curl_thread_t_null); - - /* wait for the thread to resolve the name */ - if(Curl_thread_join(&td->thread_hnd)) { - if(entry) - result = getaddrinfo_complete(conn); - } - else - DEBUGASSERT(0); - - conn->async.done = TRUE; - - if(entry) - *entry = conn->async.dns; - - if(!conn->async.dns) - /* a name was not resolved, report error */ - result = resolver_error(conn); - - destroy_async_data(&conn->async); - - if(!conn->async.dns) - connclose(conn, "asynch resolve failed"); - - return result; + return thread_wait_resolv(conn, entry, TRUE); } /* diff --git a/lib/config-os400.h b/lib/config-os400.h index 7844444f..bde4f0b3 100644 --- a/lib/config-os400.h +++ b/lib/config-os400.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, 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 @@ -425,6 +425,9 @@ /* Define if you can safely include both <sys/time.h> and <time.h>. */ #define TIME_WITH_SYS_TIME +/* Define to enable alt-svc support (experimental) */ +#undef USE_ALTSVC + /* Version number of package */ #undef VERSION diff --git a/lib/config-vxworks.h b/lib/config-vxworks.h index a03e341e..8790f826 100644 --- a/lib/config-vxworks.h +++ b/lib/config-vxworks.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, 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 @@ -161,9 +161,6 @@ /* Define to 1 if you have a working fcntl O_NONBLOCK function. */ #define HAVE_FCNTL_O_NONBLOCK 1 -/* Define to 1 if you have the fdopen function. */ -#define HAVE_FDOPEN 1 - /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 diff --git a/lib/conncache.c b/lib/conncache.c index 78ad386c..39302ba7 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -392,8 +392,8 @@ bool Curl_conncache_foreach(struct Curl_easy *data, NOTE: no locking is done here as this is presumably only done when cleaning up a cache! */ -struct connectdata * -Curl_conncache_find_first_connection(struct conncache *connc) +static struct connectdata * +conncache_find_first_connection(struct conncache *connc) { struct curl_hash_iterator iter; struct curl_hash_element *he; @@ -433,6 +433,7 @@ bool Curl_conncache_return_conn(struct connectdata *conn) data->multi->maxconnects; struct connectdata *conn_candidate = NULL; + conn->data = NULL; /* no owner anymore */ if(maxconnects > 0 && Curl_conncache_size(data) > maxconnects) { infof(data, "Connection cache is full, closing the oldest one.\n"); @@ -476,7 +477,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data, while(curr) { conn = curr->ptr; - if(!CONN_INUSE(conn)) { + if(!CONN_INUSE(conn) && !conn->data) { /* Set higher score for the age passed since the connection was used */ score = Curl_timediff(now, conn->now); @@ -534,7 +535,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) while(curr) { conn = curr->ptr; - if(!CONN_INUSE(conn)) { + if(!CONN_INUSE(conn) && !conn->data) { /* Set higher score for the age passed since the connection was used */ score = Curl_timediff(now, conn->now); @@ -566,7 +567,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc) { struct connectdata *conn; - conn = Curl_conncache_find_first_connection(connc); + conn = conncache_find_first_connection(connc); while(conn) { SIGPIPE_VARIABLE(pipe_st); conn->data = connc->closure_handle; @@ -577,7 +578,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc) (void)Curl_disconnect(connc->closure_handle, conn, FALSE); sigpipe_restore(&pipe_st); - conn = Curl_conncache_find_first_connection(connc); + conn = conncache_find_first_connection(connc); } if(connc->closure_handle) { diff --git a/lib/connect.c b/lib/connect.c index ec3cd3a7..a53d79c2 100644 --- a/lib/connect.c +++ b/lib/connect.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 @@ -446,9 +446,10 @@ static CURLcode bindlocal(struct connectdata *conn, curl_socklen_t size = sizeof(add); memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { + char buffer[STRERROR_LEN]; data->state.os_errno = error = SOCKERRNO; failf(data, "getsockname() failed with errno %d: %s", - error, Curl_strerror(conn, error)); + error, Curl_strerror(error, buffer, sizeof(buffer))); return CURLE_INTERFACE_FAILED; } infof(data, "Local port: %hu\n", port); @@ -470,10 +471,12 @@ static CURLcode bindlocal(struct connectdata *conn, else break; } - - data->state.os_errno = error = SOCKERRNO; - failf(data, "bind failed with errno %d: %s", - error, Curl_strerror(conn, error)); + { + char buffer[STRERROR_LEN]; + data->state.os_errno = error = SOCKERRNO; + failf(data, "bind failed with errno %d: %s", + error, Curl_strerror(error, buffer, sizeof(buffer))); + } return CURLE_INTERFACE_FAILED; } @@ -617,10 +620,13 @@ void Curl_persistconninfo(struct connectdata *conn) conn->data->info.conn_local_port = conn->local_port; } +UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port); + /* retrieves ip address and port from a sockaddr structure. note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */ -bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, - long *port) +UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port) { unsigned short us_port; struct sockaddr_in *si = NULL; @@ -683,11 +689,12 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) return; if(!conn->bits.reuse && !conn->bits.tcp_fastopen) { + char buffer[STRERROR_LEN]; len = sizeof(struct Curl_sockaddr_storage); if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { int error = SOCKERRNO; failf(data, "getpeername() failed with errno %d: %s", - error, Curl_strerror(conn, error)); + error, Curl_strerror(error, buffer, sizeof(buffer))); return; } @@ -696,22 +703,22 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { int error = SOCKERRNO; failf(data, "getsockname() failed with errno %d: %s", - error, Curl_strerror(conn, error)); + error, Curl_strerror(error, buffer, sizeof(buffer))); return; } - if(!Curl_getaddressinfo((struct sockaddr*)&ssrem, - conn->primary_ip, &conn->primary_port)) { + if(!getaddressinfo((struct sockaddr*)&ssrem, + conn->primary_ip, &conn->primary_port)) { failf(data, "ssrem inet_ntop() failed with errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); return; } memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); - if(!Curl_getaddressinfo((struct sockaddr*)&ssloc, - conn->local_ip, &conn->local_port)) { + if(!getaddressinfo((struct sockaddr*)&ssloc, + conn->local_ip, &conn->local_port)) { failf(data, "ssloc inet_ntop() failed with errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); return; } @@ -836,9 +843,11 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(conn->tempaddr[i]) { CURLcode status; char ipaddress[MAX_IPADR_LEN]; + char buffer[STRERROR_LEN]; Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN); infof(data, "connect to %s port %ld failed: %s\n", - ipaddress, conn->port, Curl_strerror(conn, error)); + ipaddress, conn->port, + Curl_strerror(error, buffer, sizeof(buffer))); conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ? allow : allow / 2; @@ -854,8 +863,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(result) { /* no more addresses to try */ - const char *hostname; + char buffer[STRERROR_LEN]; /* if the first address family runs out of addresses to try before the happy eyeball timeout, go ahead and try the next family now */ @@ -875,13 +884,14 @@ CURLcode Curl_is_connected(struct connectdata *conn, hostname = conn->host.name; failf(data, "Failed to connect to %s port %ld: %s", - hostname, conn->port, Curl_strerror(conn, error)); + hostname, conn->port, + Curl_strerror(error, buffer, sizeof(buffer))); } return result; } -void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) +static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) { #if defined(TCP_NODELAY) #if !defined(CURL_DISABLE_VERBOSE_STRINGS) @@ -889,6 +899,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) #endif curl_socklen_t onoff = (curl_socklen_t) 1; int level = IPPROTO_TCP; + char buffer[STRERROR_LEN]; #if defined(CURL_DISABLE_VERBOSE_STRINGS) (void) conn; @@ -897,7 +908,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd) if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) infof(data, "Could not set TCP_NODELAY: %s\n", - Curl_strerror(conn, SOCKERRNO)); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); else infof(data, "TCP_NODELAY set\n"); #else @@ -917,9 +928,11 @@ static void nosigpipe(struct connectdata *conn, struct Curl_easy *data = conn->data; int onoff = 1; if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, - sizeof(onoff)) < 0) + sizeof(onoff)) < 0) { + char buffer[STRERROR_LEN]; infof(data, "Could not set SO_NOSIGPIPE: %s\n", - Curl_strerror(conn, SOCKERRNO)); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); + } } #else #define nosigpipe(x,y) Curl_nop_stmt @@ -995,6 +1008,7 @@ static CURLcode singleipconnect(struct connectdata *conn, #ifdef TCP_FASTOPEN_CONNECT int optval = 1; #endif + char buffer[STRERROR_LEN]; *sockp = CURL_SOCKET_BAD; @@ -1006,11 +1020,11 @@ static CURLcode singleipconnect(struct connectdata *conn, return CURLE_OK; /* store remote address and port used in this connection attempt */ - if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr, - ipaddress, &port)) { + if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, + ipaddress, &port)) { /* malformed address or bug in inet_ntop, try next address */ failf(data, "sa_addr inet_ntop() failed with errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); Curl_closesocket(conn, sockfd); return CURLE_OK; } @@ -1023,7 +1037,7 @@ static CURLcode singleipconnect(struct connectdata *conn, is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM; #endif if(is_tcp && data->set.tcp_nodelay) - Curl_tcpnodelay(conn, sockfd); + tcpnodelay(conn, sockfd); nosigpipe(conn, sockfd); @@ -1146,7 +1160,7 @@ static CURLcode singleipconnect(struct connectdata *conn, default: /* unknown error, fallthrough and try another address! */ infof(data, "Immediate connect fail for %s: %s\n", - ipaddress, Curl_strerror(conn, error)); + ipaddress, Curl_strerror(error, buffer, sizeof(buffer))); data->state.os_errno = error; /* connect failed */ @@ -1420,7 +1434,7 @@ void Curl_conncontrol(struct connectdata *conn, if((ctrl == CONNCTRL_STREAM) && (conn->handler->flags & PROTOPT_STREAM)) DEBUGF(infof(conn->data, "Kill stream: %s\n", reason)); - else if(closeit != conn->bits.close) { + else if((bit)closeit != conn->bits.close) { DEBUGF(infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive", reason)); conn->bits.close = closeit; /* the only place in the source code that diff --git a/lib/connect.h b/lib/connect.h index 193dc639..6a5c755c 100644 --- a/lib/connect.h +++ b/lib/connect.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, 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 @@ -76,11 +76,6 @@ void Curl_persistconninfo(struct connectdata *conn); int Curl_closesocket(struct connectdata *conn, curl_socket_t sock); /* - * Get presentation format IP address and port from a sockaddr. - */ -bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, long *port); - -/* * The Curl_sockaddr_ex structure is basically libcurl's external API * curl_sockaddr structure with enough space available to directly hold any * protocol-specific address structures. The variable declared here will be @@ -111,8 +106,6 @@ CURLcode Curl_socket(struct connectdata *conn, struct Curl_sockaddr_ex *addr, curl_socket_t *sockfd); -void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd); - /* * Curl_conncontrol() marks the end of a connection/stream. The 'closeit' * argument specifies if it is the end of a connection or a stream. diff --git a/lib/cookie.c b/lib/cookie.c index 4fb992ac..44851a52 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -528,6 +528,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) { @@ -803,8 +816,6 @@ Curl_cookie_add(struct Curl_easy *data, co->domain = strdup(ptr); if(!co->domain) badcookie = TRUE; - else if(bad_domain(co->domain)) - badcookie = TRUE; break; case 1: /* This field got its explanation on the 23rd of May 2001 by @@ -862,6 +873,11 @@ Curl_cookie_add(struct Curl_easy *data, co->name = strdup(ptr); if(!co->name) badcookie = TRUE; + /* 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); @@ -890,6 +906,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! */ @@ -908,20 +944,18 @@ Curl_cookie_add(struct Curl_easy *data, if(!noexpire) remove_expired(c); - if(domain && co->domain && !isip(co->domain)) { - int acceptable; #ifdef USE_LIBPSL + /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */ + if(domain && co->domain && !isip(co->domain)) { const psl_ctx_t *psl = Curl_psl_use(data); + int acceptable; - /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */ if(psl) { acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain); Curl_psl_release(data); } else -#endif - /* Without libpsl, do the best we can. */ - acceptable = !bad_domain(co->domain); + acceptable = !bad_domain(domain); if(!acceptable) { infof(data, "cookie '%s' dropped, domain '%s' must not " @@ -930,6 +964,7 @@ Curl_cookie_add(struct Curl_easy *data, return NULL; } } +#endif myhash = cookiehash(co->domain); clist = c->cookies[myhash]; @@ -1054,7 +1089,7 @@ Curl_cookie_add(struct Curl_easy *data, * 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) +char *Curl_get_line(char *buf, int len, FILE *input) { bool partial = FALSE; while(1) { @@ -1134,7 +1169,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]; @@ -1503,6 +1538,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) unsigned int j; struct Cookie **array; + if(!c) + /* no cookie engine alive */ + return 0; + /* at first, remove expired cookies */ remove_expired(c); diff --git a/lib/cookie.h b/lib/cookie.h index 3ee457c6..6ac4a6ac 100644 --- a/lib/cookie.h +++ b/lib/cookie.h @@ -7,7 +7,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 @@ -44,8 +44,16 @@ struct Cookie { bool livecookie; /* updated from a server, not a stored file */ bool httponly; /* true if the httponly directive is present */ int creationtime; /* time when the cookie was written */ + unsigned char prefix; /* bitmap fields indicating which prefix are set */ }; +/* + * Available cookie prefixes, as defined in + * draft-ietf-httpbis-rfc6265bis-02 + */ +#define COOKIE_PREFIX__SECURE (1<<0) +#define COOKIE_PREFIX__HOST (1<<1) + #define COOKIE_HASH_SIZE 256 struct CookieInfo { @@ -93,6 +101,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, void Curl_cookie_freelist(struct Cookie *cookies); void Curl_cookie_clearall(struct CookieInfo *cookies); void Curl_cookie_clearsess(struct CookieInfo *cookies); +char *Curl_get_line(char *buf, int len, FILE *input); #if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES) #define Curl_cookie_list(x) NULL diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index fd49679c..16c4779c 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.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 @@ -539,7 +539,7 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract) #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ defined(HAVE_FREEADDRINFO) /* - * curl_dofreeaddrinfo() + * curl_dbg_freeaddrinfo() * * This is strictly for memory tracing and are using the same style as the * family otherwise present in memdebug.c. I put these ones here since they @@ -547,23 +547,23 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract) */ void -curl_dofreeaddrinfo(struct addrinfo *freethis, - int line, const char *source) +curl_dbg_freeaddrinfo(struct addrinfo *freethis, + int line, const char *source) { + curl_dbg_log("ADDR %s:%d freeaddrinfo(%p)\n", + source, line, (void *)freethis); #ifdef USE_LWIPSOCK lwip_freeaddrinfo(freethis); #else (freeaddrinfo)(freethis); #endif - curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n", - source, line, (void *)freethis); } #endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */ #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) /* - * curl_dogetaddrinfo() + * curl_dbg_getaddrinfo() * * This is strictly for memory tracing and are using the same style as the * family otherwise present in memdebug.c. I put these ones here since they @@ -571,11 +571,11 @@ curl_dofreeaddrinfo(struct addrinfo *freethis, */ int -curl_dogetaddrinfo(const char *hostname, - const char *service, - const struct addrinfo *hints, - struct addrinfo **result, - int line, const char *source) +curl_dbg_getaddrinfo(const char *hostname, + const char *service, + const struct addrinfo *hints, + struct addrinfo **result, + int line, const char *source) { #ifdef USE_LWIPSOCK int res = lwip_getaddrinfo(hostname, service, hints, result); @@ -584,11 +584,11 @@ curl_dogetaddrinfo(const char *hostname, #endif if(0 == res) /* success */ - curl_memlog("ADDR %s:%d getaddrinfo() = %p\n", - source, line, (void *)*result); + curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n", + source, line, (void *)*result); else - curl_memlog("ADDR %s:%d getaddrinfo() failed\n", - source, line); + curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n", + source, line); return res; } #endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */ diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h index 8f6f3d10..205e121e 100644 --- a/lib/curl_addrinfo.h +++ b/lib/curl_addrinfo.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, 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 @@ -86,17 +86,14 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract); #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ defined(HAVE_FREEADDRINFO) void -curl_dofreeaddrinfo(struct addrinfo *freethis, - int line, const char *source); +curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source); #endif #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) int -curl_dogetaddrinfo(const char *hostname, - const char *service, - const struct addrinfo *hints, - struct addrinfo **result, - int line, const char *source); +curl_dbg_getaddrinfo(const char *hostname, const char *service, + const struct addrinfo *hints, struct addrinfo **result, + int line, const char *source); #endif #ifdef HAVE_GETADDRINFO diff --git a/lib/curl_config.h b/lib/curl_config.h index 2bc705cc..a714d635 100644 --- a/lib/curl_config.h +++ b/lib/curl_config.h @@ -191,9 +191,6 @@ /* Define to 1 if you have a working fcntl O_NONBLOCK function. */ #define HAVE_FCNTL_O_NONBLOCK 1 -/* Define to 1 if you have the fdopen function. */ -#define HAVE_FDOPEN 1 - /* Define to 1 if you have the `fnmatch' function. */ #define HAVE_FNMATCH 1 @@ -527,6 +524,9 @@ /* Define to 1 if you have a working POSIX-style strerror_r function. */ #define HAVE_POSIX_STRERROR_R 1 +/* Define to 1 if you have the <proto/bsdsocket.h> header file. */ +/* #undef HAVE_PROTO_BSDSOCKET_H */ + /* if you have <pthread.h> */ #define HAVE_PTHREAD_H 1 @@ -617,9 +617,6 @@ /* Define to 1 if you have the <stdint.h> header file. */ #define HAVE_STDINT_H 1 -/* Define to 1 if you have the <stdio.h> header file. */ -#define HAVE_STDIO_H 1 - /* Define to 1 if you have the <stdlib.h> header file. */ #define HAVE_STDLIB_H 1 @@ -767,9 +764,6 @@ /* Define to 1 if you have the `wolfSSLv3_client_method' function. */ /* #undef HAVE_WOLFSSLV3_CLIENT_METHOD */ -/* Define to 1 if you have the `wolfSSL_CTX_UseSupportedCurve' function. */ -/* #undef HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE */ - /* Define to 1 if you have the `wolfSSL_get_peer_certificate' function. */ /* #undef HAVE_WOLFSSL_GET_PEER_CERTIFICATE */ @@ -908,15 +902,18 @@ /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ #define TIME_WITH_SYS_TIME 1 +/* to enable alt-svc */ +/* #undef USE_ALTSVC */ + +/* if AmiSSL is in use */ +/* #undef USE_AMISSL */ + /* Define to enable c-ares support */ /* #undef USE_ARES */ /* if CyaSSL/WolfSSL is enabled */ /* #undef USE_CYASSL */ -/* to enable Apple OS native SSL/TLS support */ -/* #undef USE_DARWINSSL */ - /* if GnuTLS is enabled */ /* #undef USE_GNUTLS */ @@ -965,6 +962,9 @@ /* to enable Windows native SSL/TLS support */ /* #undef USE_SCHANNEL */ +/* enable Secure Transport */ +/* #undef USE_SECTRANSP */ + /* if you want POSIX threaded DNS lookup */ #define USE_THREADS_POSIX 1 diff --git a/lib/curl_config.h.in b/lib/curl_config.h.in index 7ab164b7..04ed02a5 100644 --- a/lib/curl_config.h.in +++ b/lib/curl_config.h.in @@ -190,9 +190,6 @@ /* Define to 1 if you have a working fcntl O_NONBLOCK function. */ #undef HAVE_FCNTL_O_NONBLOCK -/* Define to 1 if you have the fdopen function. */ -#undef HAVE_FDOPEN - /* Define to 1 if you have the `fnmatch' function. */ #undef HAVE_FNMATCH @@ -526,6 +523,9 @@ /* Define to 1 if you have a working POSIX-style strerror_r function. */ #undef HAVE_POSIX_STRERROR_R +/* Define to 1 if you have the <proto/bsdsocket.h> header file. */ +#undef HAVE_PROTO_BSDSOCKET_H + /* if you have <pthread.h> */ #undef HAVE_PTHREAD_H @@ -616,9 +616,6 @@ /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H -/* Define to 1 if you have the <stdio.h> header file. */ -#undef HAVE_STDIO_H - /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H @@ -766,9 +763,6 @@ /* Define to 1 if you have the `wolfSSLv3_client_method' function. */ #undef HAVE_WOLFSSLV3_CLIENT_METHOD -/* Define to 1 if you have the `wolfSSL_CTX_UseSupportedCurve' function. */ -#undef HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE - /* Define to 1 if you have the `wolfSSL_get_peer_certificate' function. */ #undef HAVE_WOLFSSL_GET_PEER_CERTIFICATE @@ -925,15 +919,18 @@ /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ #undef TIME_WITH_SYS_TIME +/* to enable alt-svc */ +#undef USE_ALTSVC + +/* if AmiSSL is in use */ +#undef USE_AMISSL + /* Define to enable c-ares support */ #undef USE_ARES /* if CyaSSL/WolfSSL is enabled */ #undef USE_CYASSL -/* to enable Apple OS native SSL/TLS support */ -#undef USE_DARWINSSL - /* if GnuTLS is enabled */ #undef USE_GNUTLS @@ -982,6 +979,9 @@ /* to enable Windows native SSL/TLS support */ #undef USE_SCHANNEL +/* enable Secure Transport */ +#undef USE_SECTRANSP + /* if you want POSIX threaded DNS lookup */ #undef USE_THREADS_POSIX diff --git a/lib/curl_endian.c b/lib/curl_endian.c index c25db495..b7563b3d 100644 --- a/lib/curl_endian.c +++ b/lib/curl_endian.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, 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 @@ -82,7 +82,7 @@ unsigned short Curl_read16_be(const unsigned char *buf) } /* - * Curl_write32_le() + * write32_le() * * This function converts a 32-bit integer from the native endian format, * to little endian format ready for sending down the wire. @@ -92,7 +92,7 @@ unsigned short Curl_read16_be(const unsigned char *buf) * value [in] - The 32-bit integer value. * buffer [in] - A pointer to the output buffer. */ -void Curl_write32_le(const int value, unsigned char *buffer) +static void write32_le(const int value, unsigned char *buffer) { buffer[0] = (char)(value & 0x000000FF); buffer[1] = (char)((value & 0x0000FF00) >> 8); @@ -118,7 +118,7 @@ void Curl_write64_le(const long long value, unsigned char *buffer) void Curl_write64_le(const __int64 value, unsigned char *buffer) #endif { - Curl_write32_le((int)value, buffer); - Curl_write32_le((int)(value >> 32), buffer + 4); + write32_le((int)value, buffer); + write32_le((int)(value >> 32), buffer + 4); } #endif /* CURL_SIZEOF_CURL_OFF_T > 4 */ diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c index fbfd85c4..846ecaec 100644 --- a/lib/curl_fnmatch.c +++ b/lib/curl_fnmatch.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 @@ -21,7 +21,7 @@ ***************************************************************************/ #include "curl_setup.h" - +#ifndef CURL_DISABLE_FTP #include <curl/curl.h> #include "curl_fnmatch.h" @@ -394,3 +394,5 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string) } #endif + +#endif /* if FTP is disabled */ diff --git a/lib/curl_gssapi.h b/lib/curl_gssapi.h index 9700a281..88f68dbb 100644 --- a/lib/curl_gssapi.h +++ b/lib/curl_gssapi.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2011 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2011 - 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 @@ -26,19 +26,6 @@ #include "urldata.h" #ifdef HAVE_GSSAPI - -#ifdef HAVE_GSSGNU -# include <gss.h> -#elif defined HAVE_GSSMIT - /* MIT style */ -# include <gssapi/gssapi.h> -# include <gssapi/gssapi_generic.h> -# include <gssapi/gssapi_krb5.h> -#else - /* Heimdal-style */ -# include <gssapi.h> -#endif - extern gss_OID_desc Curl_spnego_mech_oid; extern gss_OID_desc Curl_krb5_mech_oid; @@ -71,5 +58,4 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, #define GSSAUTH_P_PRIVACY 4 #endif /* HAVE_GSSAPI */ - #endif /* HEADER_CURL_GSSAPI_H */ diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c index 9eb6c43c..e7060eb2 100644 --- a/lib/curl_ntlm_core.c +++ b/lib/curl_ntlm_core.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 @@ -38,7 +38,7 @@ 3. USE_GNUTLS 4. USE_NSS 5. USE_MBEDTLS - 6. USE_DARWINSSL + 6. USE_SECTRANSP 7. USE_OS400CRYPTO 8. USE_WIN32_CRYPTO @@ -101,7 +101,7 @@ # include "curl_md4.h" # endif -#elif defined(USE_DARWINSSL) +#elif defined(USE_SECTRANSP) # include <CommonCrypto/CommonCryptor.h> # include <CommonCrypto/CommonDigest.h> @@ -290,7 +290,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, return mbedtls_des_crypt_ecb(&ctx, in, out) == 0; } -#elif defined(USE_DARWINSSL) +#elif defined(USE_SECTRANSP) static bool encrypt_des(const unsigned char *in, unsigned char *out, const unsigned char *key_56) @@ -437,7 +437,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, setup_des_key(keys + 14, &des); gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8); gcry_cipher_close(des); -#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \ +#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) encrypt_des(plaintext, results, keys); encrypt_des(plaintext, results + 8, keys + 7); @@ -501,7 +501,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, setup_des_key(pw + 7, &des); gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8); gcry_cipher_close(des); -#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \ +#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) encrypt_des(magic, lmbuffer, pw); encrypt_des(magic, lmbuffer + 8, pw + 7); @@ -591,7 +591,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, #else Curl_md4it(ntbuffer, pw, 2 * len); #endif -#elif defined(USE_DARWINSSL) +#elif defined(USE_SECTRANSP) (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer); #elif defined(USE_OS400CRYPTO) Curl_md4it(ntbuffer, pw, 2 * len); @@ -621,9 +621,9 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) /* This returns the HMAC MD5 digest */ -CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, - const unsigned char *data, unsigned int datalen, - unsigned char *output) +static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen, + const unsigned char *data, unsigned int datalen, + unsigned char *output) { HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen); @@ -668,9 +668,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, ascii_uppercase_to_unicode_le(identity, user, userlen); ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); - result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), - ntlmv2hash); - + result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), + ntlmv2hash); free(identity); return result; @@ -756,8 +755,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */ memcpy(ptr + 8, &ntlm->nonce[0], 8); - result = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, - NTLMv2_BLOB_LEN + 8, hmac_output); + result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, + NTLMv2_BLOB_LEN + 8, hmac_output); if(result) { free(ptr); return result; @@ -799,7 +798,7 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, memcpy(&data[0], challenge_server, 8); memcpy(&data[8], challenge_client, 8); - result = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); + result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); if(result) return result; diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c index a4791eb4..18ee75dd 100644 --- a/lib/curl_ntlm_wb.c +++ b/lib/curl_ntlm_wb.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 @@ -124,6 +124,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) struct passwd pw, *pw_res; char pwbuf[1024]; #endif + char buffer[STRERROR_LEN]; /* Return if communication with ntlm_auth already set up */ if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || @@ -179,13 +180,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) if(access(ntlm_auth, X_OK) != 0) { failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s", - ntlm_auth, errno, Curl_strerror(conn, errno)); + ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; } if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) { failf(conn->data, "Could not open socket pair. errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; } @@ -194,7 +195,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) sclose(sockfds[0]); sclose(sockfds[1]); failf(conn->data, "Could not fork. errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); goto done; } else if(!child_pid) { @@ -206,13 +207,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) sclose_nolog(sockfds[0]); if(dup2(sockfds[1], STDIN_FILENO) == -1) { failf(conn->data, "Could not redirect child stdin. errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); exit(1); } if(dup2(sockfds[1], STDOUT_FILENO) == -1) { failf(conn->data, "Could not redirect child stdout. errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); exit(1); } @@ -232,7 +233,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) sclose_nolog(sockfds[1]); failf(conn->data, "Could not execl(). errno %d: %s", - errno, Curl_strerror(conn, errno)); + errno, Curl_strerror(errno, buffer, sizeof(buffer))); exit(1); } diff --git a/lib/curl_path.c b/lib/curl_path.c index 68f3e44b..ad386e74 100644 --- a/lib/curl_path.c +++ b/lib/curl_path.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 @@ -22,6 +22,8 @@ #include "curl_setup.h" +#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) + #include <curl/curl.h> #include "curl_memory.h" #include "curl_path.h" @@ -193,3 +195,5 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir) Curl_safefree(*path); return CURLE_QUOTE_ERROR; } + +#endif /* if SSH is used */ diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c index f09f2f33..16b1de1a 100644 --- a/lib/curl_rtmp.c +++ b/lib/curl_rtmp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com> * * This software is licensed as described in the file COPYING, which @@ -239,17 +239,18 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done) static CURLcode rtmp_do(struct connectdata *conn, bool *done) { + struct Curl_easy *data = conn->data; RTMP *r = conn->proto.generic; if(!RTMP_ConnectStream(r, 0)) return CURLE_FAILED_INIT; if(conn->data->set.upload) { - Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize); - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_pgrsSetUploadSize(data, data->state.infilesize); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); } else - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); *done = TRUE; return CURLE_OK; } diff --git a/lib/curl_setup.h b/lib/curl_setup.h index f83e1ea4..4c3a1735 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -7,7 +7,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 @@ -310,11 +310,12 @@ #endif #ifdef __AMIGA__ -# ifndef __ixemul__ -# include <exec/types.h> -# include <exec/execbase.h> -# include <proto/exec.h> -# include <proto/dos.h> +# include <exec/types.h> +# include <exec/execbase.h> +# include <proto/exec.h> +# include <proto/dos.h> +# ifdef HAVE_PROTO_BSDSOCKET_H +# include <proto/bsdsocket.h> /* ensure bsdsocket.library use */ # define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0) # endif #endif @@ -648,7 +649,7 @@ int netware_init(void); #if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \ defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \ defined(USE_CYASSL) || defined(USE_SCHANNEL) || \ - defined(USE_DARWINSSL) || defined(USE_GSKIT) || defined(USE_MESALINK) + defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK) #define USE_SSL /* SSL support has been enabled */ #endif @@ -667,7 +668,7 @@ int netware_init(void); /* Single point where USE_NTLM definition might be defined */ #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) #if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \ - defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \ + defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ defined(USE_MBEDTLS) @@ -816,4 +817,10 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); #endif +#ifdef DEBUGBUILD +#define UNITTEST +#else +#define UNITTEST static +#endif + #endif /* HEADER_CURL_SETUP_H */ @@ -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 @@ -137,7 +137,6 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; char *path = data->state.up.path; - curl_off_t *bytecount = &data->req.bytecount; *done = TRUE; /* unconditionally */ @@ -200,8 +199,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) failf(data, "Failed sending DICT request"); return result; } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, - -1, NULL); /* no upload */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */ } else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) || strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) || @@ -247,8 +245,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) failf(data, "Failed sending DICT request"); return result; } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, - -1, NULL); /* no upload */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); } else { @@ -270,7 +267,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done) return result; } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); } } @@ -173,8 +173,12 @@ static int Curl_doh_done(struct Curl_easy *doh, CURLcode result) return 0; } -#define ERROR_CHECK_SETOPT(x,y) result = curl_easy_setopt(doh, x, y); \ - if(result) goto error +#define ERROR_CHECK_SETOPT(x,y) \ +do { \ + result = curl_easy_setopt(doh, x, y); \ + if(result) \ + goto error; \ +} WHILE_FALSE static CURLcode dohprobe(struct Curl_easy *data, struct dnsprobe *p, DNStype dnstype, @@ -242,7 +246,68 @@ static CURLcode dohprobe(struct Curl_easy *data, ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); #endif ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms); - ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L); + if(data->set.verbose) + ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L); + if(data->set.no_signal) + ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L); + + /* Inherit *some* SSL options from the user's transfer. This is a + best-guess as to which options are needed for compatibility. #3661 */ + if(data->set.ssl.falsestart) + ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L); + if(data->set.ssl.primary.verifyhost) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L); + if(data->set.proxy_ssl.primary.verifyhost) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L); + if(data->set.ssl.primary.verifypeer) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L); + if(data->set.proxy_ssl.primary.verifypeer) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L); + if(data->set.ssl.primary.verifystatus) + ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L); + if(data->set.str[STRING_SSL_CAFILE_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CAINFO, + data->set.str[STRING_SSL_CAFILE_ORIG]); + } + if(data->set.str[STRING_SSL_CAFILE_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO, + data->set.str[STRING_SSL_CAFILE_PROXY]); + } + if(data->set.str[STRING_SSL_CAPATH_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CAPATH, + data->set.str[STRING_SSL_CAPATH_ORIG]); + } + if(data->set.str[STRING_SSL_CAPATH_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH, + data->set.str[STRING_SSL_CAPATH_PROXY]); + } + if(data->set.str[STRING_SSL_CRLFILE_ORIG]) { + ERROR_CHECK_SETOPT(CURLOPT_CRLFILE, + data->set.str[STRING_SSL_CRLFILE_ORIG]); + } + if(data->set.str[STRING_SSL_CRLFILE_PROXY]) { + ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE, + data->set.str[STRING_SSL_CRLFILE_PROXY]); + } + if(data->set.ssl.certinfo) + ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L); + if(data->set.str[STRING_SSL_RANDOM_FILE]) { + ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE, + data->set.str[STRING_SSL_RANDOM_FILE]); + } + if(data->set.str[STRING_SSL_EGDSOCKET]) { + ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET, + data->set.str[STRING_SSL_EGDSOCKET]); + } + if(data->set.ssl.no_revoke) + ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + if(data->set.proxy_ssl.no_revoke) + ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE); + if(data->set.ssl.fsslctx) + ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx); + if(data->set.ssl.fsslctxp) + ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp); + doh->set.fmultidone = Curl_doh_done; doh->set.dohfor = data; /* identify for which transfer this is done */ p->easy = doh; @@ -75,6 +75,7 @@ #include "ssh.h" #include "setopt.h" #include "http_digest.h" +#include "system_win32.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -83,70 +84,6 @@ void Curl_version_init(void); -/* win32_cleanup() is for win32 socket cleanup functionality, the opposite - of win32_init() */ -static void win32_cleanup(void) -{ -#ifdef USE_WINSOCK - WSACleanup(); -#endif -#ifdef USE_WINDOWS_SSPI - Curl_sspi_global_cleanup(); -#endif -} - -/* win32_init() performs win32 socket initialization to properly setup the - stack to allow networking */ -static CURLcode win32_init(void) -{ -#ifdef USE_WINSOCK - WORD wVersionRequested; - WSADATA wsaData; - int res; - -#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) - Error IPV6_requires_winsock2 -#endif - - wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); - - res = WSAStartup(wVersionRequested, &wsaData); - - if(res != 0) - /* Tell the user that we couldn't find a usable */ - /* winsock.dll. */ - return CURLE_FAILED_INIT; - - /* Confirm that the Windows Sockets DLL supports what we need.*/ - /* Note that if the DLL supports versions greater */ - /* than wVersionRequested, it will still return */ - /* wVersionRequested in wVersion. wHighVersion contains the */ - /* highest supported version. */ - - if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || - HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { - /* Tell the user that we couldn't find a usable */ - - /* winsock.dll. */ - WSACleanup(); - return CURLE_FAILED_INIT; - } - /* The Windows Sockets DLL is acceptable. Proceed. */ -#elif defined(USE_LWIPSOCK) - lwip_init(); -#endif - -#ifdef USE_WINDOWS_SSPI - { - CURLcode result = Curl_sspi_global_init(); - if(result) - return result; - } -#endif - - return CURLE_OK; -} - /* true globals -- for curl_global_init() and curl_global_cleanup() */ static unsigned int initialized; static long init_flags; @@ -223,11 +160,12 @@ static CURLcode global_init(long flags, bool memoryfuncs) return CURLE_FAILED_INIT; } - if(flags & CURL_GLOBAL_WIN32) - if(win32_init()) { - DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); - return CURLE_FAILED_INIT; - } +#ifdef WIN32 + if(Curl_win32_init(flags)) { + DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif #ifdef __AMIGA__ if(!Curl_amiga_init()) { @@ -331,8 +269,9 @@ void curl_global_cleanup(void) Curl_ssl_cleanup(); Curl_resolver_global_cleanup(); - if(init_flags & CURL_GLOBAL_WIN32) - win32_cleanup(); +#ifdef WIN32 + Curl_win32_cleanup(init_flags); +#endif Curl_amiga_cleanup(); @@ -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 @@ -311,7 +311,7 @@ static CURLcode file_upload(struct connectdata *conn) if(result) break; - if(readcount <= 0) /* fix questionable compare error. curlvms */ + if(!readcount) break; nread = readcount; @@ -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 @@ -448,7 +448,6 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) static CURLcode InitiateTransfer(struct connectdata *conn) { struct Curl_easy *data = conn->data; - struct FTP *ftp = data->req.protop; CURLcode result = CURLE_OK; if(conn->bits.ftp_use_data_ssl) { @@ -461,24 +460,19 @@ static CURLcode InitiateTransfer(struct connectdata *conn) } if(conn->proto.ftpc.state_saved == FTP_STOR) { - *(ftp->bytecountp) = 0; - /* When we know we're uploading a specified file, we can get the file size prior to the actual upload. */ - Curl_pgrsSetUploadSize(data, data->state.infilesize); /* set the SO_SNDBUF for the secondary socket for those who need it */ Curl_sndbufset(conn->sock[SECONDARYSOCKET]); - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ - SECONDARYSOCKET, ftp->bytecountp); + Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET); } else { /* FTP download: */ - Curl_setup_transfer(conn, SECONDARYSOCKET, - conn->proto.ftpc.retr_size_saved, FALSE, - ftp->bytecountp, -1, NULL); /* no upload here */ + Curl_setup_transfer(data, SECONDARYSOCKET, + conn->proto.ftpc.retr_size_saved, FALSE, -1); } conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */ @@ -955,7 +949,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, unsigned short port_max = 0; unsigned short port; bool possibly_non_local = TRUE; - + char buffer[STRERROR_LEN]; char *addr = NULL; /* Step 1, figure out what is requested, @@ -1064,11 +1058,10 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(!host) { /* not an interface and not a host name, get default by extracting the IP from the control connection */ - sslen = sizeof(ss); if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { failf(data, "getsockname() failed: %s", - Curl_strerror(conn, SOCKERRNO) ); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); free(addr); return CURLE_FTP_PORT_FAILED; } @@ -1121,7 +1114,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, break; } if(!ai) { - failf(data, "socket failure: %s", Curl_strerror(conn, error)); + failf(data, "socket failure: %s", + Curl_strerror(error, buffer, sizeof(buffer))); return CURLE_FTP_PORT_FAILED; } @@ -1145,14 +1139,13 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, /* The requested bind address is not local. Use the address used for * the control connection instead and restart the port loop */ - infof(data, "bind(port=%hu) on non-local address failed: %s\n", port, - Curl_strerror(conn, error) ); + Curl_strerror(error, buffer, sizeof(buffer))); sslen = sizeof(ss); if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { failf(data, "getsockname() failed: %s", - Curl_strerror(conn, SOCKERRNO) ); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1162,7 +1155,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, } if(error != EADDRINUSE && error != EACCES) { failf(data, "bind(port=%hu) failed: %s", port, - Curl_strerror(conn, error) ); + Curl_strerror(error, buffer, sizeof(buffer))); Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1185,7 +1178,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, sslen = sizeof(ss); if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { failf(data, "getsockname() failed: %s", - Curl_strerror(conn, SOCKERRNO) ); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1193,7 +1186,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, /* step 4, listen on the socket */ if(listen(portsock, 1)) { - failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO)); + failf(data, "socket failure: %s", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); Curl_closesocket(conn, portsock); return CURLE_FTP_PORT_FAILED; } @@ -1658,7 +1652,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn, infof(data, "File already completely uploaded\n"); /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); /* Set ->transfer so that we won't get any error in * ftp_done() because we didn't transfer anything! */ @@ -2230,7 +2224,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn, if(ftp->downloadsize == 0) { /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); infof(data, "File already completely downloaded\n"); /* Set ->transfer so that we won't get any error in ftp_done() @@ -3308,33 +3302,33 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, ; else if(data->set.upload) { if((-1 != data->state.infilesize) && - (data->state.infilesize != *ftp->bytecountp) && + (data->state.infilesize != data->req.writebytecount) && !data->set.crlf && (ftp->transfer == FTPTRANSFER_BODY)) { failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T " out of %" CURL_FORMAT_CURL_OFF_T " bytes)", - *ftp->bytecountp, data->state.infilesize); + data->req.bytecount, data->state.infilesize); result = CURLE_PARTIAL_FILE; } } else { if((-1 != data->req.size) && - (data->req.size != *ftp->bytecountp) && + (data->req.size != data->req.bytecount) && #ifdef CURL_DO_LINEEND_CONV /* Most FTP servers don't adjust their file SIZE response for CRLFs, so * we'll check to see if the discrepancy can be explained by the number * of CRLFs we've changed to LFs. */ ((data->req.size + data->state.crlf_conversions) != - *ftp->bytecountp) && + data->req.bytecount) && #endif /* CURL_DO_LINEEND_CONV */ - (data->req.maxdownload != *ftp->bytecountp)) { + (data->req.maxdownload != data->req.bytecount)) { failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T - " bytes", *ftp->bytecountp); + " bytes", data->req.bytecount); result = CURLE_PARTIAL_FILE; } else if(!ftpc->dont_check && - !*ftp->bytecountp && + !data->req.bytecount && (data->req.size>0)) { failf(data, "No data was received!"); result = CURLE_FTP_COULDNT_RETR_FILE; @@ -3629,7 +3623,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) if(!result && (ftp->transfer != FTPTRANSFER_BODY)) /* no data to transfer. FIX: it feels like a kludge to have this here too! */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); if(!ftpc->wait_data_conn) { /* no waiting for the data connection so this is now complete */ @@ -4308,7 +4302,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn, if(ftp->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); else if(!connected) /* since we didn't connect now, we want do_more to get called */ conn->bits.do_more = TRUE; @@ -4395,7 +4389,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn) return CURLE_OUT_OF_MEMORY; ftp->path = &data->state.up.path[1]; /* don't include the initial slash */ - data->state.slash_removed = TRUE; /* we've skipped the slash */ /* FTP URLs support an extension like ";type=<typecode>" that * we'll try to get now! */ @@ -4428,7 +4421,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn) } /* get some initial data into the ftp struct */ - ftp->bytecountp = &conn->data->req.bytecount; ftp->transfer = FTPTRANSFER_BODY; ftp->downloadsize = 0; @@ -7,7 +7,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 @@ -102,7 +102,6 @@ typedef enum { perhaps the Curl_easy is changed between the times the connection is used. */ struct FTP { - curl_off_t *bytecountp; char *user; /* user name string */ char *passwd; /* password string */ char *path; /* points to the urlpieces struct field */ diff --git a/lib/getinfo.c b/lib/getinfo.c index 19de657d..e118da80 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -163,10 +163,10 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, *param_longp = (long)data->info.filetime; break; case CURLINFO_HEADER_SIZE: - *param_longp = data->info.header_size; + *param_longp = (long)data->info.header_size; break; case CURLINFO_REQUEST_SIZE: - *param_longp = data->info.request_size; + *param_longp = (long)data->info.request_size; break; case CURLINFO_SSL_VERIFYRESULT: *param_longp = data->set.ssl.certverifyresult; diff --git a/lib/gopher.c b/lib/gopher.c index 485b4b79..b296c62d 100644 --- a/lib/gopher.c +++ b/lib/gopher.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 @@ -78,8 +78,6 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - - curl_off_t *bytecount = &data->req.bytecount; char *gopherpath; char *path = data->state.up.path; char *query = data->state.up.query; @@ -90,7 +88,10 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) *done = TRUE; /* unconditionally */ - if(path && query) + /* path is guaranteed non-NULL */ + DEBUGASSERT(path); + + if(query) gopherpath = aprintf("%s?%s", path, query); else gopherpath = strdup(path); @@ -167,8 +168,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done) if(result) return result; - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, - -1, NULL); /* no upload */ + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); return CURLE_OK; } #endif /*CURL_DISABLE_GOPHER*/ diff --git a/lib/hostasyn.c b/lib/hostasyn.c index 6ff60ba6..99d872b3 100644 --- a/lib/hostasyn.c +++ b/lib/hostasyn.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 @@ -85,14 +85,14 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn, dns = Curl_cache_addr(data, ai, conn->async.hostname, conn->async.port); + if(data->share) + Curl_share_unlock(data, CURL_LOCK_DATA_DNS); + if(!dns) { /* failed to store, cleanup and return error */ Curl_freeaddrinfo(ai); result = CURLE_OUT_OF_MEMORY; } - - if(data->share) - Curl_share_unlock(data, CURL_LOCK_DATA_DNS); } else { result = CURLE_OUT_OF_MEMORY; diff --git a/lib/hostip.c b/lib/hostip.c index 89b88e93..7909141c 100644 --- a/lib/hostip.c +++ b/lib/hostip.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 @@ -73,6 +73,8 @@ #define USE_ALARM_TIMEOUT #endif +#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */ + /* * hostip.c explained * ================== @@ -198,23 +200,19 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize) } /* - * Return a hostcache id string for the provided host + port, to be used by - * the DNS caching. + * Create a hostcache id string for the provided host + port, to be used by + * the DNS caching. Without alloc. */ -static char * -create_hostcache_id(const char *name, int port) +static void +create_hostcache_id(const char *name, int port, char *ptr, size_t buflen) { - /* create and return the new allocated entry */ - char *id = aprintf("%s:%d", name, port); - char *ptr = id; - if(ptr) { - /* lower case the name part */ - while(*ptr && (*ptr != ':')) { - *ptr = (char)TOLOWER(*ptr); - ptr++; - } - } - return id; + size_t len = strlen(name); + if(len > (buflen - 7)) + len = buflen - 7; + /* store and lower case the name */ + while(len--) + *ptr++ = (char)TOLOWER(*name++); + msnprintf(ptr, 7, ":%u", port); } struct hostcache_prune_data { @@ -296,17 +294,13 @@ fetch_addr(struct connectdata *conn, const char *hostname, int port) { - char *entry_id = NULL; struct Curl_dns_entry *dns = NULL; size_t entry_len; struct Curl_easy *data = conn->data; + char entry_id[MAX_HOSTCACHE_LEN]; /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) - return dns; - + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); entry_len = strlen(entry_id); /* See if its already in our dns cache */ @@ -314,18 +308,7 @@ fetch_addr(struct connectdata *conn, /* No entry found in cache, check if we might have a wildcard entry */ if(!dns && data->change.wildcard_resolve) { - /* - * Free the previous entry_id before requesting a new one to avoid leaking - * memory - */ - free(entry_id); - - entry_id = create_hostcache_id("*", port); - - /* If we can't create the entry id, fail */ - if(!entry_id) - return dns; - + create_hostcache_id("*", port, entry_id, sizeof(entry_id)); entry_len = strlen(entry_id); /* See if it's already in our dns cache */ @@ -346,9 +329,6 @@ fetch_addr(struct connectdata *conn, } } - /* free the allocated entry_id again */ - free(entry_id); - return dns; } @@ -388,6 +368,9 @@ Curl_fetch_addr(struct connectdata *conn, return dns; } +UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, + Curl_addrinfo **addr); + /* * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo' * struct by re-linking its linked list. @@ -400,7 +383,8 @@ Curl_fetch_addr(struct connectdata *conn, * * @unittest: 1608 */ -CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr) +UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, + Curl_addrinfo **addr) { CURLcode result = CURLE_OK; const int num_addrs = Curl_num_addresses(*addr); @@ -467,7 +451,7 @@ Curl_cache_addr(struct Curl_easy *data, const char *hostname, int port) { - char *entry_id; + char entry_id[MAX_HOSTCACHE_LEN]; size_t entry_len; struct Curl_dns_entry *dns; struct Curl_dns_entry *dns2; @@ -479,20 +463,16 @@ Curl_cache_addr(struct Curl_easy *data, return NULL; } - /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) - return NULL; - entry_len = strlen(entry_id); - /* Create a new cache entry */ dns = calloc(1, sizeof(struct Curl_dns_entry)); if(!dns) { - free(entry_id); return NULL; } + /* Create an entry id, based upon the hostname and port */ + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); + entry_len = strlen(entry_id); + dns->inuse = 1; /* the cache has the first reference */ dns->addr = addr; /* this is the address(es) */ time(&dns->timestamp); @@ -504,16 +484,11 @@ Curl_cache_addr(struct Curl_easy *data, (void *)dns); if(!dns2) { free(dns); - free(entry_id); return NULL; } dns = dns2; dns->inuse++; /* mark entry as in-use */ - - /* free the allocated entry_id */ - free(entry_id); - return dns; } @@ -568,7 +543,7 @@ int Curl_resolv(struct connectdata *conn, /* The entry was not in the cache. Resolve it to IP address */ Curl_addrinfo *addr; - int respwait; + int respwait = 0; /* Check what IP specifics the app has requested and if we can provide it. * If not, bail out. */ @@ -896,10 +871,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) data->change.wildcard_resolve = false; for(hostp = data->change.resolve; hostp; hostp = hostp->next) { + char entry_id[MAX_HOSTCACHE_LEN]; if(!hostp->data) continue; if(hostp->data[0] == '-') { - char *entry_id; size_t entry_len; if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { @@ -909,12 +884,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) } /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) { - return CURLE_OUT_OF_MEMORY; - } - + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); entry_len = strlen(entry_id); if(data->share) @@ -925,14 +895,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); - - /* free the allocated entry_id again */ - free(entry_id); } else { struct Curl_dns_entry *dns; Curl_addrinfo *head = NULL, *tail = NULL; - char *entry_id; size_t entry_len; char address[64]; #if !defined(CURL_DISABLE_VERBOSE_STRINGS) @@ -1028,12 +994,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) } /* Create an entry id, based upon the hostname and port */ - entry_id = create_hostcache_id(hostname, port); - /* If we can't create the entry id, fail */ - if(!entry_id) { - Curl_freeaddrinfo(head); - return CURLE_OUT_OF_MEMORY; - } + create_hostcache_id(hostname, port, entry_id, sizeof(entry_id)); entry_len = strlen(entry_id); if(data->share) @@ -1054,8 +1015,6 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1); } - /* free the allocated entry_id again */ - free(entry_id); /* put this new host in the cache */ dns = Curl_cache_addr(data, head, hostname, port); diff --git a/lib/hostip.h b/lib/hostip.h index 29fd1ef7..cd43882a 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -7,7 +7,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 @@ -179,16 +179,6 @@ Curl_fetch_addr(struct connectdata *conn, int port); /* - * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo' - * struct by re-linking its linked list. - * - * The addr argument should be the address of a pointer to the head node of a - * `Curl_addrinfo` list and it will be modified to point to the new head after - * shuffling. - */ -CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr); - -/* * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. * * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. diff --git a/lib/hostip6.c b/lib/hostip6.c index e06d0343..fb2f35ce 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.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 @@ -101,14 +101,15 @@ static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai) { printf("dump_addrinfo:\n"); for(; ai; ai = ai->ai_next) { - char buf[INET6_ADDRSTRLEN]; - + char buf[INET6_ADDRSTRLEN]; + char buffer[STRERROR_LEN]; printf(" fam %2d, CNAME %s, ", ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>"); if(Curl_printable_address(ai, buf, sizeof(buf))) printf("%s\n", buf); else - printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO)); + printf("failed; %s\n", + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); } } #else @@ -77,6 +77,7 @@ #include "http2.h" #include "connect.h" #include "strdup.h" +#include "altsvc.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -102,13 +103,14 @@ static int https_getsock(struct connectdata *conn, #else #define https_connecting(x,y) CURLE_COULDNT_CONNECT #endif +static CURLcode http_setup_conn(struct connectdata *conn); /* * HTTP handler interface. */ const struct Curl_handler Curl_handler_http = { "HTTP", /* scheme */ - Curl_http_setup_conn, /* setup_connection */ + http_setup_conn, /* setup_connection */ Curl_http, /* do_it */ Curl_http_done, /* done */ ZERO_NULL, /* do_more */ @@ -133,7 +135,7 @@ const struct Curl_handler Curl_handler_http = { */ const struct Curl_handler Curl_handler_https = { "HTTPS", /* scheme */ - Curl_http_setup_conn, /* setup_connection */ + http_setup_conn, /* setup_connection */ Curl_http, /* do_it */ Curl_http_done, /* done */ ZERO_NULL, /* do_more */ @@ -153,7 +155,7 @@ const struct Curl_handler Curl_handler_https = { }; #endif -CURLcode Curl_http_setup_conn(struct connectdata *conn) +static CURLcode http_setup_conn(struct connectdata *conn) { /* allocate the HTTP-specific struct for the Curl_easy, only to survive during this request */ @@ -415,7 +417,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) break; } - bytessent = http->writebytecount; + bytessent = data->req.writebytecount; if(conn->bits.authneg) { /* This is a state where we are known to be negotiating and we don't send @@ -479,8 +481,36 @@ static CURLcode http_perhapsrewind(struct connectdata *conn) (curl_off_t)(expectsend - bytessent)); } #endif +#if defined(USE_SPNEGO) + /* There is still data left to send */ + if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) || + (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) { + if(((expectsend - bytessent) < 2000) || + (conn->negotiate.state != GSS_AUTHNONE) || + (conn->proxyneg.state != GSS_AUTHNONE)) { + /* The NEGOTIATE-negotiation has started *OR* + there is just a little (<2K) data left to send, keep on sending. */ + + /* rewind data when completely done sending! */ + if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) { + conn->bits.rewindaftersend = TRUE; + infof(data, "Rewind stream after send\n"); + } + + return CURLE_OK; + } + + if(conn->bits.close) + /* this is already marked to get closed */ + return CURLE_OK; - /* This is not NTLM or many bytes left to send: close */ + infof(data, "NEGOTIATE send, close instead of sending %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + (curl_off_t)(expectsend - bytessent)); + } +#endif + + /* This is not NEGOTIATE/NTLM or many bytes left to send: close */ streamclose(conn, "Mid-auth HTTP and much data left to send"); data->req.size = 0; /* don't download any more than 0 bytes */ @@ -598,10 +628,6 @@ output_auth_headers(struct connectdata *conn, #if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO) struct Curl_easy *data = conn->data; #endif -#ifdef USE_SPNEGO - struct negotiatedata *negdata = proxy ? - &data->state.proxyneg : &data->state.negotiate; -#endif #ifdef CURL_DISABLE_CRYPTO_AUTH (void)request; @@ -609,15 +635,11 @@ output_auth_headers(struct connectdata *conn, #endif #ifdef USE_SPNEGO - negdata->state = GSS_AUTHNONE; - if((authstatus->picked == CURLAUTH_NEGOTIATE) && - negdata->context && !GSS_ERROR(negdata->status)) { + if((authstatus->picked == CURLAUTH_NEGOTIATE)) { auth = "Negotiate"; result = Curl_output_negotiate(conn, proxy); if(result) return result; - authstatus->done = TRUE; - negdata->state = GSS_AUTHSENT; } else #endif @@ -750,7 +772,7 @@ Curl_http_output_auth(struct connectdata *conn, #ifndef CURL_DISABLE_PROXY /* Send proxy authentication header if needed */ if(conn->bits.httpproxy && - (conn->bits.tunnel_proxy == proxytunnel)) { + (conn->bits.tunnel_proxy == (bit)proxytunnel)) { result = output_auth_headers(conn, authproxy, request, path, TRUE); if(result) return result; @@ -794,7 +816,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, #ifdef USE_SPNEGO struct negotiatedata *negdata = proxy? - &data->state.proxyneg:&data->state.negotiate; + &conn->proxyneg:&conn->negotiate; #endif unsigned long *availp; struct auth *authp; @@ -833,21 +855,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, authp->avail |= CURLAUTH_NEGOTIATE; if(authp->picked == CURLAUTH_NEGOTIATE) { - if(negdata->state == GSS_AUTHSENT || - negdata->state == GSS_AUTHNONE) { - CURLcode result = Curl_input_negotiate(conn, proxy, auth); - if(!result) { - DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->change.url); - if(!data->req.newurl) - return CURLE_OUT_OF_MEMORY; - data->state.authproblem = FALSE; - /* we received a GSS auth token and we dealt with it fine */ - negdata->state = GSS_AUTHRECV; - } - else - data->state.authproblem = TRUE; + CURLcode result = Curl_input_negotiate(conn, proxy, auth); + if(!result) { + DEBUGASSERT(!data->req.newurl); + data->req.newurl = strdup(data->change.url); + if(!data->req.newurl) + return CURLE_OUT_OF_MEMORY; + data->state.authproblem = FALSE; + /* we received a GSS auth token and we dealt with it fine */ + negdata->state = GSS_AUTHRECV; } + else + data->state.authproblem = TRUE; } } } @@ -1117,14 +1136,13 @@ void Curl_add_buffer_free(Curl_send_buffer **inp) CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, struct connectdata *conn, - /* add the number of sent bytes to this - counter */ - long *bytes_written, + /* add the number of sent bytes to this + counter */ + curl_off_t *bytes_written, - /* how much of the buffer contains body data */ + /* how much of the buffer contains body data */ size_t included_body_bytes, int socketindex) - { ssize_t amount; CURLcode result; @@ -1220,7 +1238,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, if(http) { /* if we sent a piece of the body here, up the byte counter for it accordingly */ - http->writebytecount += bodylen; + data->req.writebytecount += bodylen; + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); if((size_t)amount != size) { /* The whole request could not be sent in one system call. We must @@ -1553,20 +1572,6 @@ CURLcode Curl_http_done(struct connectdata *conn, Curl_unencode_cleanup(conn); -#ifdef USE_SPNEGO - if(data->state.proxyneg.state == GSS_AUTHSENT || - data->state.negotiate.state == GSS_AUTHSENT) { - /* add forbid re-use if http-code != 401/407 as a WA only needed for - * 401/407 that signal auth failure (empty) otherwise state will be RECV - * with current code. - * Do not close CONNECT_ONLY connections. */ - if((data->req.httpcode != 401) && (data->req.httpcode != 407) && - !data->set.connect_only) - streamclose(conn, "Negotiate transfer completed"); - Curl_cleanup_negotiate(data); - } -#endif - /* set the proper values (possibly modified on POST) */ conn->seek_func = data->set.seek_func; /* restore */ conn->seek_client = data->set.seek_client; /* restore */ @@ -1582,16 +1587,6 @@ CURLcode Curl_http_done(struct connectdata *conn, Curl_mime_cleanpart(&http->form); - switch(data->set.httpreq) { - case HTTPREQ_PUT: - case HTTPREQ_POST_FORM: - case HTTPREQ_POST_MIME: - data->req.bytecount = http->readbytecount + http->writebytecount; - break; - default: - break; - } - if(status) return status; @@ -1599,7 +1594,7 @@ CURLcode Curl_http_done(struct connectdata *conn, entire operation is complete */ !conn->bits.retry && !data->set.connect_only && - (http->readbytecount + + (data->req.bytecount + data->req.headerbytecount - data->req.deductheadercount) <= 0) { /* If this connection isn't simply closed to be retried, AND nothing was @@ -1789,9 +1784,16 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, } else { if(*(--ptr) == ';') { - /* send no-value custom header if terminated by semicolon */ - *ptr = ':'; - semicolonp = ptr; + /* copy the source */ + semicolonp = strdup(headers->data); + if(!semicolonp) { + Curl_add_buffer_free(&req_buffer); + return CURLE_OUT_OF_MEMORY; + } + /* put a colon where the semicolon is */ + semicolonp[ptr - headers->data] = ':'; + /* point at the colon */ + optr = &semicolonp [ptr - headers->data]; } } ptr = optr; @@ -1807,36 +1809,37 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, if(*ptr || semicolonp) { /* only send this if the contents was non-blank or done special */ CURLcode result = CURLE_OK; + char *compare = semicolonp ? semicolonp : headers->data; if(conn->allocptr.host && /* a Host: header was sent already, don't pass on any custom Host: header as that will produce *two* in the same request! */ - checkprefix("Host:", headers->data)) + checkprefix("Host:", compare)) ; else if(data->set.httpreq == HTTPREQ_POST_FORM && /* this header (extended by formdata.c) is sent later */ - checkprefix("Content-Type:", headers->data)) + checkprefix("Content-Type:", compare)) ; else if(data->set.httpreq == HTTPREQ_POST_MIME && /* this header is sent later */ - checkprefix("Content-Type:", headers->data)) + checkprefix("Content-Type:", compare)) ; else if(conn->bits.authneg && /* while doing auth neg, don't allow the custom length since we will force length zero then */ - checkprefix("Content-Length:", headers->data)) + checkprefix("Content-Length:", compare)) ; else if(conn->allocptr.te && /* when asking for Transfer-Encoding, don't pass on a custom Connection: */ - checkprefix("Connection:", headers->data)) + checkprefix("Connection:", compare)) ; else if((conn->httpversion == 20) && - checkprefix("Transfer-Encoding:", headers->data)) + checkprefix("Transfer-Encoding:", compare)) /* HTTP/2 doesn't support chunked requests */ ; - else if((checkprefix("Authorization:", headers->data) || - checkprefix("Cookie:", headers->data)) && + else if((checkprefix("Authorization:", compare) || + checkprefix("Cookie:", compare)) && /* be careful of sending this potentially sensitive header to other hosts */ (data->state.this_is_a_follow && @@ -1845,10 +1848,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, !strcasecompare(data->state.first_host, conn->host.name))) ; else { - result = Curl_add_bufferf(&req_buffer, "%s\r\n", headers->data); + result = Curl_add_bufferf(&req_buffer, "%s\r\n", compare); } if(semicolonp) - *semicolonp = ';'; /* put back the semicolon */ + free(semicolonp); if(result) return result; } @@ -2000,7 +2003,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) data->state.first_remote_port = conn->remote_port; } - http->writebytecount = http->readbytecount = 0; if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) && data->set.upload) { @@ -2061,7 +2063,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) return result; } - if((data->state.authhost.multipass || data->state.authproxy.multipass) && + if(((data->state.authhost.multipass && !data->state.authhost.done) + || (data->state.authproxy.multipass && !data->state.authproxy.done)) && (httpreq != HTTPREQ_GET) && (httpreq != HTTPREQ_HEAD)) { /* Auth is required and we are not authenticated yet. Make a PUT or POST @@ -2697,9 +2700,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending PUT request"); else /* prepare for transfer */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, postsize?FIRSTSOCKET:-1, - postsize?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + postsize?FIRSTSOCKET:-1); if(result) return result; break; @@ -2719,12 +2721,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending POST request"); else /* setup variables for the upcoming transfer */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); break; } - postsize = http->postsize; + data->state.infilesize = postsize = http->postsize; /* We only set Content-Length and allow a custom Content-Length if we don't upload data chunked, as RFC2616 forbids us to set both @@ -2788,9 +2789,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending POST request"); else /* prepare for transfer */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, postsize?FIRSTSOCKET:-1, - postsize?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + postsize?FIRSTSOCKET:-1); if(result) return result; @@ -2944,9 +2944,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) if(result) failf(data, "Failed sending HTTP POST request"); else - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postdata?FIRSTSOCKET:-1); break; default: @@ -2962,33 +2961,30 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) failf(data, "Failed sending HTTP request"); else /* HTTP GET/HEAD download: */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - http->postdata?FIRSTSOCKET:-1, - http->postdata?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, + http->postdata?FIRSTSOCKET:-1); } if(result) return result; - if(http->writebytecount) { + if(data->req.writebytecount) { /* if a request-body has been sent off, we make sure this progress is noted properly */ - Curl_pgrsSetUploadCounter(data, http->writebytecount); + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; - if(http->writebytecount >= postsize) { + if(data->req.writebytecount >= postsize) { /* already sent the entire request body, mark the "upload" as complete */ infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n", - http->writebytecount, postsize); + data->req.writebytecount, postsize); data->req.upload_done = TRUE; data->req.keepon &= ~KEEP_SEND; /* we're done writing */ data->req.exp100 = EXP100_SEND_DATA; /* already sent */ Curl_expire_done(data, EXPIRE_100_TIMEOUT); } - else - data->req.writebytecount = http->writebytecount; } if((conn->httpversion == 20) && data->req.upload_chunky) @@ -3383,7 +3379,24 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, data->state.authproblem = TRUE; } #endif - +#if defined(USE_SPNEGO) + if(conn->bits.close && + (((data->req.httpcode == 401) && + (conn->negotiate.state == GSS_AUTHRECV)) || + ((data->req.httpcode == 407) && + (conn->proxyneg.state == GSS_AUTHRECV)))) { + infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n"); + data->state.authproblem = TRUE; + } + if((conn->negotiate.state == GSS_AUTHDONE) && + (data->req.httpcode != 401)) { + conn->negotiate.state = GSS_AUTHSUCC; + } + if((conn->proxyneg.state == GSS_AUTHDONE) && + (data->req.httpcode != 407)) { + conn->proxyneg.state = GSS_AUTHSUCC; + } +#endif /* * When all the headers have been parsed, see if we should give * up and return an error. @@ -3960,6 +3973,22 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, if(result) return result; } + #ifdef USE_SPNEGO + else if(checkprefix("Persistent-Auth", k->p)) { + struct negotiatedata *negdata = &conn->negotiate; + struct auth *authp = &data->state.authhost; + if(authp->picked == CURLAUTH_NEGOTIATE) { + char *persistentauth = Curl_copy_header_value(k->p); + if(!persistentauth) + return CURLE_OUT_OF_MEMORY; + negdata->noauthpersist = checkprefix("false", persistentauth); + negdata->havenoauthpersist = TRUE; + infof(data, "Negotiate: noauthpersist -> %d, header part: %s", + negdata->noauthpersist, persistentauth); + free(persistentauth); + } + } + #endif else if((k->httpcode >= 300 && k->httpcode < 400) && checkprefix("Location:", k->p) && !data->req.location) { @@ -3987,6 +4016,27 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, } } } +#ifdef USE_ALTSVC + /* If enabled, the header is incoming and this is over HTTPS */ + else if(data->asi && checkprefix("Alt-Svc:", k->p) && + ((conn->handler->flags & PROTOPT_SSL) || +#ifdef CURLDEBUG + /* allow debug builds to circumvent the HTTPS restriction */ + getenv("CURL_ALTSVC_HTTP") +#else + 0 +#endif + )) { + /* the ALPN of the current request */ + enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1; + result = Curl_altsvc_parse(data, data->asi, + &k->p[ strlen("Alt-Svc:") ], + id, conn->host.name, + curlx_uitous(conn->remote_port)); + if(result) + return result; + } +#endif else if(conn->handler->protocol & CURLPROTO_RTSP) { result = Curl_rtsp_parseheader(conn, k->p); if(result) @@ -7,7 +7,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 @@ -65,7 +65,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr, size_t size) WARN_UNUSED_RESULT; CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, struct connectdata *conn, - long *bytes_written, + curl_off_t *bytes_written, size_t included_body_bytes, int socketindex); @@ -139,8 +139,6 @@ struct HTTP { const char *p_pragma; /* Pragma: string */ const char *p_accept; /* Accept: string */ - curl_off_t readbytecount; - curl_off_t writebytecount; /* For FORM posting */ curl_mimepart form; diff --git a/lib/http2.c b/lib/http2.c index 3b8088df..b5c53cdf 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -357,7 +357,7 @@ int Curl_http2_ver(char *p, size_t len) https://tools.ietf.org/html/rfc7540#page-77 nghttp2_error_code enums are identical. */ -const char *Curl_http2_strerror(uint32_t err) +static const char *http2_strerror(uint32_t err) { #ifndef NGHTTP2_HAS_HTTP2_STRERROR const char *str[] = { @@ -618,6 +618,18 @@ static int push_promise(struct Curl_easy *data, return rv; } +/* + * multi_connchanged() is called to tell that there is a connection in + * this multi handle that has changed state (pipelining become possible, the + * number of allowed streams changed or similar), and a subsequent use of this + * multi handle should move CONNECT_PEND handles back to CONNECT to have them + * retry. + */ +static void multi_connchanged(struct Curl_multi *multi) +{ + multi->recheckstate = TRUE; +} + static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, void *userp) { @@ -650,7 +662,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, infof(conn->data, "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n", httpc->settings.max_concurrent_streams); - Curl_multi_connchanged(conn->data->multi); + multi_connchanged(conn->data->multi); } } return 0; @@ -837,7 +849,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, return 0; } H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n", - Curl_http2_strerror(error_code), error_code, stream_id)); + http2_strerror(error_code), error_code, stream_id)); stream = data_s->req.protop; if(!stream) return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -957,6 +969,28 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(frame->hd.type == NGHTTP2_PUSH_PROMISE) { char *h; + if(!strcmp(":authority", (const char *)name)) { + /* psuedo headers are lower case */ + int rc = 0; + char *check = aprintf("%s:%d", conn->host.name, conn->remote_port); + if(!check) + /* no memory */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + if(!Curl_strcasecompare(check, (const char *)value)) { + /* This is push is not for the same authority that was asked for in + * the URL. RFC 7540 section 8.2 says: "A client MUST treat a + * PUSH_PROMISE for which the server is not authoritative as a stream + * error of type PROTOCOL_ERROR." + */ + (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + stream_id, NGHTTP2_PROTOCOL_ERROR); + rc = NGHTTP2_ERR_CALLBACK_FAILURE; + } + free(check); + if(rc) + return rc; + } + if(!stream->push_headers) { stream->push_headers_alloc = 10; stream->push_headers = malloc(stream->push_headers_alloc * @@ -1197,7 +1231,7 @@ void Curl_http2_done(struct connectdata *conn, bool premature) /* * Initialize nghttp2 for a Curl connection */ -CURLcode Curl_http2_init(struct connectdata *conn) +static CURLcode http2_init(struct connectdata *conn) { if(!conn->proto.httpc.h2) { int rc; @@ -1431,7 +1465,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, } else if(httpc->error_code != NGHTTP2_NO_ERROR) { failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)", - stream->stream_id, Curl_http2_strerror(httpc->error_code), + stream->stream_id, http2_strerror(httpc->error_code), httpc->error_code); *err = CURLE_HTTP2_STREAM; return -1; @@ -2141,7 +2175,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn) else conn->handler = &Curl_handler_http2; - result = Curl_http2_init(conn); + result = http2_init(conn); if(result) { Curl_add_buffer_free(&stream->header_recvbuf); return result; @@ -2163,7 +2197,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn) conn->bundle->multiuse = BUNDLE_MULTIPLEX; infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n"); - Curl_multi_connchanged(conn->data->multi); + multi_connchanged(conn->data->multi); return CURLE_OK; } diff --git a/lib/http2.h b/lib/http2.h index 67db3dff..db6217b1 100644 --- a/lib/http2.h +++ b/lib/http2.h @@ -7,7 +7,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 @@ -63,7 +63,6 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data); /* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */ bool Curl_h2_http_1_1_error(struct connectdata *conn); #else /* USE_NGHTTP2 */ -#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c index 2a97707e..9415236f 100644 --- a/lib/http_negotiate.c +++ b/lib/http_negotiate.c @@ -56,7 +56,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, service = data->set.str[STRING_PROXY_SERVICE_NAME] ? data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; host = conn->http_proxy.host.name; - neg_ctx = &data->state.proxyneg; + neg_ctx = &conn->proxyneg; } else { userp = conn->user; @@ -64,7 +64,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, service = data->set.str[STRING_SERVICE_NAME] ? data->set.str[STRING_SERVICE_NAME] : "HTTP"; host = conn->host.name; - neg_ctx = &data->state.negotiate; + neg_ctx = &conn->negotiate; } /* Not set means empty */ @@ -80,11 +80,16 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, header++; len = strlen(header); + neg_ctx->havenegdata = len != 0; if(!len) { - /* Is this the first call in a new negotiation? */ - if(neg_ctx->context) { - /* The server rejected our authentication and hasn't suppled any more + if(neg_ctx->state == GSS_AUTHSUCC) { + infof(conn->data, "Negotiate auth restarted\n"); + Curl_cleanup_negotiate(conn); + } + else if(neg_ctx->state != GSS_AUTHNONE) { + /* The server rejected our authentication and hasn't supplied any more negotiation mechanisms */ + Curl_cleanup_negotiate(conn); return CURLE_LOGIN_DENIED; } } @@ -106,38 +111,96 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) { - struct negotiatedata *neg_ctx = proxy ? &conn->data->state.proxyneg : - &conn->data->state.negotiate; + struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg : + &conn->negotiate; + struct auth *authp = proxy ? &conn->data->state.authproxy : + &conn->data->state.authhost; char *base64 = NULL; size_t len = 0; char *userp; CURLcode result; - result = Curl_auth_create_spnego_message(conn->data, neg_ctx, &base64, &len); - if(result) - return result; + authp->done = FALSE; + + if(neg_ctx->state == GSS_AUTHRECV) { + if(neg_ctx->havenegdata) { + neg_ctx->havemultiplerequests = TRUE; + } + } + else if(neg_ctx->state == GSS_AUTHSUCC) { + if(!neg_ctx->havenoauthpersist) { + neg_ctx->noauthpersist = !neg_ctx->havemultiplerequests; + } + } - userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", - base64); + if(neg_ctx->noauthpersist || + (neg_ctx->state != GSS_AUTHDONE && neg_ctx->state != GSS_AUTHSUCC)) { - if(proxy) { - Curl_safefree(conn->allocptr.proxyuserpwd); - conn->allocptr.proxyuserpwd = userp; + if(neg_ctx->noauthpersist && neg_ctx->state == GSS_AUTHSUCC) { + infof(conn->data, "Curl_output_negotiate, " + "no persistent authentication: cleanup existing context"); + Curl_auth_spnego_cleanup(neg_ctx); + } + if(!neg_ctx->context) { + result = Curl_input_negotiate(conn, proxy, "Negotiate"); + if(result) + return result; + } + + result = Curl_auth_create_spnego_message(conn->data, + neg_ctx, &base64, &len); + if(result) + return result; + + userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", + base64); + + if(proxy) { + Curl_safefree(conn->allocptr.proxyuserpwd); + conn->allocptr.proxyuserpwd = userp; + } + else { + Curl_safefree(conn->allocptr.userpwd); + conn->allocptr.userpwd = userp; + } + + free(base64); + + if(userp == NULL) { + return CURLE_OUT_OF_MEMORY; + } + + neg_ctx->state = GSS_AUTHSENT; + #ifdef HAVE_GSSAPI + if(neg_ctx->status == GSS_S_COMPLETE || + neg_ctx->status == GSS_S_CONTINUE_NEEDED) { + neg_ctx->state = GSS_AUTHDONE; + } + #else + #ifdef USE_WINDOWS_SSPI + if(neg_ctx->status == SEC_E_OK || + neg_ctx->status == SEC_I_CONTINUE_NEEDED) { + neg_ctx->state = GSS_AUTHDONE; + } + #endif + #endif } - else { - Curl_safefree(conn->allocptr.userpwd); - conn->allocptr.userpwd = userp; + + if(neg_ctx->state == GSS_AUTHDONE || neg_ctx->state == GSS_AUTHSUCC) { + /* connection is already authenticated, + * don't send a header in future requests */ + authp->done = TRUE; } - free(base64); + neg_ctx->havenegdata = FALSE; - return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; + return CURLE_OK; } -void Curl_cleanup_negotiate(struct Curl_easy *data) +void Curl_cleanup_negotiate(struct connectdata *conn) { - Curl_auth_spnego_cleanup(&data->state.negotiate); - Curl_auth_spnego_cleanup(&data->state.proxyneg); + Curl_auth_spnego_cleanup(&conn->negotiate); + Curl_auth_spnego_cleanup(&conn->proxyneg); } #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h index c64e5482..d4a7f09e 100644 --- a/lib/http_negotiate.h +++ b/lib/http_negotiate.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, 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 @@ -31,7 +31,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, /* this is for creating Negotiate header output */ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); -void Curl_cleanup_negotiate(struct Curl_easy *data); +void Curl_cleanup_negotiate(struct connectdata *conn); #endif /* USE_SPNEGO */ @@ -1177,11 +1177,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, if(data->req.bytecount == size) /* The entire data is already transferred! */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); else { /* IMAP download */ data->req.maxdownload = size; - Curl_setup_transfer(conn, FIRSTSOCKET, size, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1); } } else { @@ -1231,7 +1231,7 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode, Curl_pgrsSetUploadSize(data, data->state.infilesize); /* IMAP upload */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* End of DO phase */ state(conn, IMAP_STOP); @@ -1660,7 +1660,7 @@ static CURLcode imap_dophase_done(struct connectdata *conn, bool connected) if(imap->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); return CURLE_OK; } @@ -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 @@ -744,7 +744,7 @@ quit: #endif /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); connclose(conn, "LDAP connection always disable re-use"); return result; diff --git a/lib/libcurl.plist b/lib/libcurl.plist index 13f2cf74..7d005b79 100644 --- a/lib/libcurl.plist +++ b/lib/libcurl.plist @@ -15,7 +15,7 @@ <string>se.haxx.curl.libcurl</string> <key>CFBundleVersion</key> - <string>7.64.0</string> + <string>7.64.1</string> <key>CFBundleName</key> <string>libcurl</string> @@ -27,9 +27,9 @@ <string>????</string> <key>CFBundleShortVersionString</key> - <string>libcurl 7.64.0</string> + <string>libcurl 7.64.1</string> <key>CFBundleGetInfoString</key> - <string>libcurl.plist 7.64.0</string> + <string>libcurl.plist 7.64.1</string> </dict> </plist> @@ -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 @@ -83,7 +83,7 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx) gcry_md_close(*ctx); } -#elif defined(USE_OPENSSL) +#elif defined(USE_OPENSSL) && !defined(USE_AMISSL) /* When OpenSSL is available we use the MD5-function from OpenSSL */ #include <openssl/md5.h> #include "curl_memory.h" diff --git a/lib/memdebug.c b/lib/memdebug.c index 05590a8f..e3ac8edf 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.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 @@ -100,19 +100,18 @@ struct memdebug { * Don't use these with multithreaded test programs! */ -#define logfile curl_debuglogfile -FILE *curl_debuglogfile = NULL; +FILE *curl_dbg_logfile = NULL; static bool memlimit = FALSE; /* enable memory limit */ static long memsize = 0; /* set number of mallocs allowed */ /* this sets the log file name */ -void curl_memdebug(const char *logname) +void curl_dbg_memdebug(const char *logname) { - if(!logfile) { + if(!curl_dbg_logfile) { if(logname && *logname) - logfile = fopen(logname, FOPEN_WRITETEXT); + curl_dbg_logfile = fopen(logname, FOPEN_WRITETEXT); else - logfile = stderr; + curl_dbg_logfile = stderr; #ifdef MEMDEBUG_LOG_SYNC /* Flush the log file after every line so the log isn't lost in a crash */ if(logfile) @@ -123,7 +122,7 @@ void curl_memdebug(const char *logname) /* This function sets the number of malloc() calls that should return successfully! */ -void curl_memlimit(long limit) +void curl_dbg_memlimit(long limit) { if(!memlimit) { memlimit = TRUE; @@ -140,12 +139,12 @@ static bool countcheck(const char *func, int line, const char *source) if(!memsize) { if(source) { /* log to file */ - curl_memlog("LIMIT %s:%d %s reached memlimit\n", - source, line, func); + curl_dbg_log("LIMIT %s:%d %s reached memlimit\n", + source, line, func); /* log to stderr also */ fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n", source, line, func); - fflush(logfile); /* because it might crash now */ + fflush(curl_dbg_logfile); /* because it might crash now */ } errno = ENOMEM; return TRUE; /* RETURN ERROR! */ @@ -159,7 +158,7 @@ static bool countcheck(const char *func, int line, const char *source) return FALSE; /* allow this */ } -void *curl_domalloc(size_t wantedsize, int line, const char *source) +void *curl_dbg_malloc(size_t wantedsize, int line, const char *source) { struct memdebug *mem; size_t size; @@ -180,15 +179,15 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source) } if(source) - curl_memlog("MEM %s:%d malloc(%zu) = %p\n", - source, line, wantedsize, - mem ? (void *)mem->mem : (void *)0); + curl_dbg_log("MEM %s:%d malloc(%zu) = %p\n", + source, line, wantedsize, + mem ? (void *)mem->mem : (void *)0); return (mem ? mem->mem : NULL); } -void *curl_docalloc(size_t wanted_elements, size_t wanted_size, - int line, const char *source) +void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size, + int line, const char *source) { struct memdebug *mem; size_t size, user_size; @@ -208,14 +207,14 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size, mem->size = user_size; if(source) - curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n", - source, line, wanted_elements, wanted_size, - mem ? (void *)mem->mem : (void *)0); + curl_dbg_log("MEM %s:%d calloc(%zu,%zu) = %p\n", + source, line, wanted_elements, wanted_size, + mem ? (void *)mem->mem : (void *)0); return (mem ? mem->mem : NULL); } -char *curl_dostrdup(const char *str, int line, const char *source) +char *curl_dbg_strdup(const char *str, int line, const char *source) { char *mem; size_t len; @@ -227,19 +226,19 @@ char *curl_dostrdup(const char *str, int line, const char *source) len = strlen(str) + 1; - mem = curl_domalloc(len, 0, NULL); /* NULL prevents logging */ + mem = curl_dbg_malloc(len, 0, NULL); /* NULL prevents logging */ if(mem) memcpy(mem, str, len); if(source) - curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n", - source, line, (const void *)str, len, (const void *)mem); + curl_dbg_log("MEM %s:%d strdup(%p) (%zu) = %p\n", + source, line, (const void *)str, len, (const void *)mem); return mem; } #if defined(WIN32) && defined(UNICODE) -wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source) +wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source) { wchar_t *mem; size_t wsiz, bsiz; @@ -252,12 +251,12 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source) wsiz = wcslen(str) + 1; bsiz = wsiz * sizeof(wchar_t); - mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */ + mem = curl_dbg_malloc(bsiz, 0, NULL); /* NULL prevents logging */ if(mem) memcpy(mem, str, bsiz); if(source) - curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n", + curl_dbg_log("MEM %s:%d wcsdup(%p) (%zu) = %p\n", source, line, (void *)str, bsiz, (void *)mem); return mem; @@ -266,8 +265,8 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source) /* We provide a realloc() that accepts a NULL as pointer, which then performs a malloc(). In order to work with ares. */ -void *curl_dorealloc(void *ptr, size_t wantedsize, - int line, const char *source) +void *curl_dbg_realloc(void *ptr, size_t wantedsize, + int line, const char *source) { struct memdebug *mem = NULL; @@ -293,7 +292,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize, mem = (Curl_crealloc)(mem, size); if(source) - curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n", + curl_dbg_log("MEM %s:%d realloc(%p, %zu) = %p\n", source, line, (void *)ptr, wantedsize, mem ? (void *)mem->mem : (void *)0); @@ -305,7 +304,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize, return NULL; } -void curl_dofree(void *ptr, int line, const char *source) +void curl_dbg_free(void *ptr, int line, const char *source) { struct memdebug *mem; @@ -331,11 +330,11 @@ void curl_dofree(void *ptr, int line, const char *source) } if(source) - curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr); + curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr); } -curl_socket_t curl_socket(int domain, int type, int protocol, - int line, const char *source) +curl_socket_t curl_dbg_socket(int domain, int type, int protocol, + int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? "FD %s:%d socket() = %d\n" : @@ -351,44 +350,44 @@ curl_socket_t curl_socket(int domain, int type, int protocol, sockfd = socket(domain, type, protocol); if(source && (sockfd != CURL_SOCKET_BAD)) - curl_memlog(fmt, source, line, sockfd); + curl_dbg_log(fmt, source, line, sockfd); return sockfd; } -SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd, - SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, - SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line, - const char *source) +SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, + SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, + SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line, + const char *source) { SEND_TYPE_RETV rc; if(countcheck("send", line, source)) return -1; rc = send(sockfd, buf, len, flags); if(source) - curl_memlog("SEND %s:%d send(%lu) = %ld\n", + curl_dbg_log("SEND %s:%d send(%lu) = %ld\n", source, line, (unsigned long)len, (long)rc); return rc; } -RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf, - RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line, - const char *source) +RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf, + RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line, + const char *source) { RECV_TYPE_RETV rc; if(countcheck("recv", line, source)) return -1; rc = recv(sockfd, buf, len, flags); if(source) - curl_memlog("RECV %s:%d recv(%lu) = %ld\n", + curl_dbg_log("RECV %s:%d recv(%lu) = %ld\n", source, line, (unsigned long)len, (long)rc); return rc; } #ifdef HAVE_SOCKETPAIR -int curl_socketpair(int domain, int type, int protocol, - curl_socket_t socket_vector[2], - int line, const char *source) +int curl_dbg_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? "FD %s:%d socketpair() = %d %d\n" : @@ -399,14 +398,14 @@ int curl_socketpair(int domain, int type, int protocol, int res = socketpair(domain, type, protocol, socket_vector); if(source && (0 == res)) - curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]); + curl_dbg_log(fmt, source, line, socket_vector[0], socket_vector[1]); return res; } #endif -curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen, - int line, const char *source) +curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen, + int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? "FD %s:%d accept() = %d\n" : @@ -420,13 +419,13 @@ curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen, curl_socket_t sockfd = accept(s, addr, addrlen); if(source && (sockfd != CURL_SOCKET_BAD)) - curl_memlog(fmt, source, line, sockfd); + curl_dbg_log(fmt, source, line, sockfd); return sockfd; } /* separate function to allow libcurl to mark a "faked" close */ -void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source) +void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source) { const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ? "FD %s:%d sclose(%d)\n": @@ -435,54 +434,40 @@ void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source) "FD %s:%d sclose(%zd)\n"; if(source) - curl_memlog(fmt, source, line, sockfd); + curl_dbg_log(fmt, source, line, sockfd); } /* this is our own defined way to close sockets on *ALL* platforms */ -int curl_sclose(curl_socket_t sockfd, int line, const char *source) +int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source) { int res = sclose(sockfd); - curl_mark_sclose(sockfd, line, source); + curl_dbg_mark_sclose(sockfd, line, source); return res; } -FILE *curl_fopen(const char *file, const char *mode, - int line, const char *source) +FILE *curl_dbg_fopen(const char *file, const char *mode, + int line, const char *source) { FILE *res = fopen(file, mode); if(source) - curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", + curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", source, line, file, mode, (void *)res); return res; } -#ifdef HAVE_FDOPEN -FILE *curl_fdopen(int filedes, const char *mode, - int line, const char *source) -{ - FILE *res = fdopen(filedes, mode); - - if(source) - curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n", - source, line, filedes, mode, (void *)res); - - return res; -} -#endif - -int curl_fclose(FILE *file, int line, const char *source) +int curl_dbg_fclose(FILE *file, int line, const char *source) { int res; DEBUGASSERT(file != NULL); - res = fclose(file); - if(source) - curl_memlog("FILE %s:%d fclose(%p)\n", - source, line, (void *)file); + curl_dbg_log("FILE %s:%d fclose(%p)\n", + source, line, (void *)file); + + res = fclose(file); return res; } @@ -490,13 +475,13 @@ int curl_fclose(FILE *file, int line, const char *source) #define LOGLINE_BUFSIZE 1024 /* this does the writing to the memory tracking log file */ -void curl_memlog(const char *format, ...) +void curl_dbg_log(const char *format, ...) { char *buf; int nchars; va_list ap; - if(!logfile) + if(!curl_dbg_logfile) return; buf = (Curl_cmalloc)(LOGLINE_BUFSIZE); @@ -511,7 +496,7 @@ void curl_memlog(const char *format, ...) nchars = LOGLINE_BUFSIZE - 1; if(nchars > 0) - fwrite(buf, 1, (size_t)nchars, logfile); + fwrite(buf, 1, (size_t)nchars, curl_dbg_logfile); (Curl_cfree)(buf); } diff --git a/lib/memdebug.h b/lib/memdebug.h index 233de65a..5236f60f 100644 --- a/lib/memdebug.h +++ b/lib/memdebug.h @@ -8,7 +8,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 @@ -30,97 +30,92 @@ #define CURL_MT_LOGFNAME_BUFSIZE 512 -#define logfile curl_debuglogfile - -extern FILE *logfile; +extern FILE *curl_dbg_logfile; /* memory functions */ -CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source); -CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line, - const char *source); -CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line, - const char *source); -CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source); -CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source); -#if defined(WIN32) && defined(UNICODE) -CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line, +CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source); +CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line, + const char *source); +CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line, const char *source); +CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source); +CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src); +#if defined(WIN32) && defined(UNICODE) +CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, + const char *source); #endif -CURL_EXTERN void curl_memdebug(const char *logname); -CURL_EXTERN void curl_memlimit(long limit); -CURL_EXTERN void curl_memlog(const char *format, ...); +CURL_EXTERN void curl_dbg_memdebug(const char *logname); +CURL_EXTERN void curl_dbg_memlimit(long limit); +CURL_EXTERN void curl_dbg_log(const char *format, ...); /* file descriptor manipulators */ -CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol, - int line, const char *source); -CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd, - int line, const char *source); -CURL_EXTERN int curl_sclose(curl_socket_t sockfd, - int line, const char *source); -CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen, +CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol, + int line, const char *source); +CURL_EXTERN void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source); -#ifdef HAVE_SOCKETPAIR -CURL_EXTERN int curl_socketpair(int domain, int type, int protocol, - curl_socket_t socket_vector[2], +CURL_EXTERN int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source); +CURL_EXTERN curl_socket_t curl_dbg_accept(curl_socket_t s, void *a, void *alen, + int line, const char *source); +#ifdef HAVE_SOCKETPAIR +CURL_EXTERN int curl_dbg_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source); #endif /* send/receive sockets */ -CURL_EXTERN SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd, - SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, - SEND_TYPE_ARG3 len, - SEND_TYPE_ARG4 flags, int line, - const char *source); -CURL_EXTERN RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd, - RECV_TYPE_ARG2 buf, RECV_TYPE_ARG3 len, - RECV_TYPE_ARG4 flags, int line, - const char *source); +CURL_EXTERN SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, + SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, + SEND_TYPE_ARG3 len, + SEND_TYPE_ARG4 flags, int line, + const char *source); +CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, + RECV_TYPE_ARG2 buf, + RECV_TYPE_ARG3 len, + RECV_TYPE_ARG4 flags, int line, + const char *source); /* FILE functions */ -CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line, - const char *source); -#ifdef HAVE_FDOPEN -CURL_EXTERN FILE *curl_fdopen(int filedes, const char *mode, int line, - const char *source); -#endif -CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source); +CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line, + const char *source); +CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); #ifndef MEMDEBUG_NODEFINES /* Set this symbol on the command-line, recompile all lib-sources */ #undef strdup -#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__) -#define malloc(size) curl_domalloc(size, __LINE__, __FILE__) -#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__) -#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__) -#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__) -#define send(a,b,c,d) curl_dosend(a,b,c,d, __LINE__, __FILE__) -#define recv(a,b,c,d) curl_dorecv(a,b,c,d, __LINE__, __FILE__) +#define strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) +#define malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__) +#define calloc(nbelem,size) curl_dbg_calloc(nbelem, size, __LINE__, __FILE__) +#define realloc(ptr,size) curl_dbg_realloc(ptr, size, __LINE__, __FILE__) +#define free(ptr) curl_dbg_free(ptr, __LINE__, __FILE__) +#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__) +#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__) #ifdef WIN32 # ifdef UNICODE # undef wcsdup -# define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__) +# define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) # undef _wcsdup -# define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__) +# define _wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) # undef _tcsdup -# define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__) +# define _tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) # else # undef _tcsdup -# define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__) +# define _tcsdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) # endif #endif #undef socket #define socket(domain,type,protocol)\ - curl_socket(domain, type, protocol, __LINE__, __FILE__) + curl_dbg_socket(domain, type, protocol, __LINE__, __FILE__) #undef accept /* for those with accept as a macro */ #define accept(sock,addr,len)\ - curl_accept(sock, addr, len, __LINE__, __FILE__) + curl_dbg_accept(sock, addr, len, __LINE__, __FILE__) #ifdef HAVE_SOCKETPAIR #define socketpair(domain,type,protocol,socket_vector)\ - curl_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__) + curl_dbg_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__) #endif #ifdef HAVE_GETADDRINFO @@ -129,31 +124,31 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source); our macro as for other platforms. Instead, we redefine the new name they define getaddrinfo to become! */ #define ogetaddrinfo(host,serv,hint,res) \ - curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__) + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) #else #undef getaddrinfo #define getaddrinfo(host,serv,hint,res) \ - curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__) + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) #endif #endif /* HAVE_GETADDRINFO */ #ifdef HAVE_FREEADDRINFO #undef freeaddrinfo #define freeaddrinfo(data) \ - curl_dofreeaddrinfo(data, __LINE__, __FILE__) + curl_dbg_freeaddrinfo(data, __LINE__, __FILE__) #endif /* HAVE_FREEADDRINFO */ /* sclose is probably already defined, redefine it! */ #undef sclose -#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__) +#define sclose(sockfd) curl_dbg_sclose(sockfd,__LINE__,__FILE__) -#define fake_sclose(sockfd) curl_mark_sclose(sockfd,__LINE__,__FILE__) +#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd,__LINE__,__FILE__) #undef fopen -#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__) +#define fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__) #undef fdopen -#define fdopen(file,mode) curl_fdopen(file,mode,__LINE__,__FILE__) -#define fclose(file) curl_fclose(file,__LINE__,__FILE__) +#define fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__) +#define fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__) #endif /* MEMDEBUG_NODEFINES */ @@ -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 @@ -1122,8 +1122,6 @@ void curl_mime_free(curl_mime *mime) Curl_mime_cleanpart(part); free(part); } - - free(mime->boundary); free(mime); } } @@ -1220,18 +1218,10 @@ curl_mime *curl_mime_init(struct Curl_easy *easy) mime->firstpart = NULL; mime->lastpart = NULL; - /* Get a part boundary. */ - mime->boundary = malloc(24 + MIME_RAND_BOUNDARY_CHARS + 1); - if(!mime->boundary) { - free(mime); - return NULL; - } - memset(mime->boundary, '-', 24); - if(Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24, + if(Curl_rand_hex(easy, (unsigned char *) &mime->boundary[24], MIME_RAND_BOUNDARY_CHARS + 1)) { /* failed to get random separator, bail out */ - free(mime->boundary); free(mime); return NULL; } @@ -7,7 +7,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 @@ -88,13 +88,16 @@ typedef struct { size_t offset; /* State-dependent offset. */ } mime_state; +/* minimum buffer size for the boundary string */ +#define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1) + /* A mime multipart. */ struct curl_mime_s { struct Curl_easy *easy; /* The associated easy handle. */ curl_mimepart *parent; /* Parent part. */ curl_mimepart *firstpart; /* First part. */ curl_mimepart *lastpart; /* Last part. */ - char *boundary; /* The part boundary. */ + char boundary[MIME_BOUNDARY_LEN]; /* The part boundary. */ mime_state state; /* Current readback state. */ }; diff --git a/lib/multi.c b/lib/multi.c index 130226f5..cc16924a 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -80,6 +80,7 @@ static CURLMcode add_next_timeout(struct curltime now, static CURLMcode multi_timeout(struct Curl_multi *multi, long *timeout_ms); static void process_pending_handles(struct Curl_multi *multi); +static void detach_connnection(struct Curl_easy *data); #ifdef DEBUGBUILD static const char * const statename[]={ @@ -114,7 +115,7 @@ static void Curl_init_completed(struct Curl_easy *data) /* Important: reset the conn pointer so that we don't point to memory that could be freed anytime */ - Curl_detach_connnection(data); + detach_connnection(data); Curl_expire_clear(data); /* stop all timers */ } @@ -496,6 +497,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, data->set.server_response_timeout; data->state.conn_cache->closure_handle->set.no_signal = data->set.no_signal; + data->state.conn_cache->closure_handle->set.verbose = + data->set.verbose; update_timer(multi); return CURLM_OK; @@ -572,7 +575,7 @@ static CURLcode multi_done(struct Curl_easy *data, if(conn->send_pipe.size || conn->recv_pipe.size) { /* Stop if pipeline is not empty . */ - Curl_detach_connnection(data); + detach_connnection(data); DEBUGF(infof(data, "Connection still in use %zu/%zu, " "no more multi_done now!\n", conn->send_pipe.size, conn->recv_pipe.size)); @@ -597,7 +600,7 @@ static CURLcode multi_done(struct Curl_easy *data, /* if data->set.reuse_forbid is TRUE, it means the libcurl client has forced us to close this connection. This is ignored for requests taking - place in a NTLM authentication handshake + place in a NTLM/NEGOTIATE authentication handshake if conn->bits.close is TRUE, it means that the connection should be closed in spite of all our efforts to be nice, due to protocol @@ -615,6 +618,10 @@ static CURLcode multi_done(struct Curl_easy *data, && !(conn->ntlm.state == NTLMSTATE_TYPE2 || conn->proxyntlm.state == NTLMSTATE_TYPE2) #endif +#if defined(USE_SPNEGO) + && !(conn->negotiate.state == GSS_AUTHRECV || + conn->proxyneg.state == GSS_AUTHRECV) +#endif ) || conn->bits.close || (premature && !(conn->handler->flags & PROTOPT_STREAM))) { CURLcode res2 = Curl_disconnect(data, conn, premature); @@ -645,7 +652,7 @@ static CURLcode multi_done(struct Curl_easy *data, data->state.lastconnect = NULL; } - Curl_detach_connnection(data); + detach_connnection(data); Curl_free_request_state(data); return result; } @@ -752,7 +759,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, /* Remove the association between the connection and the handle */ if(data->conn) { data->conn->data = NULL; - Curl_detach_connnection(data); + detach_connnection(data); } #ifdef USE_LIBPSL @@ -804,7 +811,7 @@ bool Curl_pipeline_wanted(const struct Curl_multi *multi, int bits) /* This is the only function that should clear data->conn. This will occasionally be called with the pointer already cleared. */ -void Curl_detach_connnection(struct Curl_easy *data) +static void detach_connnection(struct Curl_easy *data) { data->conn = NULL; } @@ -998,11 +1005,11 @@ CURLMcode Curl_multi_wait(struct Curl_multi *multi, unsigned int i; unsigned int nfds = 0; unsigned int curlfds; - struct pollfd *ufds = NULL; bool ufds_malloc = FALSE; long timeout_internal; int retcode = 0; struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; + struct pollfd *ufds = &a_few_on_stack[0]; if(gotsocket) *gotsocket = FALSE; @@ -1047,19 +1054,15 @@ CURLMcode Curl_multi_wait(struct Curl_multi *multi, curlfds = nfds; /* number of internal file descriptors */ nfds += extra_nfds; /* add the externally provided ones */ - if(nfds) { - if(nfds > NUM_POLLS_ON_STACK) { - /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes - big, so at 2^29 sockets this value might wrap. When a process gets - the capability to actually handle over 500 million sockets this - calculation needs a integer overflow check. */ - ufds = malloc(nfds * sizeof(struct pollfd)); - if(!ufds) - return CURLM_OUT_OF_MEMORY; - ufds_malloc = TRUE; - } - else - ufds = &a_few_on_stack[0]; + if(nfds > NUM_POLLS_ON_STACK) { + /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes + big, so at 2^29 sockets this value might wrap. When a process gets + the capability to actually handle over 500 million sockets this + calculation needs a integer overflow check. */ + ufds = malloc(nfds * sizeof(struct pollfd)); + if(!ufds) + return CURLM_OUT_OF_MEMORY; + ufds_malloc = TRUE; } nfds = 0; @@ -1154,17 +1157,6 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi, { return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, NULL); } -/* - * Curl_multi_connchanged() is called to tell that there is a connection in - * this multi handle that has changed state (pipelining become possible, the - * number of allowed streams changed or similar), and a subsequent use of this - * multi handle should move CONNECT_PEND handles back to CONNECT to have them - * retry. - */ -void Curl_multi_connchanged(struct Curl_multi *multi) -{ - multi->recheckstate = TRUE; -} /* * multi_ischanged() is called @@ -1207,57 +1199,6 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, return rc; } -static CURLcode multi_reconnect_request(struct Curl_easy *data) -{ - CURLcode result = CURLE_OK; - struct connectdata *conn = data->conn; - - /* This was a re-use of a connection and we got a write error in the - * DO-phase. Then we DISCONNECT this connection and have another attempt to - * CONNECT and then DO again! The retry cannot possibly find another - * connection to re-use, since we only keep one possible connection for - * each. */ - - infof(data, "Re-used connection seems dead, get a new one\n"); - - connclose(conn, "Reconnect dead connection"); /* enforce close */ - result = multi_done(data, result, FALSE); /* we are so done with this */ - - /* data->conn was detached in multi_done() */ - - /* - * We need to check for CURLE_SEND_ERROR here as well. This could happen - * when the request failed on a FTP connection and thus multi_done() itself - * tried to use the connection (again). - */ - if(!result || (CURLE_SEND_ERROR == result)) { - bool async; - bool protocol_done = TRUE; - - /* Now, redo the connect and get a new connection */ - result = Curl_connect(data, &async, &protocol_done); - if(!result) { - /* We have connected or sent away a name resolve query fine */ - - conn = data->conn; /* in case it was updated */ - if(async) { - /* Now, if async is TRUE here, we need to wait for the name - to resolve */ - result = Curl_resolver_wait_resolv(conn, NULL); - if(result) - return result; - - /* Resolved, continue with the connection */ - result = Curl_once_resolved(conn, &protocol_done); - if(result) - return result; - } - } - } - - return result; -} - /* * do_complete is called when the DO actions are complete. * @@ -1267,8 +1208,6 @@ static CURLcode multi_reconnect_request(struct Curl_easy *data) static void do_complete(struct connectdata *conn) { conn->data->req.chunk = FALSE; - conn->data->req.maxfd = (conn->sockfd>conn->writesockfd? - conn->sockfd:conn->writesockfd) + 1; Curl_pgrsTime(conn->data, TIMER_PRETRANSFER); } @@ -1281,27 +1220,6 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done) /* generic protocol-specific function pointer set in curl_connect() */ result = conn->handler->do_it(conn, done); - /* This was formerly done in transfer.c, but we better do it here */ - if((CURLE_SEND_ERROR == result) && conn->bits.reuse) { - /* - * If the connection is using an easy handle, call reconnect - * to re-establish the connection. Otherwise, let the multi logic - * figure out how to re-establish the connection. - */ - if(!data->multi) { - result = multi_reconnect_request(data); - - if(!result) { - /* ... finally back to actually retry the DO phase */ - conn = data->conn; /* re-assign conn since multi_reconnect_request - creates a new connection */ - result = conn->handler->do_it(conn, done); - } - } - else - return result; - } - if(!result && *done) /* do_complete must be called after the protocol-specific DO function */ do_complete(conn); @@ -1549,7 +1467,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(result) /* if Curl_once_resolved() returns failure, the connection struct is already freed and gone */ - Curl_detach_connnection(data); /* no more connection */ + detach_connnection(data); /* no more connection */ else { /* call again please so that we get the next socket setup */ rc = CURLM_CALL_MULTI_PERFORM; @@ -1620,7 +1538,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } else if(result) { /* failure detected */ - /* Just break, the cleaning up is handled all in one place */ + Curl_posttransfer(data); + multi_done(data, result, TRUE); stream_error = TRUE; break; } @@ -1933,13 +1852,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, k = &data->req; - if(!(k->keepon & KEEP_RECV)) + if(!(k->keepon & KEEP_RECV)) { /* We're done receiving */ Curl_pipeline_leave_read(data->conn); + } - if(!(k->keepon & KEEP_SEND)) + if(!(k->keepon & KEEP_SEND)) { /* We're done sending */ Curl_pipeline_leave_write(data->conn); + } if(done || (result == CURLE_RECV_ERROR)) { /* If CURLE_RECV_ERROR happens early enough, we assume it was a race @@ -2087,7 +2008,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, * removed before we perform the processing in CURLM_STATE_COMPLETED */ if(data->conn) - Curl_detach_connnection(data); + detach_connnection(data); } if(data->state.wildcardmatch) { @@ -2145,7 +2066,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* This is where we make sure that the conn pointer is reset. We don't have to do this in every case block above where a failure is detected */ - Curl_detach_connnection(data); + detach_connnection(data); } } else if(data->mstate == CURLM_STATE_CONNECT) { @@ -2298,8 +2219,9 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi) Curl_psl_destroy(&multi->psl); /* Free the blacklists by setting them to NULL */ - Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl); - Curl_pipeline_set_server_blacklist(NULL, &multi->pipelining_server_bl); + (void)Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl); + (void)Curl_pipeline_set_server_blacklist(NULL, + &multi->pipelining_server_bl); free(multi); @@ -2360,8 +2282,6 @@ static CURLMcode singlesocket(struct Curl_multi *multi, int num; unsigned int curraction; int actions[MAX_SOCKSPEREASYHANDLE]; - unsigned int comboaction; - bool sincebefore = FALSE; for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) socks[i] = CURL_SOCKET_BAD; @@ -2380,6 +2300,8 @@ static CURLMcode singlesocket(struct Curl_multi *multi, i++) { unsigned int action = CURL_POLL_NONE; unsigned int prevaction = 0; + unsigned int comboaction; + bool sincebefore = FALSE; s = socks[i]; @@ -3028,9 +2950,6 @@ void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id) DEBUGASSERT(id < EXPIRE_LAST); - infof(data, "Expire in %ld ms for %x (transfer %p)\n", - (long)milli, id, data); - set = Curl_now(); set.tv_sec += milli/1000; set.tv_usec += (unsigned int)(milli%1000)*1000; diff --git a/lib/non-ascii.c b/lib/non-ascii.c index 14143248..42beaec4 100644 --- a/lib/non-ascii.c +++ b/lib/non-ascii.c @@ -78,7 +78,7 @@ CURLcode Curl_convert_clone(struct Curl_easy *data, /* * Curl_convert_to_network() is an internal function for performing ASCII - * conversions on non-ASCII platforms. It convers the buffer _in place_. + * conversions on non-ASCII platforms. It converts the buffer _in place_. */ CURLcode Curl_convert_to_network(struct Curl_easy *data, char *buffer, size_t length) @@ -144,7 +144,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, /* * Curl_convert_from_network() is an internal function for performing ASCII - * conversions on non-ASCII platforms. It convers the buffer _in place_. + * conversions on non-ASCII platforms. It converts the buffer _in place_. */ CURLcode Curl_convert_from_network(struct Curl_easy *data, char *buffer, size_t length) diff --git a/lib/openldap.c b/lib/openldap.c index bc007883..a98c50b4 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010, Howard Chu, <hyc@openldap.org> - * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2011 - 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 @@ -414,7 +414,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done) return CURLE_OUT_OF_MEMORY; lr->msgid = msgid; data->req.protop = lr; - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); *done = TRUE; return CURLE_OK; } @@ -912,7 +912,7 @@ static CURLcode pop3_state_command_resp(struct connectdata *conn, if(pop3->transfer == FTPTRANSFER_BODY) { /* POP3 download */ - Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); if(pp->cache) { /* The header "cache" contains a bunch of data that is actually body @@ -39,8 +39,11 @@ */ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num); -/* Same as above but outputs only random lowercase hex characters. - Does NOT terminate.*/ +/* + * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random + * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * size. + */ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, size_t num); @@ -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 @@ -80,8 +80,6 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, bool *readmore); static CURLcode rtsp_setup_connection(struct connectdata *conn); - -bool rtsp_connisdead(struct connectdata *check); static unsigned int rtsp_conncheck(struct connectdata *check, unsigned int checks_to_perform); @@ -147,7 +145,7 @@ static CURLcode rtsp_setup_connection(struct connectdata *conn) * Instead, if it is readable, run Curl_connalive() to peek at the socket * and distinguish between closed and data. */ -bool rtsp_connisdead(struct connectdata *check) +static bool rtsp_connisdead(struct connectdata *check) { int sval; bool ret_val = TRUE; @@ -251,7 +249,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) CURLcode result = CURLE_OK; Curl_RtspReq rtspreq = data->set.rtspreq; struct RTSP *rtsp = data->req.protop; - struct HTTP *http; Curl_send_buffer *req_buffer; curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */ curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */ @@ -270,10 +267,6 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) *done = TRUE; - http = &(rtsp->http_wrapper); - /* Assert that no one has changed the RTSP struct in an evil way */ - DEBUGASSERT((void *)http == (void *)rtsp); - rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq; rtsp->CSeq_recv = 0; @@ -330,8 +323,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) } if(rtspreq == RTSPREQ_RECEIVE) { - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, - &http->readbytecount, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); return result; } @@ -599,17 +591,15 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) return result; } - Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, - putsize?FIRSTSOCKET:-1, - putsize?&http->writebytecount:NULL); + Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, putsize?FIRSTSOCKET:-1); /* Increment the CSeq on success */ data->state.rtsp_next_client_CSeq++; - if(http->writebytecount) { + if(data->req.writebytecount) { /* if a request-body has been sent off, we make sure this progress is noted properly */ - Curl_pgrsSetUploadCounter(data, http->writebytecount); + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; } diff --git a/lib/security.c b/lib/security.c index 7f13071f..eec6e6f4 100644 --- a/lib/security.c +++ b/lib/security.c @@ -10,7 +10,7 @@ * Copyright (c) 1998, 1999, 2017 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * - * Copyright (C) 2001 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2001 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * * All rights reserved. * @@ -142,7 +142,7 @@ socket_read(curl_socket_t fd, void *to, size_t len) { char *to_p = to; CURLcode result; - ssize_t nread; + ssize_t nread = 0; while(len > 0) { result = Curl_read_plain(fd, to_p, len, &nread); diff --git a/lib/sendf.c b/lib/sendf.c index e8598e61..5008d933 100644 --- a/lib/sendf.c +++ b/lib/sendf.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 @@ -411,8 +411,9 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num, *code = CURLE_AGAIN; } else { + char buffer[STRERROR_LEN]; failf(conn->data, "Send failure: %s", - Curl_strerror(conn, err)); + Curl_strerror(err, buffer, sizeof(buffer))); conn->data->state.os_errno = err; *code = CURLE_SEND_ERROR; } @@ -476,8 +477,9 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, *code = CURLE_AGAIN; } else { + char buffer[STRERROR_LEN]; failf(conn->data, "Recv failure: %s", - Curl_strerror(conn, err)); + Curl_strerror(err, buffer, sizeof(buffer))); conn->data->state.os_errno = err; *code = CURLE_RECV_ERROR; } diff --git a/lib/setopt.c b/lib/setopt.c index d98ca66c..b5f74a93 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -44,6 +44,7 @@ #include "http2.h" #include "setopt.h" #include "multiif.h" +#include "altsvc.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -111,8 +112,8 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) #define C_SSLVERSION_VALUE(x) (x & 0xffff) #define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000) -CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, - va_list param) +static CURLcode vsetopt(struct Curl_easy *data, CURLoption option, + va_list param) { char *argptr; CURLcode result = CURLE_OK; @@ -682,7 +683,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, * Set header option. */ arg = va_arg(param, long); - data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE; + data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE); break; case CURLOPT_HTTP200ALIASES: @@ -884,7 +885,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, /* the DIGEST_IE bit is only used to set a special marker, for all the rest we need to handle it as normal DIGEST */ - data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE; + data->state.authhost.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); if(auth & CURLAUTH_DIGEST_IE) { auth |= CURLAUTH_DIGEST; /* set standard digest bit */ @@ -967,7 +969,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, /* the DIGEST_IE bit is only used to set a special marker, for all the rest we need to handle it as normal DIGEST */ - data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE; + data->state.authproxy.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); if(auth & CURLAUTH_DIGEST_IE) { auth |= CURLAUTH_DIGEST; /* set standard digest bit */ @@ -2076,13 +2079,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, case CURLOPT_SSL_OPTIONS: arg = va_arg(param, long); - data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; + data->set.ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); break; case CURLOPT_PROXY_SSL_OPTIONS: arg = va_arg(param, long); - data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; + data->set.proxy_ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); break; @@ -2651,6 +2656,31 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, data->set.trailer_data = va_arg(param, void *); #endif break; +#ifdef USE_ALTSVC + case CURLOPT_ALTSVC: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + argptr = va_arg(param, char *); + result = Curl_setstropt(&data->set.str[STRING_ALTSVC], argptr); + if(result) + return result; + (void)Curl_altsvc_load(data->asi, argptr); + break; + case CURLOPT_ALTSVC_CTRL: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + arg = va_arg(param, long); + result = Curl_altsvc_ctrl(data->asi, arg); + if(result) + return result; + break; +#endif default: /* unknown tag and its companion, just ignore: */ result = CURLE_UNKNOWN_OPTION; @@ -2679,7 +2709,7 @@ CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...) va_start(arg, tag); - result = Curl_vsetopt(data, tag, arg); + result = vsetopt(data, tag, arg); va_end(arg); return result; @@ -959,7 +959,7 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn, int smtpcode, Curl_pgrsSetUploadSize(data, data->state.infilesize); /* SMTP upload */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* End of DO phase */ state(conn, SMTP_STOP); @@ -1388,7 +1388,7 @@ static CURLcode smtp_dophase_done(struct connectdata *conn, bool connected) if(smtp->transfer != FTPTRANSFER_BODY) /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(conn->data, -1, -1, FALSE, -1); return CURLE_OK; } diff --git a/lib/socks.c b/lib/socks.c index d2209ad8..d0aba060 100644 --- a/lib/socks.c +++ b/lib/socks.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 @@ -54,7 +54,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */ ssize_t buffersize, /* max amount to read */ ssize_t *n) /* amount bytes read */ { - ssize_t nread; + ssize_t nread = 0; ssize_t allread = 0; int result; *n = 0; diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c index bedb01eb..57027ef6 100644 --- a/lib/socks_sspi.c +++ b/lib/socks_sspi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com> * * This software is licensed as described in the file COPYING, which @@ -51,8 +51,9 @@ static int check_sspi_err(struct connectdata *conn, status != SEC_I_COMPLETE_AND_CONTINUE && status != SEC_I_COMPLETE_NEEDED && status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; failf(conn->data, "SSPI error: %s failed: %s", function, - Curl_sspi_strerror(conn, status)); + Curl_sspi_strerror(status, buffer, sizeof(buffer))); return 1; } return 0; diff --git a/lib/ssh-libssh.c b/lib/ssh-libssh.c index 333df03e..609da1e0 100644 --- a/lib/ssh-libssh.c +++ b/lib/ssh-libssh.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2017 - 2018 Red Hat, Inc. + * Copyright (C) 2017 - 2019 Red Hat, Inc. * * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek, * Robert Kolcun, Andreas Schneider @@ -1200,7 +1200,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) Curl_pgrsSetUploadSize(data, data->state.infilesize); } /* upload data */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->sockfd = conn->writesockfd; @@ -1462,7 +1462,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) sshc->sftp_dir = NULL; /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); state(conn, SSH_STOP); break; @@ -1603,13 +1603,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* Setup the actual download */ if(data->req.size == 0) { /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); infof(data, "File already completely downloaded\n"); state(conn, SSH_STOP); break; } - Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size, - FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->writesockfd = conn->sockfd; @@ -1731,8 +1730,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) } /* upload data */ - Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL, - FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->sockfd = conn->writesockfd; @@ -1775,8 +1773,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block) /* download data */ bytecount = ssh_scp_request_get_size(sshc->scp_session); data->req.maxdownload = (curl_off_t) bytecount; - Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, - NULL); + Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->writesockfd = conn->sockfd; @@ -2398,13 +2395,9 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status, /* Post quote commands are executed after the SFTP_CLOSE state to avoid errors that could happen due to open file handles during POSTQUOTE operation */ - if(!status && !premature && conn->data->set.postquote && - !conn->bits.retry) { + if(!premature && conn->data->set.postquote && !conn->bits.retry) sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; - state(conn, SSH_SFTP_CLOSE); - } - else - state(conn, SSH_SFTP_CLOSE); + state(conn, SSH_SFTP_CLOSE); } return myssh_done(conn, status); } @@ -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 @@ -81,11 +81,11 @@ #include "multiif.h" #include "select.h" #include "warnless.h" +#include "curl_path.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" -#include "curl_path.h" #include "memdebug.h" #if LIBSSH2_VERSION_NUM >= 0x010206 @@ -1808,7 +1808,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_pgrsSetUploadSize(data, data->state.infilesize); } /* upload data */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->sockfd = conn->writesockfd; @@ -2105,7 +2105,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) Curl_safefree(sshc->readdir_longentry); /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); state(conn, SSH_STOP); break; @@ -2245,13 +2245,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* Setup the actual download */ if(data->req.size == 0) { /* no data to transfer */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); infof(data, "File already completely downloaded\n"); state(conn, SSH_STOP); break; } - Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size, - FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->writesockfd = conn->sockfd; @@ -2395,8 +2394,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } /* upload data */ - Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL, - FIRSTSOCKET, NULL); + Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->sockfd = conn->writesockfd; @@ -2467,7 +2465,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* download data */ bytecount = (curl_off_t)sb.st_size; data->req.maxdownload = (curl_off_t)sb.st_size; - Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1); /* not set by Curl_setup_transfer to preserve keepon bits */ conn->writesockfd = conn->sockfd; @@ -2791,9 +2789,12 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done) CURLcode result = CURLE_OK; bool block; /* we store the status and use that to provide a ssh_getsock() implementation */ - - result = ssh_statemach_act(conn, &block); - *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; + do { + result = ssh_statemach_act(conn, &block); + *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; + /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then + try again */ + } while(!result && !*done && !block); ssh_block2waitfor(conn, block); return result; @@ -3222,13 +3223,9 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status, /* Post quote commands are executed after the SFTP_CLOSE state to avoid errors that could happen due to open file handles during POSTQUOTE operation */ - if(!status && !premature && conn->data->set.postquote && - !conn->bits.retry) { + if(!premature && conn->data->set.postquote && !conn->bits.retry) sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT; - state(conn, SSH_SFTP_CLOSE); - } - else - state(conn, SSH_SFTP_CLOSE); + state(conn, SSH_SFTP_CLOSE); } return ssh_done(conn, status); } diff --git a/lib/strerror.c b/lib/strerror.c index bf30c890..e273f376 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2004 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2004 - 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 @@ -646,20 +646,18 @@ get_winsock_error (int err, char *buf, size_t len) * We don't do range checking (on systems other than Windows) since there is * no good reliable and portable way to do it. */ -const char *Curl_strerror(struct connectdata *conn, int err) +const char *Curl_strerror(int err, char *buf, size_t buflen) { #ifdef PRESERVE_WINDOWS_ERROR_CODE DWORD old_win_err = GetLastError(); #endif int old_errno = errno; - char *buf, *p; + char *p; size_t max; - DEBUGASSERT(conn); DEBUGASSERT(err >= 0); - buf = conn->syserr_buf; - max = sizeof(conn->syserr_buf)-1; + max = buflen - 1; *buf = '\0'; #ifdef USE_WINSOCK @@ -757,7 +755,7 @@ const char *Curl_strerror(struct connectdata *conn, int err) } #ifdef USE_WINDOWS_SSPI -const char *Curl_sspi_strerror (struct connectdata *conn, int err) +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen) { #ifdef PRESERVE_WINDOWS_ERROR_CODE DWORD old_win_err = GetLastError(); @@ -768,15 +766,13 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) size_t outmax; #ifndef CURL_DISABLE_VERBOSE_STRINGS char txtbuf[80]; - char msgbuf[sizeof(conn->syserr_buf)]; + char msgbuf[256]; char *p, *str, *msg = NULL; bool msg_formatted = FALSE; #endif - DEBUGASSERT(conn); - - outbuf = conn->syserr_buf; - outmax = sizeof(conn->syserr_buf)-1; + outbuf = buf; + outmax = buflen - 1; *outbuf = '\0'; #ifndef CURL_DISABLE_VERBOSE_STRINGS diff --git a/lib/strerror.h b/lib/strerror.h index 627273eb..683b5b4a 100644 --- a/lib/strerror.h +++ b/lib/strerror.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, 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 @@ -24,14 +24,11 @@ #include "urldata.h" -const char *Curl_strerror (struct connectdata *conn, int err); - -#ifdef USE_LIBIDN2 -const char *Curl_idn_strerror (struct connectdata *conn, int err); -#endif +#define STRERROR_LEN 128 /* a suitable length */ +const char *Curl_strerror(int err, char *buf, size_t buflen); #ifdef USE_WINDOWS_SSPI -const char *Curl_sspi_strerror (struct connectdata *conn, int err); +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen); #endif #endif /* HEADER_CURL_STRERROR_H */ diff --git a/lib/system_win32.c b/lib/system_win32.c index 6b8004e5..f7f817dd 100644 --- a/lib/system_win32.c +++ b/lib/system_win32.c @@ -26,12 +26,94 @@ #include <curl/curl.h> #include "system_win32.h" +#include "curl_sspi.h" #include "warnless.h" /* The last #include files should be: */ #include "curl_memory.h" #include "memdebug.h" +LARGE_INTEGER Curl_freq; +bool Curl_isVistaOrGreater; + +/* Curl_win32_init() performs win32 global initialization */ +CURLcode Curl_win32_init(long flags) +{ + /* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which + is just for Winsock at the moment. Any required win32 initialization + should take place after this block. */ + if(flags & CURL_GLOBAL_WIN32) { +#ifdef USE_WINSOCK + WORD wVersionRequested; + WSADATA wsaData; + int res; + +#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2) +#error IPV6_requires_winsock2 +#endif + + wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); + + res = WSAStartup(wVersionRequested, &wsaData); + + if(res != 0) + /* Tell the user that we couldn't find a usable */ + /* winsock.dll. */ + return CURLE_FAILED_INIT; + + /* Confirm that the Windows Sockets DLL supports what we need.*/ + /* Note that if the DLL supports versions greater */ + /* than wVersionRequested, it will still return */ + /* wVersionRequested in wVersion. wHighVersion contains the */ + /* highest supported version. */ + + if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || + HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { + /* Tell the user that we couldn't find a usable */ + + /* winsock.dll. */ + WSACleanup(); + return CURLE_FAILED_INIT; + } + /* The Windows Sockets DLL is acceptable. Proceed. */ + #elif defined(USE_LWIPSOCK) + lwip_init(); + #endif + } /* CURL_GLOBAL_WIN32 */ + +#ifdef USE_WINDOWS_SSPI + { + CURLcode result = Curl_sspi_global_init(); + if(result) + return result; + } +#endif + + if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { + Curl_isVistaOrGreater = TRUE; + QueryPerformanceFrequency(&Curl_freq); + } + else + Curl_isVistaOrGreater = FALSE; + + return CURLE_OK; +} + +/* Curl_win32_cleanup() is the opposite of Curl_win32_init() */ +void Curl_win32_cleanup(long init_flags) +{ +#ifdef USE_WINDOWS_SSPI + Curl_sspi_global_cleanup(); +#endif + + if(init_flags & CURL_GLOBAL_WIN32) { +#ifdef USE_WINSOCK + WSACleanup(); +#endif + } +} + #if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \ defined(USE_WINSOCK)) diff --git a/lib/system_win32.h b/lib/system_win32.h index 1e772856..926328a9 100644 --- a/lib/system_win32.h +++ b/lib/system_win32.h @@ -26,6 +26,12 @@ #if defined(WIN32) +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; + +CURLcode Curl_win32_init(long flags); +void Curl_win32_cleanup(long init_flags); + /* Version condition */ typedef enum { VERSION_LESS_THAN, diff --git a/lib/telnet.c b/lib/telnet.c index e4c0bac3..955255c3 100644 --- a/lib/telnet.c +++ b/lib/telnet.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 @@ -1692,7 +1692,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } #endif /* mark this as "no further transfer wanted" */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); return result; } @@ -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 @@ -540,7 +540,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) state->conn->ip_addr->ai_addr, state->conn->ip_addr->ai_addrlen); if(senddata != (ssize_t)sbytes) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + char buffer[STRERROR_LEN]; + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); } free(filename); break; @@ -590,6 +591,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ssize_t sbytes; int rblock; struct Curl_easy *data = state->conn->data; + char buffer[STRERROR_LEN]; switch(event) { @@ -622,7 +624,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) (struct sockaddr *)&state->remote_addr, state->remote_addrlen); if(sbytes < 0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } @@ -647,7 +649,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) (struct sockaddr *)&state->remote_addr, state->remote_addrlen); if(sbytes < 0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } @@ -673,7 +675,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) (struct sockaddr *)&state->remote_addr, state->remote_addrlen); if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } } @@ -713,6 +715,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) CURLcode result = CURLE_OK; struct SingleRequest *k = &data->req; size_t cb; /* Bytes currently read */ + char buffer[STRERROR_LEN]; switch(event) { @@ -747,7 +750,8 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) state->remote_addrlen); /* Check all sbytes were sent */ if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, + buffer, sizeof(buffer))); result = CURLE_SEND_ERROR; } } @@ -791,7 +795,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) state->remote_addrlen); /* Check all sbytes were sent */ if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } /* Update the progress meter */ @@ -817,7 +821,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) state->remote_addrlen); /* Check all sbytes were sent */ if(sbytes<0) { - failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); + failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_SEND_ERROR; } /* since this was a re-send, we remain at the still byte position */ @@ -1030,8 +1034,9 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, conn->ip_addr->ai_addrlen); if(rc) { + char buffer[STRERROR_LEN]; failf(conn->data, "bind() failed; %s", - Curl_strerror(conn, SOCKERRNO)); + Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); return CURLE_COULDNT_CONNECT; } conn->bits.bound = TRUE; @@ -1242,7 +1247,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; if(*done) /* Tell curl we're done */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); } else { /* no timeouts to handle, check our socket */ @@ -1251,7 +1256,8 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) if(rc == -1) { /* bail out */ int error = SOCKERRNO; - failf(data, "%s", Curl_strerror(conn, error)); + char buffer[STRERROR_LEN]; + failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer))); state->event = TFTP_EVENT_ERROR; } else if(rc != 0) { @@ -1264,7 +1270,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done) *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; if(*done) /* Tell curl we're done */ - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + Curl_setup_transfer(data, -1, -1, FALSE, -1); } /* if rc == 0, then select() timed out */ } diff --git a/lib/timeval.c b/lib/timeval.c index 2569f175..ff8d8a69 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -21,30 +21,22 @@ ***************************************************************************/ #include "timeval.h" -#include "system_win32.h" #if defined(WIN32) && !defined(MSDOS) +/* set in win32_init() */ +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; + struct curltime Curl_now(void) { struct curltime now; - static LARGE_INTEGER freq; - static int isVistaOrGreater = -1; - if(isVistaOrGreater == -1) { - if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, - VERSION_GREATER_THAN_EQUAL)) { - isVistaOrGreater = 1; - QueryPerformanceFrequency(&freq); - } - else - isVistaOrGreater = 0; - } - if(isVistaOrGreater == 1) { /* QPC timer might have issues pre-Vista */ + if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */ LARGE_INTEGER count; QueryPerformanceCounter(&count); - now.tv_sec = (time_t)(count.QuadPart / freq.QuadPart); - now.tv_usec = - (int)((count.QuadPart % freq.QuadPart) * 1000000 / freq.QuadPart); + now.tv_sec = (time_t)(count.QuadPart / Curl_freq.QuadPart); + now.tv_usec = (int)((count.QuadPart % Curl_freq.QuadPart) * 1000000 / + Curl_freq.QuadPart); } else { /* Disable /analyze warning that GetTickCount64 is preferred */ diff --git a/lib/transfer.c b/lib/transfer.c index 3a18c7bd..ca603172 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -296,10 +296,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, here, knowing they'll become CRLFs later on. */ - char hexbuffer[11]; + char hexbuffer[11] = ""; + int hexlen = 0; const char *endofline_native; const char *endofline_network; - int hexlen = 0; if( #ifdef CURL_DO_LINEEND_CONV @@ -354,12 +354,14 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, length = nread; else /* just translate the protocol portion */ - length = strlen(hexbuffer); - result = Curl_convert_to_network(data, data->req.upload_fromhere, - length); - /* Curl_convert_to_network calls failf if unsuccessful */ - if(result) - return result; + length = hexlen; + if(length) { + result = Curl_convert_to_network(data, data->req.upload_fromhere, + length); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + } } #endif /* CURL_DOES_CONVERSIONS */ @@ -1196,6 +1198,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data, (size_t)bytes_written); k->writebytecount += bytes_written; + Curl_pgrsSetUploadCounter(data, k->writebytecount); if((!k->upload_chunky || k->forbidchunk) && (k->writebytecount == data->state.infilesize)) { @@ -1229,7 +1232,6 @@ static CURLcode readwrite_upload(struct Curl_easy *data, } } - Curl_pgrsSetUploadCounter(data, k->writebytecount); } WHILE_FALSE; /* just to break out from! */ @@ -1307,11 +1309,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, k->now = Curl_now(); if(didwhat) { - /* Update read/write counters */ - if(k->bytecountp) - *k->bytecountp = k->bytecount; /* read count */ - if(k->writebytecountp) - *k->writebytecountp = k->writebytecount; /* write count */ + ; } else { /* no read no write, this is a timeout? */ @@ -1526,11 +1524,14 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) if(data->set.httpreq == HTTPREQ_PUT) data->state.infilesize = data->set.filesize; - else { + else if((data->set.httpreq != HTTPREQ_GET) && + (data->set.httpreq != HTTPREQ_HEAD)) { data->state.infilesize = data->set.postfieldsize; if(data->set.postfields && (data->state.infilesize == -1)) data->state.infilesize = (curl_off_t)strlen(data->set.postfields); } + else + data->state.infilesize = 0; /* If there is a list of cookie files to read, do it now! */ if(data->change.cookielist) @@ -1852,8 +1853,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, if(conn->handler->protocol&PROTO_FAMILY_HTTP) { - struct HTTP *http = data->req.protop; - if(http->writebytecount) { + if(data->req.writebytecount) { CURLcode result = Curl_readrewind(conn); if(result) { Curl_safefree(*url); @@ -1871,24 +1871,17 @@ CURLcode Curl_retry_request(struct connectdata *conn, */ void Curl_setup_transfer( - struct connectdata *conn, /* connection data */ + struct Curl_easy *data, /* transfer */ int sockindex, /* socket index to read from or -1 */ curl_off_t size, /* -1 if unknown at this point */ bool getheader, /* TRUE if header parsing is wanted */ - curl_off_t *bytecountp, /* return number of bytes read or NULL */ - int writesockindex, /* socket index to write to, it may very well be + int writesockindex /* socket index to write to, it may very well be the same we read from. -1 disables */ - curl_off_t *writecountp /* return number of bytes written or NULL */ ) { - struct Curl_easy *data; - struct SingleRequest *k; - + struct SingleRequest *k = &data->req; + struct connectdata *conn = data->conn; DEBUGASSERT(conn != NULL); - - data = conn->data; - k = &data->req; - DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); if(conn->bits.multiplex || conn->httpversion == 20) { @@ -1907,8 +1900,6 @@ Curl_setup_transfer( k->getheader = getheader; k->size = size; - k->bytecountp = bytecountp; - k->writebytecountp = writecountp; /* The code sequence below is placed in this function just because all necessary input is not always known in do_complete() as this function may diff --git a/lib/transfer.h b/lib/transfer.h index 9742455a..a9bff634 100644 --- a/lib/transfer.h +++ b/lib/transfer.h @@ -7,7 +7,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 @@ -59,15 +59,13 @@ CURLcode Curl_get_upload_buffer(struct Curl_easy *data); /* This sets up a forthcoming transfer */ void -Curl_setup_transfer (struct connectdata *data, - int sockindex, /* socket index to read from or -1 */ - curl_off_t size, /* -1 if unknown at this point */ - bool getheader, /* TRUE if header parsing is wanted */ - curl_off_t *bytecountp, /* return number of bytes read */ - int writesockindex, /* socket index to write to, it may - very well be the same we read from. - -1 disables */ - curl_off_t *writecountp /* return number of bytes written */ -); +Curl_setup_transfer (struct Curl_easy *data, + int sockindex, /* socket index to read from or -1 */ + curl_off_t size, /* -1 if unknown at this point */ + bool getheader, /* TRUE if header parsing is wanted */ + int writesockindex /* socket index to write to. May be + the same we read from. -1 + disables */ + ); #endif /* HEADER_CURL_TRANSFER_H */ @@ -120,6 +120,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out); #include "dotdot.h" #include "strdup.h" #include "setopt.h" +#include "altsvc.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -292,7 +293,7 @@ void Curl_freeset(struct Curl_easy *data) } /* free the URL pieces */ -void Curl_up_free(struct Curl_easy *data) +static void up_free(struct Curl_easy *data) { struct urlpieces *up = &data->state.up; Curl_safefree(up->scheme); @@ -303,7 +304,8 @@ void Curl_up_free(struct Curl_easy *data) Curl_safefree(up->options); Curl_safefree(up->path); Curl_safefree(up->query); - curl_url_cleanup(data->state.uh); + if(data->set.uh != data->state.uh) + curl_url_cleanup(data->state.uh); data->state.uh = NULL; } @@ -369,11 +371,16 @@ CURLcode Curl_close(struct Curl_easy *data) } data->change.referer = NULL; - Curl_up_free(data); + up_free(data); Curl_safefree(data->state.buffer); Curl_safefree(data->state.headerbuff); Curl_safefree(data->state.ulbuf); Curl_flush_cookies(data, 1); +#ifdef USE_ALTSVC + Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]); + Curl_altsvc_cleanup(data->asi); + data->asi = NULL; +#endif Curl_digest_cleanup(data); Curl_safefree(data->info.contenttype); Curl_safefree(data->info.wouldredirect); @@ -660,11 +667,15 @@ static void conn_reset_all_postponed_data(struct connectdata *conn) #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ -static void conn_free(struct connectdata *conn) + +static void conn_shutdown(struct connectdata *conn) { if(!conn) return; + infof(conn->data, "Closing connection %ld\n", conn->connection_id); + DEBUGASSERT(conn->data); + /* possible left-overs from the async name resolvers */ Curl_resolver_cancel(conn); @@ -688,6 +699,21 @@ static void conn_free(struct connectdata *conn) Curl_ntlm_wb_cleanup(conn); #endif + /* unlink ourselves. this should be called last since other shutdown + procedures need a valid conn->data and this may clear it. */ + Curl_conncache_remove_conn(conn->data, conn, TRUE); +} + +static void conn_free(struct connectdata *conn) +{ + if(!conn) + return; + + free_idnconverted_hostname(&conn->host); + free_idnconverted_hostname(&conn->conn_to_host); + free_idnconverted_hostname(&conn->http_proxy.host); + free_idnconverted_hostname(&conn->socks_proxy.host); + Curl_safefree(conn->user); Curl_safefree(conn->passwd); Curl_safefree(conn->oauth_bearer); @@ -780,27 +806,20 @@ CURLcode Curl_disconnect(struct Curl_easy *data, /* Cleanup NTLM connection-related data */ Curl_http_ntlm_cleanup(conn); #endif +#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) + /* Cleanup NEGOTIATE connection-related data */ + Curl_cleanup_negotiate(conn); +#endif - /* the protocol specific disconnect handler needs a transfer for its - connection! */ + /* the protocol specific disconnect handler and conn_shutdown need a transfer + for the connection! */ conn->data = data; + if(conn->handler->disconnect) /* This is set if protocol-specific cleanups should be made */ conn->handler->disconnect(conn, dead_connection); - /* unlink ourselves! */ - infof(data, "Closing connection %ld\n", conn->connection_id); - Curl_conncache_remove_conn(data, conn, TRUE); - - free_idnconverted_hostname(&conn->host); - free_idnconverted_hostname(&conn->conn_to_host); - free_idnconverted_hostname(&conn->http_proxy.host); - free_idnconverted_hostname(&conn->socks_proxy.host); - - /* this assumes that the pointer is still there after the connection was - detected from the cache */ - Curl_ssl_close(conn, FIRSTSOCKET); - + conn_shutdown(conn); conn_free(conn); return CURLE_OK; } @@ -956,7 +975,7 @@ static bool extract_if_dead(struct connectdata *conn, struct Curl_easy *data) { size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size; - if(!pipeLen && !CONN_INUSE(conn)) { + if(!pipeLen && !CONN_INUSE(conn) && !conn->data) { /* The check for a dead socket makes sense only if there are no handles in pipeline and the connection isn't already marked in use */ @@ -965,7 +984,10 @@ static bool extract_if_dead(struct connectdata *conn, /* The protocol has a special method for checking the state of the connection. Use it to check if the connection is dead. */ unsigned int state; + struct Curl_easy *olddata = conn->data; + conn->data = data; /* use this transfer for now */ state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD); + conn->data = olddata; dead = (state & CONNRESULT_DEAD); } else { @@ -994,7 +1016,6 @@ struct prunedead { static int call_extract_if_dead(struct connectdata *conn, void *param) { struct prunedead *p = (struct prunedead *)param; - conn->data = p->data; /* transfer to use for this check */ if(extract_if_dead(conn, p->data)) { /* stop the iteration here, pass back the connection that was extracted */ p->extracted = conn; @@ -1132,6 +1153,10 @@ ConnectionExists(struct Curl_easy *data, check = curr->ptr; curr = curr->next; + if(check->bits.connect_only) + /* connect-only connections will not be reused */ + continue; + if(extract_if_dead(check, data)) { /* disconnect it */ (void)Curl_disconnect(data, check, /* dead_connection */TRUE); @@ -1262,14 +1287,15 @@ ConnectionExists(struct Curl_easy *data, } } - if(!canpipe && CONN_INUSE(check)) + if(!canpipe && check->data) /* this request can't be pipelined but the checked connection is already in use so we skip it */ continue; - if(CONN_INUSE(check) && (check->data->multi != needle->data->multi)) - /* this could be subject for pipeline/multiplex use, but only - if they belong to the same multi handle */ + if(CONN_INUSE(check) && check->data && + (check->data->multi != needle->data->multi)) + /* this could be subject for pipeline/multiplex use, but only if they + belong to the same multi handle */ continue; if(needle->localdev || needle->localport) { @@ -1685,6 +1711,8 @@ static bool is_ASCII_name(const char *hostname) static void strip_trailing_dot(struct hostname *host) { size_t len; + if(!host || !host->name) + return; len = strlen(host->name); if(len && (host->name[len-1] == '.')) host->name[len-1] = 0; @@ -1749,15 +1777,6 @@ static CURLcode idnconvert_hostname(struct connectdata *conn, infof(data, "IDN support not present, can't parse Unicode domains\n"); #endif } - { - char *hostp; - for(hostp = host->name; *hostp; hostp++) { - if(*hostp <= 32) { - failf(data, "Host name '%s' contains bad letter", host->name); - return CURLE_URL_MALFORMAT; - } - } - } return CURLE_OK; } @@ -1899,8 +1918,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) data->set.proxy_ssl.primary.verifystatus; conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; - conn->ip_version = data->set.ipver; + conn->bits.connect_only = data->set.connect_only; #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ defined(NTLM_WB_ENABLED) @@ -2029,11 +2048,11 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, CURLUcode uc; char *hostname; - Curl_up_free(data); /* cleanup previous leftovers first */ + up_free(data); /* cleanup previous leftovers first */ /* parse the URL */ if(data->set.uh) { - uh = data->set.uh; + uh = data->state.uh = data->set.uh; } else { uh = data->state.uh = curl_url(); @@ -3361,6 +3380,34 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, conn_to_host = conn_to_host->next; } +#ifdef USE_ALTSVC + if(data->asi && !host && (port == -1) && + (conn->handler->protocol == CURLPROTO_HTTPS)) { + /* no connect_to match, try alt-svc! */ + const char *nhost; + int nport; + enum alpnid nalpnid; + bool hit; + host = conn->host.rawalloc; + hit = Curl_altsvc_lookup(data->asi, + ALPN_h1, host, conn->remote_port, /* from */ + &nalpnid, &nhost, &nport /* to */); + if(hit) { + char *hostd = strdup((char *)nhost); + if(!hostd) + return CURLE_OUT_OF_MEMORY; + conn->conn_to_host.rawalloc = hostd; + conn->conn_to_host.name = hostd; + conn->bits.conn_to_host = TRUE; + conn->conn_to_port = nport; + conn->bits.conn_to_port = TRUE; + infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n", + Curl_alpnid2str(ALPN_h1), host, conn->remote_port, + Curl_alpnid2str(nalpnid), hostd, nport); + } + } +#endif + return result; } @@ -3374,6 +3421,8 @@ static CURLcode resolve_server(struct Curl_easy *data, CURLcode result = CURLE_OK; timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + DEBUGASSERT(conn); + DEBUGASSERT(data); /************************************************************* * Resolve the name of the server or proxy *************************************************************/ @@ -3789,9 +3838,8 @@ static CURLcode create_conn(struct Curl_easy *data, (void)conn->handler->done(conn, result, FALSE); goto out; } - - Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ - -1, NULL); /* no upload */ + Curl_attach_connnection(data, conn); + Curl_setup_transfer(data, -1, -1, FALSE, -1); } /* since we skip do_init() */ @@ -3877,8 +3925,9 @@ static CURLcode create_conn(struct Curl_easy *data, /* reuse_fresh is TRUE if we are told to use a new connection by force, but we only acknowledge this option if this is not a re-used connection already (which happens due to follow-location or during a HTTP - authentication phase). */ - if(data->set.reuse_fresh && !data->state.this_is_a_follow) + authentication phase). CONNECT_ONLY transfers also refuse reuse. */ + if((data->set.reuse_fresh && !data->state.this_is_a_follow) || + data->set.connect_only) reuse = FALSE; else reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe); @@ -4170,7 +4219,8 @@ CURLcode Curl_connect(struct Curl_easy *data, connectdata struct, free those here */ Curl_disconnect(data, conn, TRUE); } - else + else if(!data->conn) + /* FILE: transfers already have the connection attached */ Curl_attach_connnection(data, conn); return result; diff --git a/lib/urlapi.c b/lib/urlapi.c index 3af8e939..a19867eb 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.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 @@ -67,12 +67,6 @@ struct Curl_URL { #define DEFAULT_SCHEME "https" -#ifdef DEBUGBUILD -#define UNITTEST -#else -#define UNITTEST static -#endif - static void free_urlhandle(struct Curl_URL *u) { free(u->scheme); @@ -141,7 +135,7 @@ static bool urlchar_needs_escaping(int c) * URL encoding should be skipped for host names, otherwise IDN resolution * will fail. */ -size_t Curl_strlen_url(const char *url, bool relative) +static size_t strlen_url(const char *url, bool relative) { const unsigned char *ptr; size_t newlen = 0; @@ -183,7 +177,7 @@ size_t Curl_strlen_url(const char *url, bool relative) * URL encoding should be skipped for host names, otherwise IDN resolution * will fail. */ -void Curl_strcpy_url(char *output, const char *url, bool relative) +static void strcpy_url(char *output, const char *url, bool relative) { /* we must add this with whitespace-replacing */ bool left = TRUE; @@ -268,7 +262,7 @@ bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen) * The returned pointer must be freed by the caller unless NULL * (returns NULL on out of memory). */ -char *Curl_concat_url(const char *base, const char *relurl) +static char *concat_url(const char *base, const char *relurl) { /*** TRY to append this new path to the old URL @@ -392,7 +386,7 @@ char *Curl_concat_url(const char *base, const char *relurl) letter we replace each space with %20 while it is replaced with '+' on the right side of the '?' letter. */ - newlen = Curl_strlen_url(useurl, !host_changed); + newlen = strlen_url(useurl, !host_changed); urllen = strlen(url_clone); @@ -414,7 +408,7 @@ char *Curl_concat_url(const char *base, const char *relurl) newest[urllen++]='/'; /* then append the new piece on the right side */ - Curl_strcpy_url(&newest[urllen], useurl, !host_changed); + strcpy_url(&newest[urllen], useurl, !host_changed); free(url_clone); @@ -574,15 +568,15 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname) /* scan for byte values < 31 or 127 */ static CURLUcode junkscan(char *part) { - char badbytes[]={ - /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x7f, - 0x00 /* zero terminate */ - }; if(part) { + static const char badbytes[]={ + /* */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x7f, + 0x00 /* zero terminate */ + }; size_t n = strlen(part); size_t nfine = strcspn(part, badbytes); if(nfine != n) @@ -1083,10 +1077,10 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what, return CURLUE_OUT_OF_MEMORY; *part = url; return CURLUE_OK; - break; } default: ptr = NULL; + break; } if(ptr) { *part = strdup(ptr); @@ -1252,7 +1246,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, } /* apply the relative part to create a new URL */ - redired_url = Curl_concat_url(oldurl, part); + redired_url = concat_url(oldurl, part); free(oldurl); if(!redired_url) return CURLUE_OUT_OF_MEMORY; diff --git a/lib/urldata.h b/lib/urldata.h index ff3cc9a6..24187a4c 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -129,12 +129,14 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ #ifdef HAVE_GSSAPI # ifdef HAVE_GSSGNU # include <gss.h> -# elif defined HAVE_GSSMIT +# elif defined HAVE_GSSAPI_GSSAPI_H # include <gssapi/gssapi.h> -# include <gssapi/gssapi_generic.h> # else # include <gssapi.h> # endif +# ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H +# include <gssapi/gssapi_generic.h> +# endif #endif #ifdef HAVE_LIBSSH2_H @@ -154,13 +156,16 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ #define GOOD_EASY_HANDLE(x) \ ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) +/* the type we use for storing a single boolean bit */ +typedef unsigned int bit; + #ifdef HAVE_GSSAPI /* Types needed for krb5-ftp connections */ struct krb5buffer { void *data; size_t size; size_t index; - int eof_flag; + bit eof_flag:1; }; enum protection_level { @@ -198,21 +203,17 @@ struct ssl_connect_data { /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm but at least asked to or meaning to use it. See 'state' for the exact current state of the connection. */ - bool use; ssl_connection_state state; ssl_connect_state connecting_state; #if defined(USE_SSL) struct ssl_backend_data *backend; #endif + bit use:1; }; struct ssl_primary_config { long version; /* what version the client wants to use */ long version_max; /* max supported version the client wants to use*/ - bool verifypeer; /* set TRUE if this is desired */ - bool verifyhost; /* set TRUE if CN/SAN must match hostname */ - bool verifystatus; /* set TRUE if certificate status must be checked */ - bool sessionid; /* cache session IDs or not */ char *CApath; /* certificate dir (doesn't work on windows) */ char *CAfile; /* certificate to verify peer against */ char *clientcert; @@ -220,32 +221,33 @@ struct ssl_primary_config { char *egdsocket; /* path to file containing the EGD daemon socket */ char *cipher_list; /* list of ciphers to use */ char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ + bit verifypeer:1; /* set TRUE if this is desired */ + bit verifyhost:1; /* set TRUE if CN/SAN must match hostname */ + bit verifystatus:1; /* set TRUE if certificate status must be checked */ + bit sessionid:1; /* cache session IDs or not */ }; struct ssl_config_data { struct ssl_primary_config primary; - bool enable_beast; /* especially allow this flaw for interoperability's - sake*/ - bool no_revoke; /* disable SSL certificate revocation checks */ long certverifyresult; /* result from the certificate verification */ char *CRLfile; /* CRL to check certificate revocation */ char *issuercert;/* optional issuer certificate filename */ curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ void *fsslctxp; /* parameter for call back */ - bool certinfo; /* gather lots of certificate info */ - bool falsestart; - char *cert; /* client certificate file name */ char *cert_type; /* format for certificate (default: PEM)*/ char *key; /* private key file name */ char *key_type; /* format for private key (default: PEM) */ char *key_passwd; /* plain text private key password */ - #ifdef USE_TLS_SRP char *username; /* TLS username (for, e.g., SRP) */ char *password; /* TLS password (for, e.g., SRP) */ enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ #endif + bit certinfo:1; /* gather lots of certificate info */ + bit falsestart:1; + bit enable_beast:1; /* allow this flaw for interoperability's sake*/ + bit no_revoke:1; /* disable SSL certificate revocation checks */ }; struct ssl_general_config { @@ -284,12 +286,12 @@ struct digestdata { char *cnonce; char *realm; int algo; - bool stale; /* set true for re-negotiation */ char *opaque; char *qop; char *algorithm; int nc; /* nounce count */ - bool userhash; + bit stale:1; /* set true for re-negotiation */ + bit userhash:1; #endif }; @@ -356,7 +358,9 @@ struct ntlmdata { struct negotiatedata { /* When doing Negotiate (SPNEGO) auth, we first need to send a token and then validate the received one. */ - enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state; + enum { + GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT, GSS_AUTHDONE, GSS_AUTHSUCC + } state; #ifdef HAVE_GSSAPI OM_uint32 status; gss_ctx_id_t context; @@ -378,6 +382,10 @@ struct negotiatedata { size_t output_token_length; #endif #endif + bool noauthpersist; + bool havenoauthpersist; + bool havenegdata; + bool havemultiplerequests; }; #endif @@ -387,69 +395,65 @@ struct negotiatedata { */ struct ConnectBits { /* always modify bits.close with the connclose() and connkeep() macros! */ - bool close; /* if set, we close the connection after this request */ - bool reuse; /* if set, this is a re-used connection */ - bool conn_to_host; /* if set, this connection has a "connect to host" - that overrides the host in the URL */ - bool conn_to_port; /* if set, this connection has a "connect to port" - that overrides the port in the URL (remote port) */ - bool proxy; /* if set, this transfer is done through a proxy - any type */ - bool httpproxy; /* if set, this transfer is done through a http proxy */ - bool socksproxy; /* if set, this transfer is done through a socks proxy */ - bool user_passwd; /* do we use user+password for this connection? */ - bool proxy_user_passwd; /* user+password for the proxy? */ - bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6 - IP address */ - bool ipv6; /* we communicate with a site using an IPv6 address */ - - bool do_more; /* this is set TRUE if the ->curl_do_more() function is - supposed to be called, after ->curl_do() */ - bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set - the first time on the first connect function call */ - bool protoconnstart;/* the protocol layer has STARTED its operation after - the TCP layer connect */ - - bool retry; /* this connection is about to get closed and then - re-attempted at another connection. */ - bool tunnel_proxy; /* if CONNECT is used to "tunnel" through the proxy. - This is implicit when SSL-protocols are used through - proxies, but can also be enabled explicitly by - apps */ - bool authneg; /* TRUE when the auth phase has started, which means - that we are creating a request with an auth header, - but it is not the final request in the auth - negotiation. */ - bool rewindaftersend;/* TRUE when the sending couldn't be stopped even - though it will be discarded. When the whole send - operation is done, we must call the data rewind - callback. */ - bool ftp_use_epsv; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out - EPSV doesn't work we disable it for the forthcoming - requests */ - - bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out - EPRT doesn't work we disable it for the forthcoming - requests */ - bool ftp_use_data_ssl; /* Enabled SSL for the data connection */ - bool netrc; /* name+password provided by netrc */ - bool userpwd_in_url; /* name+password found in url */ - bool stream_was_rewound; /* Indicates that the stream was rewound after a - request read past the end of its response byte - boundary */ - bool proxy_connect_closed; /* set true if a proxy disconnected the - connection in a CONNECT request with auth, so - that libcurl should reconnect and continue. */ - bool bound; /* set true if bind() has already been done on this socket/ - connection */ - bool type_set; /* type= was used in the URL */ - bool multiplex; /* connection is multiplexed */ - - bool tcp_fastopen; /* use TCP Fast Open */ - bool tls_enable_npn; /* TLS NPN extension? */ - bool tls_enable_alpn; /* TLS ALPN extension? */ bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy is complete */ - bool socksproxy_connecting; /* connecting through a socks proxy */ + bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set + the first time on the first connect function call */ + bit close:1; /* if set, we close the connection after this request */ + bit reuse:1; /* if set, this is a re-used connection */ + bit conn_to_host:1; /* if set, this connection has a "connect to host" + that overrides the host in the URL */ + bit conn_to_port:1; /* if set, this connection has a "connect to port" + that overrides the port in the URL (remote port) */ + bit proxy:1; /* if set, this transfer is done through a proxy - any type */ + bit httpproxy:1; /* if set, this transfer is done through a http proxy */ + bit socksproxy:1; /* if set, this transfer is done through a socks proxy */ + bit user_passwd:1; /* do we use user+password for this connection? */ + bit proxy_user_passwd:1; /* user+password for the proxy? */ + bit ipv6_ip:1; /* we communicate with a remote site specified with pure IPv6 + IP address */ + bit ipv6:1; /* we communicate with a site using an IPv6 address */ + bit do_more:1; /* this is set TRUE if the ->curl_do_more() function is + supposed to be called, after ->curl_do() */ + bit protoconnstart:1;/* the protocol layer has STARTED its operation after + the TCP layer connect */ + bit retry:1; /* this connection is about to get closed and then + re-attempted at another connection. */ + bit tunnel_proxy:1; /* if CONNECT is used to "tunnel" through the proxy. + This is implicit when SSL-protocols are used through + proxies, but can also be enabled explicitly by + apps */ + bit authneg:1; /* TRUE when the auth phase has started, which means + that we are creating a request with an auth header, + but it is not the final request in the auth + negotiation. */ + bit rewindaftersend:1;/* TRUE when the sending couldn't be stopped even + though it will be discarded. When the whole send + operation is done, we must call the data rewind + callback. */ + bit ftp_use_epsv:1; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out + EPSV doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_eprt:1; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out + EPRT doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_data_ssl:1; /* Enabled SSL for the data connection */ + bit netrc:1; /* name+password provided by netrc */ + bit userpwd_in_url:1; /* name+password found in url */ + bit stream_was_rewound:1; /* The stream was rewound after a request read + past the end of its response byte boundary */ + bit proxy_connect_closed:1; /* TRUE if a proxy disconnected the connection + in a CONNECT request with auth, so that + libcurl should reconnect and continue. */ + bit bound:1; /* set true if bind() has already been done on this socket/ + connection */ + bit type_set:1; /* type= was used in the URL */ + bit multiplex:1; /* connection is multiplexed */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit tls_enable_npn:1; /* TLS NPN extension? */ + bit tls_enable_alpn:1; /* TLS ALPN extension? */ + bit socksproxy_connecting:1; /* connecting through a socks proxy */ + bit connect_only:1; }; struct hostname { @@ -476,14 +480,13 @@ struct hostname { #define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) #define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) - struct Curl_async { char *hostname; int port; struct Curl_dns_entry *dns; - bool done; /* set TRUE when the lookup is complete */ int status; /* if done is TRUE, this is the status from the callback */ void *os_specific; /* 'struct thread_data' for Windows */ + bit done:1; /* set TRUE when the lookup is complete */ }; #define FIRSTSOCKET 0 @@ -541,25 +544,21 @@ struct dohdata { */ struct SingleRequest { curl_off_t size; /* -1 if unknown at this point */ - curl_off_t *bytecountp; /* return number of bytes read or NULL */ - curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch, -1 means unlimited */ - curl_off_t *writebytecountp; /* return number of bytes written or NULL */ - curl_off_t bytecount; /* total number of bytes read */ curl_off_t writebytecount; /* number of bytes written */ - long headerbytecount; /* only count received headers */ - long deductheadercount; /* this amount of bytes doesn't count when we check - if anything has been transferred at the end of a - connection. We use this counter to make only a - 100 reply (without a following second response - code) result in a CURLE_GOT_NOTHING error code */ + curl_off_t headerbytecount; /* only count received headers */ + curl_off_t deductheadercount; /* this amount of bytes doesn't count when we + check if anything has been transferred at + the end of a connection. We use this + counter to make only a 100 reply (without a + following second response code) result in a + CURLE_GOT_NOTHING error code */ struct curltime start; /* transfer started at this time */ struct curltime now; /* current time */ - bool header; /* incoming data has HTTP header */ enum { HEADER_NORMAL, /* no bad header at all */ HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest @@ -575,7 +574,6 @@ struct SingleRequest { char *str_start; /* within buf */ char *end_ptr; /* within buf */ char *p; /* within headerbuff */ - bool content_range; /* set TRUE if Content-Range: was found */ curl_off_t offset; /* possible resume offset read from the Content-Range: header */ int httpcode; /* error code from the 'HTTP/1.? XXX' or @@ -588,19 +586,8 @@ struct SingleRequest { /* See sec 3.5, RFC2616. */ time_t timeofdoc; long bodywrites; - char *buf; - curl_socket_t maxfd; - int keepon; - - bool upload_done; /* set to TRUE when doing chunked transfer-encoding upload - and we're uploading the last chunk */ - - bool ignorebody; /* we read a response-body but we ignore it! */ - bool ignorecl; /* This HTTP response has no body so we ignore the Content- - Length: header */ - char *location; /* This points to an allocated version of the Location: header data */ char *newurl; /* Set to the new URL to use when a redirect or a retry is @@ -610,24 +597,28 @@ struct SingleRequest { still left in the buffer, aimed for upload. */ ssize_t upload_present; - /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a - buffer, so the next read should read from where this pointer points to, - and the 'upload_present' contains the number of bytes available at this - position */ + /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a + buffer, so the next read should read from where this pointer points to, + and the 'upload_present' contains the number of bytes available at this + position */ char *upload_fromhere; - - bool chunk; /* if set, this is a chunked transfer-encoding */ - bool upload_chunky; /* set TRUE if we are doing chunked transfer-encoding - on upload */ - bool getheader; /* TRUE if header parsing is wanted */ - - bool forbidchunk; /* used only to explicitly forbid chunk-upload for - specific upload buffers. See readmoredata() in - http.c for details. */ - void *protop; /* Allocated protocol-specific data. Each protocol handler makes sure this points to data it needs. */ struct dohdata doh; /* DoH specific data for this request */ + bit header:1; /* incoming data has HTTP header */ + bit content_range:1; /* set TRUE if Content-Range: was found */ + bit upload_done:1; /* set to TRUE when doing chunked transfer-encoding + upload and we're uploading the last chunk */ + bit ignorebody:1; /* we read a response-body but we ignore it! */ + bit ignorecl:1; /* This HTTP response has no body so we ignore the + Content-Length: header */ + bit chunk:1; /* if set, this is a chunked transfer-encoding */ + bit upload_chunky:1; /* set TRUE if we are doing chunked transfer-encoding + on upload */ + bit getheader:1; /* TRUE if header parsing is wanted */ + bit forbidchunk:1; /* used only to explicitly forbid chunk-upload for + specific upload buffers. See readmoredata() in http.c + for details. */ }; /* @@ -775,13 +766,13 @@ struct http_connect_state { char *line_start; char *ptr; /* where to store more data */ curl_off_t cl; /* size of content to read and ignore */ - bool chunked_encoding; enum { TUNNEL_INIT, /* init/default/no tunnel state */ TUNNEL_CONNECT, /* CONNECT has been sent off */ TUNNEL_COMPLETE /* CONNECT response received completely */ } tunnel_state; - bool close_connection; + bit chunked_encoding:1; + bit close_connection:1; }; /* @@ -898,8 +889,6 @@ struct connectdata { #endif struct ssl_primary_config ssl_config; struct ssl_primary_config proxy_ssl_config; - bool tls_upgraded; - struct ConnectBits bits; /* various state-flags for this connection */ /* connecttime: when connect() is called on the current IP address. Used to @@ -946,7 +935,7 @@ struct connectdata { } allocptr; #ifdef HAVE_GSSAPI - int sec_complete; /* if Kerberos is enabled for this connection */ + bit sec_complete:1; /* if Kerberos is enabled for this connection */ enum protection_level command_prot; enum protection_level data_prot; enum protection_level request_data_prot; @@ -961,14 +950,6 @@ struct connectdata { struct kerberos5data krb5; /* variables into the structure definition, */ #endif /* however, some of them are ftp specific. */ - /* the two following *_inuse fields are only flags, not counters in any way. - If TRUE it means the channel is in use, and if FALSE it means the channel - is up for grabs by one. */ - - bool readchannel_inuse; /* whether the read channel is in use by an easy - handle */ - bool writechannel_inuse; /* whether the write channel is in use by an easy - handle */ struct curl_llist send_pipe; /* List of handles waiting to send on this pipeline */ struct curl_llist recv_pipe; /* List of handles waiting to read their @@ -1002,7 +983,11 @@ struct connectdata { #endif #endif - char syserr_buf [256]; /* buffer for Curl_strerror() */ +#ifdef USE_SPNEGO + struct negotiatedata negotiate; /* state data for host Negotiate auth */ + struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ +#endif + /* data used for the asynch name resolve callback */ struct Curl_async async; @@ -1045,8 +1030,16 @@ struct connectdata { #ifdef USE_UNIX_SOCKETS char *unix_domain_socket; - bool abstract_unix_socket; + bit abstract_unix_socket:1; #endif + bit tls_upgraded:1; + /* the two following *_inuse fields are only flags, not counters in any way. + If TRUE it means the channel is in use, and if FALSE it means the channel + is up for grabs by one. */ + bit readchannel_inuse:1; /* whether the read channel is in use by an easy + handle */ + bit writechannel_inuse:1; /* whether the write channel is in use by an easy + handle */ }; /* The end of connectdata. */ @@ -1061,10 +1054,8 @@ struct PureInfo { int httpversion; /* the http version number X.Y = X*10+Y */ time_t filetime; /* If requested, this is might get set. Set to -1 if the time was unretrievable. */ - bool timecond; /* set to TRUE if the time condition didn't match, which - thus made the document NOT get fetched */ - long header_size; /* size of read header(s) in bytes */ - long request_size; /* the amount of bytes sent in the request(s) */ + curl_off_t header_size; /* size of read header(s) in bytes */ + curl_off_t request_size; /* the amount of bytes sent in the request(s) */ unsigned long proxyauthavail; /* what proxy auth types were announced */ unsigned long httpauthavail; /* what host auth types were announced */ long numconnects; /* how many new connection did libcurl created */ @@ -1081,16 +1072,16 @@ struct PureInfo { char conn_primary_ip[MAX_IPADR_LEN]; long conn_primary_port; - char conn_local_ip[MAX_IPADR_LEN]; long conn_local_port; - const char *conn_scheme; unsigned int conn_protocol; - struct curl_certinfo certs; /* info about the certs, only populated in OpenSSL builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ + + bit timecond:1; /* set to TRUE if the time condition didn't match, which + thus made the document NOT get fetched */ }; @@ -1104,7 +1095,6 @@ struct Progress { curl_off_t current_speed; /* uses the currently fastest transfer */ - bool callback; /* set when progress callback is used */ int width; /* screen width at download start */ int flags; /* see progress.h */ @@ -1125,7 +1115,6 @@ struct Progress { struct curltime t_startop; struct curltime t_acceptdata; - bool is_t_startransfer_set; /* upload speed limit */ struct curltime ul_limit_start; @@ -1139,6 +1128,8 @@ struct Progress { curl_off_t speeder[ CURR_TIME ]; struct curltime speeder_time[ CURR_TIME ]; int speeder_c; + bit callback:1; /* set when progress callback is used */ + bit is_t_startransfer_set:1; }; typedef enum { @@ -1150,7 +1141,6 @@ typedef enum { HTTPREQ_PUT, HTTPREQ_HEAD, HTTPREQ_OPTIONS, - HTTPREQ_CUSTOM, HTTPREQ_LAST /* last in list */ } Curl_HttpReq; @@ -1187,12 +1177,12 @@ struct auth { unsigned long picked; unsigned long avail; /* Bitmask for what the server reports to support for this resource */ - bool done; /* TRUE when the auth phase is done and ready to do the *actual* - request */ - bool multipass; /* TRUE if this is not yet authenticated but within the - auth multipass negotiation */ - bool iestyle; /* TRUE if digest should be done IE-style or FALSE if it should - be RFC compliant */ + bit done:1; /* TRUE when the auth phase is done and ready to do the + *actual* request */ + bit multipass:1; /* TRUE if this is not yet authenticated but within the + auth multipass negotiation */ + bit iestyle:1; /* TRUE if digest should be done IE-style or FALSE if it + should be RFC compliant */ }; struct Curl_http2_dep { @@ -1263,11 +1253,6 @@ struct UrlState { /* Points to the connection cache */ struct conncache *conn_cache; - /* when curl_easy_perform() is called, the multi handle is "owned" by - the easy handle so curl_easy_cleanup() on such an easy handle will - also close the multi handle! */ - bool multi_owned_by_easy; - /* buffers to store authentication data in, as parsed from input options */ struct curltime keeps_speed; /* for the progress meter really */ @@ -1280,8 +1265,6 @@ struct UrlState { char *ulbuf; /* allocated upload buffer or NULL */ curl_off_t current_speed; /* the ProgressShow() function sets this, bytes / second */ - bool this_is_a_follow; /* this is a followed Location: request */ - bool refused_stream; /* this was refused, try again */ char *first_host; /* host name of the first (not followed) request. if set, this should be the host name that we will sent authorization to, no else. Used to make Location: @@ -1294,29 +1277,17 @@ struct UrlState { unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */ struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */ char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */ - bool errorbuf; /* Set to TRUE if the error buffer is already filled in. - This must be set to FALSE every time _easy_perform() is - called. */ int os_errno; /* filled in with errno whenever an error occurs */ #ifdef HAVE_SIGNAL /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ void (*prev_signal)(int sig); #endif - bool allow_port; /* Is set.use_port allowed to take effect or not. This - is always set TRUE when curl_easy_perform() is called. */ struct digestdata digest; /* state data for host Digest auth */ struct digestdata proxydigest; /* state data for proxy Digest auth */ -#ifdef USE_SPNEGO - struct negotiatedata negotiate; /* state data for host Negotiate auth */ - struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ -#endif - struct auth authhost; /* auth details for host */ struct auth authproxy; /* auth details for proxy */ - bool authproblem; /* TRUE if there's some problem authenticating */ - void *resolver; /* resolver state, if it is used in the URL state - ares_channel f.e. */ @@ -1332,27 +1303,18 @@ struct UrlState { /* a place to store the most recently set FTP entrypath */ char *most_recent_ftp_entrypath; - /* set after initial USER failure, to prevent an authentication loop */ - bool ftp_trying_alternative; - bool wildcardmatch; /* enable wildcard matching */ int httpversion; /* the lowest HTTP version*10 reported by any server involved in this request */ - bool expect100header; /* TRUE if we added Expect: 100-continue */ #if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \ !defined(__SYMBIAN32__) /* do FTP line-end conversions on most platforms */ #define CURL_DO_LINEEND_CONV /* for FTP downloads: track CRLF sequences that span blocks */ - bool prev_block_had_trailing_cr; + bit prev_block_had_trailing_cr:1; /* for FTP downloads: how many CRLFs did we converted to LFs? */ curl_off_t crlf_conversions; #endif - bool slash_removed; /* set TRUE if the 'path' points to a path where the - initial URL slash separator has been taken off */ - bool use_range; - bool rangestringalloc; /* the range string is malloc()'ed */ - char *range; /* range, if used. See README for detailed specification on this syntax. */ curl_off_t resume_from; /* continue [ftp] transfer from here */ @@ -1368,19 +1330,12 @@ struct UrlState { size_t drain; /* Increased when this stream has data to read, even if its socket is not necessarily is readable. Decreased when checked. */ - bool done; /* set to FALSE when Curl_init_do() is called and set to TRUE - when multi_done() is called, to prevent multi_done() to get - invoked twice when the multi interface is used. */ curl_read_callback fread_func; /* read callback/function */ void *in; /* CURLOPT_READDATA */ struct Curl_easy *stream_depends_on; - bool stream_depends_e; /* set or don't set the Exclusive bit */ int stream_weight; -#ifdef CURLDEBUG - bool conncache_lock; -#endif CURLU *uh; /* URL handle for the current parsed URL */ struct urlpieces up; #ifndef CURL_DISABLE_HTTP @@ -1390,6 +1345,32 @@ struct UrlState { #endif trailers_state trailers_state; /* whether we are sending trailers and what stage are we at */ +#ifdef CURLDEBUG + bit conncache_lock:1; +#endif + /* when curl_easy_perform() is called, the multi handle is "owned" by + the easy handle so curl_easy_cleanup() on such an easy handle will + also close the multi handle! */ + bit multi_owned_by_easy:1; + + bit this_is_a_follow:1; /* this is a followed Location: request */ + bit refused_stream:1; /* this was refused, try again */ + bit errorbuf:1; /* Set to TRUE if the error buffer is already filled in. + This must be set to FALSE every time _easy_perform() is + called. */ + bit allow_port:1; /* Is set.use_port allowed to take effect or not. This + is always set TRUE when curl_easy_perform() is called. */ + bit authproblem:1; /* TRUE if there's some problem authenticating */ + /* set after initial USER failure, to prevent an authentication loop */ + bit ftp_trying_alternative:1; + bit wildcardmatch:1; /* enable wildcard matching */ + bit expect100header:1; /* TRUE if we added Expect: 100-continue */ + bit use_range:1; + bit rangestringalloc:1; /* the range string is malloc()'ed */ + bit done:1; /* set to FALSE when Curl_init_do() is called and set to TRUE + when multi_done() is called, to prevent multi_done() to get + invoked twice when the multi interface is used. */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ }; @@ -1402,14 +1383,15 @@ struct UrlState { struct DynamicStatic { char *url; /* work URL, copied from UserDefined */ - bool url_alloc; /* URL string is malloc()'ed */ char *referer; /* referer string */ - bool referer_alloc; /* referer string is malloc()ed */ struct curl_slist *cookielist; /* list of cookie files set by curl_easy_setopt(COOKIEFILE) calls */ struct curl_slist *resolve; /* set to point to the set.resolve list when this should be dealt with in pretransfer */ - bool wildcard_resolve; /* Set to true if any resolve change is a wildcard */ + bit url_alloc:1; /* URL string is malloc()'ed */ + bit referer_alloc:1; /* referer string is malloc()ed */ + bit wildcard_resolve:1; /* Set to true if any resolve change is a + wildcard */ }; /* @@ -1502,6 +1484,9 @@ enum dupstring { #endif STRING_TARGET, /* CURLOPT_REQUEST_TARGET */ STRING_DOH, /* CURLOPT_DOH_URL */ +#ifdef USE_ALTSVC + STRING_ALTSVC, /* CURLOPT_ALTSVC */ +#endif /* -- end of zero-terminated strings -- */ STRING_LASTZEROTERMINATED, @@ -1539,8 +1524,6 @@ struct UserDefined { int keep_post; /* keep POSTs as POSTs after a 30x request; each bit represents a request, from 301 to 303 */ - bool free_referer; /* set TRUE if 'referer' points to a string we - allocated */ void *postfields; /* if POST, set the fields' values here */ curl_seek_callback seek_func; /* function that seeks the input */ curl_off_t postfieldsize; /* if POST, this might have a size to use instead @@ -1553,8 +1536,6 @@ struct UserDefined { curl_write_callback fwrite_header; /* function that stores headers */ curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */ curl_read_callback fread_func_set; /* function that reads the input */ - int is_fread_set; /* boolean, has read callback been set to non-NULL? */ - int is_fwrite_set; /* boolean, has write callback been set to non-NULL? */ curl_progress_callback fprogress; /* OLD and deprecated progress callback */ curl_xferinfo_callback fxferinfo; /* progress callback */ curl_debug_callback fdebug; /* function that write informational data */ @@ -1586,7 +1567,6 @@ struct UserDefined { long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */ long server_response_timeout; /* in milliseconds, 0 means no timeout */ long tftp_blksize; /* in bytes, 0 means use default */ - bool tftp_no_options; /* do not send TFTP options requests */ curl_off_t filesize; /* size of file to upload, -1 means unknown */ long low_speed_limit; /* bytes/second */ long low_speed_time; /* number of seconds */ @@ -1598,9 +1578,6 @@ struct UserDefined { struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */ struct curl_httppost *httppost; /* linked list of old POST data */ curl_mimepart mimepost; /* MIME/POST data. */ - bool sep_headers; /* handle host and proxy headers separately */ - bool cookiesession; /* new cookie session? */ - bool crlf; /* convert crlf on ftp upload(?) */ struct curl_slist *quote; /* after connection is established */ struct curl_slist *postquote; /* after the transfer */ struct curl_slist *prequote; /* before the transfer, after type */ @@ -1619,7 +1596,6 @@ struct UserDefined { Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ long httpversion; /* when non-zero, a specific HTTP version requested to be used in the library's request(s) */ - bool strip_path_slash; /* strip off initial slash from path */ struct ssl_config_data ssl; /* user defined SSL stuff */ struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ struct ssl_general_config general_ssl; /* general user defined SSL stuff */ @@ -1629,87 +1605,33 @@ struct UserDefined { size_t upload_buffer_size; /* size of upload buffer to use, keep it >= CURL_MAX_WRITE_SIZE */ void *private_data; /* application-private data */ - struct curl_slist *http200aliases; /* linked list of aliases for http200 */ - long ipver; /* the CURL_IPRESOLVE_* defines in the public header file 0 - whatever, 1 - v2, 2 - v6 */ - curl_off_t max_filesize; /* Maximum file size to download */ - curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */ - int ftp_create_missing_dirs; /* 1 - create directories that don't exist 2 - the same but also allow MKD to fail once */ - curl_sshkeycallback ssh_keyfunc; /* key matching callback */ void *ssh_keyfunc_userp; /* custom pointer to callback */ - bool ssh_compression; /* enable SSH compression */ - -/* Here follows boolean settings that define how to behave during - this session. They are STATIC, set by libcurl users or at least initially - and they don't change during operations. */ - bool get_filetime; /* get the time and get of the remote file */ - bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */ - bool prefer_ascii; /* ASCII rather than binary */ - bool ftp_append; /* append, not overwrite, on upload */ - bool ftp_list_only; /* switch FTP command for listing directories */ - bool ftp_use_port; /* use the FTP PORT command */ - bool hide_progress; /* don't use the progress meter */ - bool http_fail_on_error; /* fail on HTTP error codes >= 400 */ - bool http_keep_sending_on_error; /* for HTTP status codes >= 300 */ - bool http_follow_location; /* follow HTTP redirects */ - bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */ - bool allow_auth_to_other_hosts; - bool include_header; /* include received protocol headers in data output */ - bool http_set_referer; /* is a custom referer used */ - bool http_auto_referer; /* set "correct" referer when following location: */ - bool opt_no_body; /* as set with CURLOPT_NOBODY */ - bool upload; /* upload request */ enum CURL_NETRC_OPTION use_netrc; /* defined in include/curl.h */ - bool verbose; /* output verbosity */ - bool krb; /* Kerberos connection requested */ - bool reuse_forbid; /* forbidden to be reused, close after use */ - bool reuse_fresh; /* do not re-use an existing connection */ - bool ftp_use_epsv; /* if EPSV is to be attempted or not */ - bool ftp_use_eprt; /* if EPRT is to be attempted or not */ - bool ftp_use_pret; /* if PRET is to be used before PASV or not */ - curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or IMAP or POP3 or others! */ curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */ curl_ftpccc ftp_ccc; /* FTP CCC options */ - bool no_signal; /* do not use any signal/alarm handler */ - bool global_dns_cache; /* subject for future removal */ - bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */ - bool ignorecl; /* ignore content length */ - bool ftp_skip_ip; /* skip the IP address the FTP server passes on to - us */ - bool connect_only; /* make connection, let application use the socket */ - long ssh_auth_types; /* allowed SSH auth types */ - bool http_te_skip; /* pass the raw body data to the user, even when - transfer-encoded (chunked, compressed) */ - bool http_ce_skip; /* pass the raw body data to the user, even when - content-encoded (chunked, compressed) */ long new_file_perms; /* Permissions to use when creating remote files */ long new_directory_perms; /* Permissions to use when creating remote dirs */ - bool proxy_transfer_mode; /* set transfer mode (;type=<a|i>) when doing FTP - via an HTTP proxy */ + long ssh_auth_types; /* allowed SSH auth types */ char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */ unsigned int scope_id; /* Scope id for IPv6 */ long allowed_protocols; long redir_protocols; -#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) - bool socks5_gssapi_nec; /* Flag to support NEC SOCKS5 server */ -#endif struct curl_slist *mail_rcpt; /* linked list of mail recipients */ - bool sasl_ir; /* Enable/disable SASL initial response */ /* Common RTSP header options */ Curl_RtspReq rtspreq; /* RTSP request type */ long rtspversion; /* like httpversion, for RTSP */ - bool wildcard_enabled; /* enable wildcard matching */ curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer starts */ curl_chunk_end_callback chunk_end; /* called after part transferring @@ -1721,47 +1643,102 @@ struct UserDefined { long gssapi_delegation; /* GSS-API credential delegation, see the documentation of CURLOPT_GSSAPI_DELEGATION */ - bool tcp_keepalive; /* use TCP keepalives */ long tcp_keepidle; /* seconds in idle before sending keepalive probe */ long tcp_keepintvl; /* seconds between TCP keepalive probes */ - bool tcp_fastopen; /* use TCP Fast Open */ - size_t maxconnects; /* Max idle connections in the connection cache */ + size_t maxconnects; /* Max idle connections in the connection cache */ - bool ssl_enable_npn; /* TLS NPN extension? */ - bool ssl_enable_alpn; /* TLS ALPN extension? */ - bool path_as_is; /* allow dotdots? */ - bool pipewait; /* wait for pipe/multiplex status before starting a - new connection */ long expect_100_timeout; /* in milliseconds */ - bool suppress_connect_headers; /* suppress proxy CONNECT response headers - from user callbacks */ - - bool dns_shuffle_addresses; /* whether to shuffle addresses before use */ - struct Curl_easy *stream_depends_on; - bool stream_depends_e; /* set or don't set the Exclusive bit */ int stream_weight; - - bool haproxyprotocol; /* whether to send HAProxy PROXY protocol v1 header */ - struct Curl_http2_dep *stream_dependents; - bool abstract_unix_socket; - curl_resolver_start_callback resolver_start; /* optional callback called before resolver start */ void *resolver_start_client; /* pointer to pass to resolver start callback */ - bool disallow_username_in_url; /* disallow username in url */ long upkeep_interval_ms; /* Time between calls for connection upkeep. */ - bool doh; /* DNS-over-HTTPS enabled */ - bool doh_get; /* use GET for DoH requests, instead of POST */ - bool http09_allowed; /* allow HTTP/0.9 responses */ multidone_func fmultidone; struct Curl_easy *dohfor; /* this is a DoH request for that transfer */ CURLU *uh; /* URL handle for the current parsed URL */ void *trailer_data; /* pointer to pass to trailer data callback */ curl_trailer_callback trailer_callback; /* trailing data callback */ + bit is_fread_set:1; /* has read callback been set to non-NULL? */ + bit is_fwrite_set:1; /* has write callback been set to non-NULL? */ + bit free_referer:1; /* set TRUE if 'referer' points to a string we + allocated */ + bit tftp_no_options:1; /* do not send TFTP options requests */ + bit sep_headers:1; /* handle host and proxy headers separately */ + bit cookiesession:1; /* new cookie session? */ + bit crlf:1; /* convert crlf on ftp upload(?) */ + bit strip_path_slash:1; /* strip off initial slash from path */ + bit ssh_compression:1; /* enable SSH compression */ + +/* Here follows boolean settings that define how to behave during + this session. They are STATIC, set by libcurl users or at least initially + and they don't change during operations. */ + bit get_filetime:1; /* get the time and get of the remote file */ + bit tunnel_thru_httpproxy:1; /* use CONNECT through a HTTP proxy */ + bit prefer_ascii:1; /* ASCII rather than binary */ + bit ftp_append:1; /* append, not overwrite, on upload */ + bit ftp_list_only:1; /* switch FTP command for listing directories */ + bit ftp_use_port:1; /* use the FTP PORT command */ + bit hide_progress:1; /* don't use the progress meter */ + bit http_fail_on_error:1; /* fail on HTTP error codes >= 400 */ + bit http_keep_sending_on_error:1; /* for HTTP status codes >= 300 */ + bit http_follow_location:1; /* follow HTTP redirects */ + bit http_transfer_encoding:1; /* request compressed HTTP + transfer-encoding */ + bit allow_auth_to_other_hosts:1; + bit include_header:1; /* include received protocol headers in data output */ + bit http_set_referer:1; /* is a custom referer used */ + bit http_auto_referer:1; /* set "correct" referer when following + location: */ + bit opt_no_body:1; /* as set with CURLOPT_NOBODY */ + bit upload:1; /* upload request */ + bit verbose:1; /* output verbosity */ + bit krb:1; /* Kerberos connection requested */ + bit reuse_forbid:1; /* forbidden to be reused, close after use */ + bit reuse_fresh:1; /* do not re-use an existing connection */ + bit ftp_use_epsv:1; /* if EPSV is to be attempted or not */ + bit ftp_use_eprt:1; /* if EPRT is to be attempted or not */ + bit ftp_use_pret:1; /* if PRET is to be used before PASV or not */ + + bit no_signal:1; /* do not use any signal/alarm handler */ + bit global_dns_cache:1; /* subject for future removal */ + bit tcp_nodelay:1; /* whether to enable TCP_NODELAY or not */ + bit ignorecl:1; /* ignore content length */ + bit ftp_skip_ip:1; /* skip the IP address the FTP server passes on to + us */ + bit connect_only:1; /* make connection, let application use the socket */ + bit http_te_skip:1; /* pass the raw body data to the user, even when + transfer-encoded (chunked, compressed) */ + bit http_ce_skip:1; /* pass the raw body data to the user, even when + content-encoded (chunked, compressed) */ + bit proxy_transfer_mode:1; /* set transfer mode (;type=<a|i>) when doing + FTP via an HTTP proxy */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + bit socks5_gssapi_nec:1; /* Flag to support NEC SOCKS5 server */ +#endif + bit sasl_ir:1; /* Enable/disable SASL initial response */ + bit wildcard_enabled:1; /* enable wildcard matching */ + bit tcp_keepalive:1; /* use TCP keepalives */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit ssl_enable_npn:1; /* TLS NPN extension? */ + bit ssl_enable_alpn:1;/* TLS ALPN extension? */ + bit path_as_is:1; /* allow dotdots? */ + bit pipewait:1; /* wait for pipe/multiplex status before starting a + new connection */ + bit suppress_connect_headers:1; /* suppress proxy CONNECT response headers + from user callbacks */ + bit dns_shuffle_addresses:1; /* whether to shuffle addresses before use */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ + bit haproxyprotocol:1; /* whether to send HAProxy PROXY protocol v1 + header */ + bit abstract_unix_socket:1; + bit disallow_username_in_url:1; /* disallow username in url */ + bit doh:1; /* DNS-over-HTTPS enabled */ + bit doh_get:1; /* use GET for DoH requests, instead of POST */ + bit http09_allowed:1; /* allow HTTP/0.9 responses */ }; struct Names { @@ -1826,6 +1803,9 @@ struct Curl_easy { NOTE that the 'cookie' field in the UserDefined struct defines if the "engine" is to be used or not. */ +#ifdef USE_ALTSVC + struct altsvcinfo *asi; /* the alt-svc cache */ +#endif struct Progress progress; /* for all the progress meter data */ struct UrlState state; /* struct for fields used for state info and other dynamic purposes */ diff --git a/lib/vauth/spnego_gssapi.c b/lib/vauth/spnego_gssapi.c index 4a48bdd2..7c4bd4b5 100644 --- a/lib/vauth/spnego_gssapi.c +++ b/lib/vauth/spnego_gssapi.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2016, 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 @@ -273,6 +273,11 @@ void Curl_auth_spnego_cleanup(struct negotiatedata *nego) /* Reset any variables */ nego->status = 0; + nego->state = GSS_AUTHNONE; + nego->noauthpersist = FALSE; + nego->havenoauthpersist = FALSE; + nego->havenegdata = FALSE; + nego->havemultiplerequests = FALSE; } #endif /* HAVE_GSSAPI && USE_SPNEGO */ diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c index 00d84046..0171ec52 100644 --- a/lib/vauth/spnego_sspi.c +++ b/lib/vauth/spnego_sspi.c @@ -248,8 +248,9 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, free(chlg); if(GSS_ERROR(nego->status)) { + char buffer[STRERROR_LEN]; failf(data, "InitializeSecurityContext failed: %s", - Curl_sspi_strerror(data->conn, nego->status)); + Curl_sspi_strerror(nego->status, buffer, sizeof(buffer))); return CURLE_OUT_OF_MEMORY; } @@ -342,6 +343,11 @@ void Curl_auth_spnego_cleanup(struct negotiatedata *nego) /* Reset any variables */ nego->status = 0; nego->token_max = 0; + nego->state = GSS_AUTHNONE; + nego->noauthpersist = FALSE; + nego->havenoauthpersist = FALSE; + nego->havenegdata = FALSE; + nego->havemultiplerequests = FALSE; } #endif /* USE_WINDOWS_SSPI && USE_SPNEGO */ diff --git a/lib/version.c b/lib/version.c index e553100c..9369ae8e 100644 --- a/lib/version.c +++ b/lib/version.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 @@ -212,6 +212,10 @@ char *curl_version(void) } #endif + /* Silent scan-build even if librtmp is not enabled. */ + (void) left; + (void) ptr; + initialized = true; return version; } @@ -366,6 +370,9 @@ static curl_version_info_data version_info = { #if defined(HAVE_BROTLI) | CURL_VERSION_BROTLI #endif +#if defined(USE_ALTSVC) + | CURL_VERSION_ALTSVC +#endif , NULL, /* ssl_version */ 0, /* ssl_version_num, this is kept at zero */ diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c index ea96cf65..c7a3268e 100644 --- a/lib/vtls/cyassl.c +++ b/lib/vtls/cyassl.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 @@ -67,15 +67,6 @@ and that's a problem since options.h hasn't been included yet. */ #endif #endif -/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC - supported curve extension in options.h. Note ECC is enabled separately. */ -#ifndef HAVE_SUPPORTED_CURVES -#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \ - defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE) -#define HAVE_SUPPORTED_CURVES -#endif -#endif - #include <limits.h> #include "urldata.h" @@ -364,16 +355,6 @@ cyassl_connect_step1(struct connectdata *conn, } #endif -#ifdef HAVE_SUPPORTED_CURVES - /* CyaSSL/wolfSSL does not send the supported ECC curves ext automatically: - https://github.com/wolfSSL/wolfssl/issues/366 - The supported curves below are those also supported by OpenSSL 1.0.2 and - in the same order. */ - CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x17); /* secp256r1 */ - CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x19); /* secp521r1 */ - CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x18); /* secp384r1 */ -#endif - /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { CURLcode result = CURLE_OK; diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 9035ec48..e224861c 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.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 @@ -1423,11 +1423,6 @@ gtls_connect_step3(struct connectdata *conn, size = sizeof(certbuf); gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size); infof(data, "\t issuer: %s\n", certbuf); - - /* compression algorithm (if any) */ - ptr = gnutls_compression_get_name(gnutls_compression_get(session)); - /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */ - infof(data, "\t compression: %s\n", ptr); #endif gnutls_x509_crt_deinit(x509_cert); diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index bb6a757b..27a9402c 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -716,6 +716,8 @@ mbed_connect_step3(struct connectdata *conn, ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid); if(ret) { + if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED) + mbedtls_ssl_session_free(our_ssl_sessionid); free(our_ssl_sessionid); failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; @@ -729,6 +731,7 @@ mbed_connect_step3(struct connectdata *conn, retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); Curl_ssl_sessionid_unlock(conn); if(retcode) { + mbedtls_ssl_session_free(our_ssl_sessionid); free(our_ssl_sessionid); failf(data, "failed to store ssl session"); return retcode; @@ -813,9 +816,14 @@ static void Curl_mbedtls_session_free(void *ptr) static size_t Curl_mbedtls_version(char *buffer, size_t size) { +#ifdef MBEDTLS_VERSION_C + /* if mbedtls_version_get_number() is available it is better */ unsigned int version = mbedtls_version_get_number(); return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24, (version>>16)&0xff, (version>>8)&0xff); +#else + return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING); +#endif } static CURLcode Curl_mbedtls_random(struct Curl_easy *data, diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 9d11b89e..eff5c210 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -65,6 +65,10 @@ #include <openssl/buffer.h> #include <openssl/pkcs12.h> +#ifdef USE_AMISSL +#include "amigaos.h" +#endif + #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP) #include <openssl/ocsp.h> #endif @@ -820,8 +824,11 @@ int cert_stuff(struct connectdata *conn, fail: EVP_PKEY_free(pri); X509_free(x509); +#ifdef USE_AMISSL + sk_X509_pop_free(ca, Curl_amiga_X509_free); +#else sk_X509_pop_free(ca, X509_free); - +#endif if(!cert_done) return 0; /* failure! */ break; @@ -831,15 +838,15 @@ int cert_stuff(struct connectdata *conn, return 0; } - file_type = do_file_type(key_type); + if(!key_file) + key_file = cert_file; + else + file_type = do_file_type(key_type); switch(file_type) { case SSL_FILETYPE_PEM: if(cert_done) break; - if(!key_file) - /* cert & key can only be in PEM case in the same file */ - key_file = cert_file; /* FALLTHROUGH */ case SSL_FILETYPE_ASN1: if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { @@ -2808,6 +2815,12 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) connssl->connecting_state = ssl_connect_2_writing; return CURLE_OK; } +#ifdef SSL_ERROR_WANT_ASYNC + if(SSL_ERROR_WANT_ASYNC == detail) { + connssl->connecting_state = ssl_connect_2; + return CURLE_OK; + } +#endif else { /* untreated error */ unsigned long errdetail; diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index c8574f56..39ac080e 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -324,6 +324,9 @@ get_alg_id_by_name(char *name) #ifdef CALG_ECDSA CIPHEROPTION(CALG_ECDSA); #endif +#ifdef CALG_ECDH_EPHEM + CIPHEROPTION(CALG_ECDH_EPHEM); +#endif return 0; } @@ -433,8 +436,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; - infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", - hostname, conn->remote_port); + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", + hostname, conn->remote_port)); if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, VERSION_LESS_THAN_EQUAL)) { @@ -494,12 +498,13 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { BACKEND->cred = old_cred; - infof(data, "schannel: re-using existing credential handle\n"); + DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); /* increment the reference counter of the credential/session handle */ BACKEND->cred->refcount++; - infof(data, "schannel: incremented credential handle refcount = %d\n", - BACKEND->cred->refcount); + DEBUGF(infof(data, + "schannel: incremented credential handle refcount = %d\n", + BACKEND->cred->refcount)); } Curl_ssl_sessionid_unlock(conn); } @@ -522,26 +527,28 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; - infof(data, "schannel: disabled server certificate revocation " - "checks\n"); + DEBUGF(infof(data, "schannel: disabled server certificate revocation " + "checks\n")); } else { schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; - infof(data, "schannel: checking server certificate revocation\n"); + DEBUGF(infof(data, + "schannel: checking server certificate revocation\n")); } } else { schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; - infof(data, "schannel: disabled server certificate revocation checks\n"); + DEBUGF(infof(data, + "schannel: disabled server cert revocation checks\n")); } if(!conn->ssl_config.verifyhost) { schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; - infof(data, "schannel: verifyhost setting prevents Schannel from " - "comparing the supplied target name with the subject " - "names in server certificates.\n"); + DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " + "comparing the supplied target name with the subject " + "names in server certificates.\n")); } switch(conn->ssl_config.version) { @@ -680,8 +687,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) CertFreeCertificateContext(client_certs[0]); if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; failf(data, "schannel: AcquireCredentialsHandle failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); Curl_safefree(BACKEND->cred); switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: @@ -796,15 +804,16 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) Curl_unicodefree(host_name); if(sspi_status != SEC_I_CONTINUE_NEEDED) { + char buffer[STRERROR_LEN]; Curl_safefree(BACKEND->ctxt); switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: failf(data, "schannel: initial InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_OUT_OF_MEMORY; case SEC_E_WRONG_PRINCIPAL: failf(data, "schannel: SNI or certificate check failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_PEER_FAILED_VERIFICATION; /* case SEC_E_INVALID_HANDLE: @@ -819,13 +828,13 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) */ default: failf(data, "schannel: initial InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_SSL_CONNECT_ERROR; } } - infof(data, "schannel: sending initial handshake data: " - "sending %lu bytes...\n", outbuf.cbBuffer); + DEBUGF(infof(data, "schannel: sending initial handshake data: " + "sending %lu bytes...\n", outbuf.cbBuffer)); /* send initial handshake data which is now stored in output buffer */ result = Curl_write_plain(conn, conn->sock[sockindex], outbuf.pvBuffer, @@ -837,8 +846,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; } - infof(data, "schannel: sent initial handshake data: " - "sent %zd bytes\n", written); + DEBUGF(infof(data, "schannel: sent initial handshake data: " + "sent %zd bytes\n", written)); BACKEND->recv_unrecoverable_err = CURLE_OK; BACKEND->recv_sspi_close_notify = false; @@ -874,8 +883,9 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; - infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", - hostname, conn->remote_port); + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", + hostname, conn->remote_port)); if(!BACKEND->cred || !BACKEND->ctxt) return CURLE_SSL_CONNECT_ERROR; @@ -934,8 +944,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) if(result == CURLE_AGAIN) { if(connssl->connecting_state != ssl_connect_2_writing) connssl->connecting_state = ssl_connect_2_reading; - infof(data, "schannel: failed to receive handshake, " - "need more data\n"); + DEBUGF(infof(data, "schannel: failed to receive handshake, " + "need more data\n")); return CURLE_OK; } else if((result != CURLE_OK) || (nread == 0)) { @@ -947,11 +957,12 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* increase encrypted data buffer offset */ BACKEND->encdata_offset += nread; BACKEND->encdata_is_incomplete = false; - infof(data, "schannel: encrypted data got %zd\n", nread); + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); /* setup input buffers */ InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset), @@ -994,7 +1005,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { BACKEND->encdata_is_incomplete = true; connssl->connecting_state = ssl_connect_2_reading; - infof(data, "schannel: received incomplete message, need more data\n"); + DEBUGF(infof(data, + "schannel: received incomplete message, need more data\n")); return CURLE_OK; } @@ -1005,7 +1017,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; connssl->connecting_state = ssl_connect_2_writing; - infof(data, "schannel: a client certificate has been requested\n"); + DEBUGF(infof(data, + "schannel: a client certificate has been requested\n")); return CURLE_OK; } @@ -1014,8 +1027,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) for(i = 0; i < 3; i++) { /* search for handshake tokens that need to be send */ if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { - infof(data, "schannel: sending next handshake data: " - "sending %lu bytes...\n", outbuf[i].cbBuffer); + DEBUGF(infof(data, "schannel: sending next handshake data: " + "sending %lu bytes...\n", outbuf[i].cbBuffer)); /* send handshake token to server */ result = Curl_write_plain(conn, conn->sock[sockindex], @@ -1036,14 +1049,15 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) } } else { + char buffer[STRERROR_LEN]; switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: failf(data, "schannel: next InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_OUT_OF_MEMORY; case SEC_E_WRONG_PRINCIPAL: failf(data, "schannel: SNI or certificate check failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_PEER_FAILED_VERIFICATION; /* case SEC_E_INVALID_HANDLE: @@ -1058,14 +1072,15 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) */ default: failf(data, "schannel: next InitializeSecurityContext failed: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); return CURLE_SSL_CONNECT_ERROR; } } /* check if there was additional remaining encrypted data */ if(inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) { - infof(data, "schannel: encrypted data length: %lu\n", inbuf[1].cbBuffer); + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[1].cbBuffer)); /* There are two cases where we could be getting extra data here: 1) If we're renegotiating a connection and the handshake is already @@ -1104,7 +1119,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* check if the handshake is complete */ if(sspi_status == SEC_E_OK) { connssl->connecting_state = ssl_connect_3; - infof(data, "schannel: SSL/TLS handshake complete\n"); + DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); } pubkey_ptr = SSL_IS_PROXY() ? @@ -1190,7 +1205,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; -#ifndef CURL_DISABLE_VERBOSE_STRINGS +#ifdef DEBUGBUILD const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; #endif @@ -1200,8 +1215,9 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", - hostname, conn->remote_port); + DEBUGF(infof(data, + "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", + hostname, conn->remote_port)); if(!BACKEND->cred) return CURLE_SSL_CONNECT_ERROR; @@ -1266,7 +1282,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) sockindex)); if(incache) { if(old_cred != BACKEND->cred) { - infof(data, "schannel: old credential handle is stale, removing\n"); + DEBUGF(infof(data, + "schannel: old credential handle is stale, removing\n")); /* we're not taking old_cred ownership here, no refcount++ is needed */ Curl_ssl_delsessionid(conn, (void *)old_cred); incache = FALSE; @@ -1284,7 +1301,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) else { /* this cred session is now also referenced by sessionid cache */ BACKEND->cred->refcount++; - infof(data, "schannel: stored credential handle in session cache\n"); + DEBUGF(infof(data, + "schannel: stored credential handle in session cache\n")); } } Curl_ssl_sessionid_unlock(conn); @@ -1615,7 +1633,7 @@ schannel_recv(struct connectdata *conn, int sockindex, * handled in the cleanup. */ - infof(data, "schannel: client wants to read %zu bytes\n", len); + DEBUGF(infof(data, "schannel: client wants to read %zu bytes\n", len)); *err = CURLE_OK; if(len && len <= BACKEND->decdata_offset) { @@ -1660,12 +1678,13 @@ schannel_recv(struct connectdata *conn, int sockindex, BACKEND->encdata_buffer = reallocated_buffer; BACKEND->encdata_length = reallocated_length; size = BACKEND->encdata_length - BACKEND->encdata_offset; - infof(data, "schannel: encdata_buffer resized %zu\n", - BACKEND->encdata_length); + DEBUGF(infof(data, "schannel: encdata_buffer resized %zu\n", + BACKEND->encdata_length)); } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); /* read encrypted data from socket */ *err = Curl_read_plain(conn->sock[sockindex], @@ -1675,7 +1694,8 @@ schannel_recv(struct connectdata *conn, int sockindex, if(*err) { nread = -1; if(*err == CURLE_AGAIN) - infof(data, "schannel: Curl_read_plain returned CURLE_AGAIN\n"); + DEBUGF(infof(data, + "schannel: Curl_read_plain returned CURLE_AGAIN\n")); else if(*err == CURLE_RECV_ERROR) infof(data, "schannel: Curl_read_plain returned CURLE_RECV_ERROR\n"); else @@ -1683,17 +1703,18 @@ schannel_recv(struct connectdata *conn, int sockindex, } else if(nread == 0) { BACKEND->recv_connection_closed = true; - infof(data, "schannel: server closed the connection\n"); + DEBUGF(infof(data, "schannel: server closed the connection\n")); } else if(nread > 0) { BACKEND->encdata_offset += (size_t)nread; BACKEND->encdata_is_incomplete = false; - infof(data, "schannel: encrypted data got %zd\n", nread); + DEBUGF(infof(data, "schannel: encrypted data got %zd\n", nread)); } } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); /* decrypt loop */ while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK && @@ -1721,8 +1742,8 @@ schannel_recv(struct connectdata *conn, int sockindex, /* check for successfully decrypted data, even before actual renegotiation or shutdown of the connection context */ if(inbuf[1].BufferType == SECBUFFER_DATA) { - infof(data, "schannel: decrypted data length: %lu\n", - inbuf[1].cbBuffer); + DEBUGF(infof(data, "schannel: decrypted data length: %lu\n", + inbuf[1].cbBuffer)); /* increase buffer in order to fit the received amount of data */ size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ? @@ -1754,15 +1775,16 @@ schannel_recv(struct connectdata *conn, int sockindex, BACKEND->decdata_offset += size; } - infof(data, "schannel: decrypted data added: %zu\n", size); - infof(data, "schannel: decrypted data cached: offset %zu length %zu\n", - BACKEND->decdata_offset, BACKEND->decdata_length); + DEBUGF(infof(data, "schannel: decrypted data added: %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted cached: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); } /* check for remaining encrypted data */ if(inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) { - infof(data, "schannel: encrypted data length: %lu\n", - inbuf[3].cbBuffer); + DEBUGF(infof(data, "schannel: encrypted data length: %lu\n", + inbuf[3].cbBuffer)); /* check if the remaining data is less than the total amount * and therefore begins after the already processed data @@ -1776,8 +1798,9 @@ schannel_recv(struct connectdata *conn, int sockindex, BACKEND->encdata_offset = inbuf[3].cbBuffer; } - infof(data, "schannel: encrypted data cached: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted cached: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); } else { /* reset encrypted buffer offset, because there is no data remaining */ @@ -1831,22 +1854,25 @@ schannel_recv(struct connectdata *conn, int sockindex, goto cleanup; } else { + char buffer[STRERROR_LEN]; *err = CURLE_RECV_ERROR; infof(data, "schannel: failed to read data from server: %s\n", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); goto cleanup; } } - infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n", - BACKEND->encdata_offset, BACKEND->encdata_length); + DEBUGF(infof(data, + "schannel: encrypted data buffer: offset %zu length %zu\n", + BACKEND->encdata_offset, BACKEND->encdata_length)); - infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", - BACKEND->decdata_offset, BACKEND->decdata_length); + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); cleanup: /* Warning- there is no guarantee the encdata state is valid at this point */ - infof(data, "schannel: schannel_recv cleanup\n"); + DEBUGF(infof(data, "schannel: schannel_recv cleanup\n")); /* Error if the connection has closed without a close_notify. Behavior here is a matter of debate. We don't want to be vulnerable to a @@ -1879,10 +1905,10 @@ cleanup: memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size, BACKEND->decdata_offset - size); BACKEND->decdata_offset -= size; - - infof(data, "schannel: decrypted data returned %zu\n", size); - infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n", - BACKEND->decdata_offset, BACKEND->decdata_length); + DEBUGF(infof(data, "schannel: decrypted data returned %zu\n", size)); + DEBUGF(infof(data, + "schannel: decrypted data buffer: offset %zu length %zu\n", + BACKEND->decdata_offset, BACKEND->decdata_length)); *err = CURLE_OK; return (ssize_t)size; } @@ -1960,6 +1986,8 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; + DEBUGASSERT(data); + infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", hostname, conn->remote_port); @@ -1979,9 +2007,11 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle, &BuffDesc); - if(sspi_status != SEC_E_OK) + if(sspi_status != SEC_E_OK) { + char buffer[STRERROR_LEN]; failf(data, "schannel: ApplyControlToken failure: %s", - Curl_sspi_strerror(conn, sspi_status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + } host_name = Curl_convert_UTF8_to_tchar(hostname); if(!host_name) @@ -2023,7 +2053,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) /* free SSPI Schannel API security context handle */ if(BACKEND->ctxt) { - infof(data, "schannel: clear security context handle\n"); + DEBUGF(infof(data, "schannel: clear security context handle\n")); s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle); Curl_safefree(BACKEND->ctxt); } @@ -2035,11 +2065,9 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) * might not have an associated transfer so the check for conn->data is * necessary. */ - if(conn->data) - Curl_ssl_sessionid_lock(conn); + Curl_ssl_sessionid_lock(conn); Curl_schannel_session_free(BACKEND->cred); - if(conn->data) - Curl_ssl_sessionid_unlock(conn); + Curl_ssl_sessionid_unlock(conn); BACKEND->cred = NULL; } @@ -2101,7 +2129,7 @@ static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM, static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, const char *pinnedpubkey) { - SECURITY_STATUS status; + SECURITY_STATUS sspi_status; struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CERT_CONTEXT *pCertContextServer = NULL; @@ -2118,13 +2146,15 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex, return CURLE_OK; do { - status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, - SECPKG_ATTR_REMOTE_CERT_CONTEXT, - &pCertContextServer); + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); - if((status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", - Curl_sspi_strerror(conn, status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); break; /* failed */ } diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c index 680f6ec5..5a09e969 100644 --- a/lib/vtls/schannel_verify.c +++ b/lib/vtls/schannel_verify.c @@ -96,9 +96,10 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, ca_file_tstr = Curl_convert_UTF8_to_tchar((char *)ca_file); if(!ca_file_tstr) { + char buffer[STRERROR_LEN]; failf(data, "schannel: invalid path name for CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -116,17 +117,19 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, FILE_ATTRIBUTE_NORMAL, NULL); if(ca_file_handle == INVALID_HANDLE_VALUE) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to open CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } if(!GetFileSizeEx(ca_file_handle, &file_size)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to determine size of CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -153,10 +156,10 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read, bytes_to_read, &bytes_read, NULL)) { - + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to read from CA file '%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -215,11 +218,12 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, NULL, NULL, (const void **)&cert_context)) { - + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to extract certificate from CA file " "'%s': %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; more_certs = 0; } @@ -243,10 +247,12 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store, NULL); CertFreeCertificateContext(cert_context); if(!add_cert_result) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to add certificate from CA file '%s' " "to certificate store: %s", - ca_file, Curl_strerror(conn, GetLastError())); + ca_file, + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; more_certs = 0; } @@ -408,7 +414,7 @@ cleanup: CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) { - SECURITY_STATUS status; + SECURITY_STATUS sspi_status; struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CURLcode result = CURLE_OK; @@ -420,13 +426,15 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) conn->http_proxy.host.name : conn->host.name; - status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, - SECPKG_ATTR_REMOTE_CERT_CONTEXT, - &pCertContextServer); + sspi_status = + s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle, + SECPKG_ATTR_REMOTE_CERT_CONTEXT, + &pCertContextServer); - if((status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", - Curl_sspi_strerror(conn, status)); + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); result = CURLE_PEER_FAILED_VERIFICATION; } @@ -450,8 +458,9 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) CERT_STORE_CREATE_NEW_FLAG, NULL); if(!trust_store) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to create certificate store: %s", - Curl_strerror(conn, GetLastError())); + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; } else { @@ -477,9 +486,10 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) CertCreateCertificateChainEngine( (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine); if(!create_engine_result) { + char buffer[STRERROR_LEN]; failf(data, "schannel: failed to create certificate chain engine: %s", - Curl_strerror(conn, GetLastError())); + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; } } @@ -500,8 +510,9 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) CERT_CHAIN_REVOCATION_CHECK_CHAIN), NULL, &pChainContext)) { + char buffer[STRERROR_LEN]; failf(data, "schannel: CertGetCertificateChain failed: %s", - Curl_sspi_strerror(conn, GetLastError())); + Curl_strerror(GetLastError(), buffer, sizeof(buffer))); pChainContext = NULL; result = CURLE_PEER_FAILED_VERIFICATION; } diff --git a/lib/vtls/darwinssl.c b/lib/vtls/sectransp.c index bb251cdb..971dd78e 100644 --- a/lib/vtls/darwinssl.c +++ b/lib/vtls/sectransp.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>. - * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 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 @@ -32,7 +32,7 @@ #include "curl_base64.h" #include "strtok.h" -#ifdef USE_DARWINSSL +#ifdef USE_SECTRANSP #ifdef __clang__ #pragma clang diagnostic push @@ -59,7 +59,7 @@ #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 -#error "The darwinssl back-end requires Leopard or later." +#error "The Secure Transport back-end requires Leopard or later." #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ #define CURL_BUILD_IOS 0 @@ -105,7 +105,7 @@ #define CURL_SUPPORT_MAC_10_9 0 #else -#error "The darwinssl back-end requires iOS or OS X." +#error "The Secure Transport back-end requires iOS or macOS." #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ #if CURL_BUILD_MAC @@ -118,7 +118,7 @@ #include "connect.h" #include "select.h" #include "vtls.h" -#include "darwinssl.h" +#include "sectransp.h" #include "curl_printf.h" #include "strdup.h" @@ -144,20 +144,20 @@ struct ssl_backend_data { /* version 1 supports macOS 10.12+ and iOS 10+ */ #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \ (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) -#define DARWIN_SSL_PINNEDPUBKEY_V1 1 +#define SECTRANSP_PINNEDPUBKEY_V1 1 #endif /* version 2 supports MacOSX 10.7+ */ #if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) -#define DARWIN_SSL_PINNEDPUBKEY_V2 1 +#define SECTRANSP_PINNEDPUBKEY_V2 1 #endif -#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2) +#if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2) /* this backend supports CURLOPT_PINNEDPUBLICKEY */ -#define DARWIN_SSL_PINNEDPUBKEY 1 -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#define SECTRANSP_PINNEDPUBKEY 1 +#endif /* SECTRANSP_PINNEDPUBKEY */ -#ifdef DARWIN_SSL_PINNEDPUBKEY +#ifdef SECTRANSP_PINNEDPUBKEY /* both new and old APIs return rsa keys missing the spki header (not DER) */ static const unsigned char rsa4096SpkiHeader[] = { 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, @@ -170,7 +170,7 @@ static const unsigned char rsa2048SpkiHeader[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00}; -#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 +#ifdef SECTRANSP_PINNEDPUBKEY_V1 /* the *new* version doesn't return DER encoded ecdsa certs like the old... */ static const unsigned char ecDsaSecp256r1SpkiHeader[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, @@ -184,8 +184,8 @@ static const unsigned char ecDsaSecp384r1SpkiHeader[] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00}; -#endif /* DARWIN_SSL_PINNEDPUBKEY_V1 */ -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#endif /* SECTRANSP_PINNEDPUBKEY_V1 */ +#endif /* SECTRANSP_PINNEDPUBKEY */ /* The following two functions were ripped from Apple sample code, * with some modifications: */ @@ -1242,7 +1242,7 @@ CF_INLINE bool is_file(const char *filename) } #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS -static CURLcode darwinssl_version_from_curl(SSLProtocol *darwinver, +static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver, long ssl_version) { switch(ssl_version) { @@ -1312,13 +1312,13 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) if(SSLSetProtocolVersionMax != NULL) { SSLProtocol darwin_ver_min = kTLSProtocol1; SSLProtocol darwin_ver_max = kTLSProtocol1; - CURLcode result = darwinssl_version_from_curl(&darwin_ver_min, + CURLcode result = sectransp_version_from_curl(&darwin_ver_min, ssl_version); if(result) { failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); return result; } - result = darwinssl_version_from_curl(&darwin_ver_max, + result = sectransp_version_from_curl(&darwin_ver_max, ssl_version_max >> 16); if(result) { failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); @@ -1361,12 +1361,12 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex) #endif /* CURL_SUPPORT_MAC_10_8 */ } #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - failf(data, "DarwinSSL: cannot set SSL protocol"); + failf(data, "Secure Transport: cannot set SSL protocol"); return CURLE_SSL_CONNECT_ERROR; } -static CURLcode darwinssl_connect_step1(struct connectdata *conn, +static CURLcode sectransp_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; @@ -1577,7 +1577,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 if(conn->bits.tls_enable_alpn) { - if(__builtin_available(macOS 10.13.4, iOS 11, *)) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); @@ -2234,7 +2234,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data, } } -#ifdef DARWIN_SSL_PINNEDPUBKEY +#ifdef SECTRANSP_PINNEDPUBKEY static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, SSLContextRef ctx, const char *pinnedpubkey) @@ -2266,14 +2266,14 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, if(keyRef == NULL) break; -#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 +#ifdef SECTRANSP_PINNEDPUBKEY_V1 publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); CFRelease(keyRef); if(publicKeyBits == NULL) break; -#elif DARWIN_SSL_PINNEDPUBKEY_V2 +#elif SECTRANSP_PINNEDPUBKEY_V2 OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, &publicKeyBits); @@ -2281,7 +2281,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, if(success != errSecSuccess || publicKeyBits == NULL) break; -#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ pubkeylen = CFDataGetLength(publicKeyBits); pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits); @@ -2295,7 +2295,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, /* 2048 bit RSA pubkeylen == 270 */ spkiHeader = rsa2048SpkiHeader; break; -#ifdef DARWIN_SSL_PINNEDPUBKEY_V1 +#ifdef SECTRANSP_PINNEDPUBKEY_V1 case 65: /* ecDSA secp256r1 pubkeylen == 65 */ spkiHeader = ecDsaSecp256r1SpkiHeader; @@ -2308,7 +2308,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, break; default: infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); -#elif DARWIN_SSL_PINNEDPUBKEY_V2 +#elif SECTRANSP_PINNEDPUBKEY_V2 default: /* ecDSA secp256r1 pubkeylen == 91 header already included? * ecDSA secp384r1 header already included too @@ -2316,7 +2316,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, */ result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey, pubkeylen); -#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */ +#endif /* SECTRANSP_PINNEDPUBKEY_V2 */ continue; /* break from loop */ } @@ -2339,10 +2339,10 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, return result; } -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#endif /* SECTRANSP_PINNEDPUBKEY */ static CURLcode -darwinssl_connect_step2(struct connectdata *conn, int sockindex) +sectransp_connect_step2(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -2376,7 +2376,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) return res; } /* the documentation says we need to call SSLHandshake() again */ - return darwinssl_connect_step2(conn, sockindex); + return sectransp_connect_step2(conn, sockindex); /* Problem with encrypt / decrypt */ case errSSLPeerDecodeError: @@ -2578,7 +2578,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) /* we have been connected fine, we're not waiting for anything else. */ connssl->connecting_state = ssl_connect_3; -#ifdef DARWIN_SSL_PINNEDPUBKEY +#ifdef SECTRANSP_PINNEDPUBKEY if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx, data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); @@ -2587,7 +2587,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) return result; } } -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#endif /* SECTRANSP_PINNEDPUBKEY */ /* Informational message */ (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher); @@ -2628,7 +2628,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 if(conn->bits.tls_enable_alpn) { - if(__builtin_available(macOS 10.13.4, iOS 11, *)) { + if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { CFArrayRef alpnArr = NULL; CFStringRef chosenProtocol = NULL; err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr); @@ -2771,7 +2771,7 @@ show_verbose_server_cert(struct connectdata *conn, #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ static CURLcode -darwinssl_connect_step3(struct connectdata *conn, +sectransp_connect_step3(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; @@ -2789,11 +2789,11 @@ darwinssl_connect_step3(struct connectdata *conn, return CURLE_OK; } -static Curl_recv darwinssl_recv; -static Curl_send darwinssl_send; +static Curl_recv sectransp_recv; +static Curl_send sectransp_send; static CURLcode -darwinssl_connect_common(struct connectdata *conn, +sectransp_connect_common(struct connectdata *conn, int sockindex, bool nonblocking, bool *done) @@ -2821,7 +2821,7 @@ darwinssl_connect_common(struct connectdata *conn, return CURLE_OPERATION_TIMEDOUT; } - result = darwinssl_connect_step1(conn, sockindex); + result = sectransp_connect_step1(conn, sockindex); if(result) return result; } @@ -2875,7 +2875,7 @@ darwinssl_connect_common(struct connectdata *conn, * before step2 has completed while ensuring that a client using select() * or epoll() will always have a valid fdset to wait on. */ - result = darwinssl_connect_step2(conn, sockindex); + result = sectransp_connect_step2(conn, sockindex); if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state || @@ -2886,15 +2886,15 @@ darwinssl_connect_common(struct connectdata *conn, if(ssl_connect_3 == connssl->connecting_state) { - result = darwinssl_connect_step3(conn, sockindex); + result = sectransp_connect_step3(conn, sockindex); if(result) return result; } if(ssl_connect_done == connssl->connecting_state) { connssl->state = ssl_connection_complete; - conn->recv[sockindex] = darwinssl_recv; - conn->send[sockindex] = darwinssl_send; + conn->recv[sockindex] = sectransp_recv; + conn->send[sockindex] = sectransp_send; *done = TRUE; } else @@ -2906,18 +2906,18 @@ darwinssl_connect_common(struct connectdata *conn, return CURLE_OK; } -static CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn, +static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done) { - return darwinssl_connect_common(conn, sockindex, TRUE, done); + return sectransp_connect_common(conn, sockindex, TRUE, done); } -static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex) +static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex) { CURLcode result; bool done = FALSE; - result = darwinssl_connect_common(conn, sockindex, FALSE, &done); + result = sectransp_connect_common(conn, sockindex, FALSE, &done); if(result) return result; @@ -2927,7 +2927,7 @@ static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex) return CURLE_OK; } -static void Curl_darwinssl_close(struct connectdata *conn, int sockindex) +static void Curl_sectransp_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; @@ -2948,7 +2948,7 @@ static void Curl_darwinssl_close(struct connectdata *conn, int sockindex) BACKEND->ssl_sockfd = 0; } -static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) +static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct Curl_easy *data = conn->data; @@ -2963,7 +2963,7 @@ static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) return 0; - Curl_darwinssl_close(conn, sockindex); + Curl_sectransp_close(conn, sockindex); rc = 0; @@ -3001,18 +3001,18 @@ static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex) return rc; } -static void Curl_darwinssl_session_free(void *ptr) +static void Curl_sectransp_session_free(void *ptr) { /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a cached session ID inside the Security framework. There is a private function that does this, but I don't want to have to explain to you why I got your application rejected from the App Store due to the use of a private API, so the best we can do is free up our own char array that we - created way back in darwinssl_connect_step1... */ + created way back in sectransp_connect_step1... */ Curl_safefree(ptr); } -static size_t Curl_darwinssl_version(char *buffer, size_t size) +static size_t Curl_sectransp_version(char *buffer, size_t size) { return msnprintf(buffer, size, "SecureTransport"); } @@ -3025,7 +3025,7 @@ static size_t Curl_darwinssl_version(char *buffer, size_t size) * 0 means the connection has been closed * -1 means the connection status is unknown */ -static int Curl_darwinssl_check_cxn(struct connectdata *conn) +static int Curl_sectransp_check_cxn(struct connectdata *conn) { struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; OSStatus err; @@ -3040,7 +3040,7 @@ static int Curl_darwinssl_check_cxn(struct connectdata *conn) return 0; } -static bool Curl_darwinssl_data_pending(const struct connectdata *conn, +static bool Curl_sectransp_data_pending(const struct connectdata *conn, int connindex) { const struct ssl_connect_data *connssl = &conn->ssl[connindex]; @@ -3057,7 +3057,7 @@ static bool Curl_darwinssl_data_pending(const struct connectdata *conn, return false; } -static CURLcode Curl_darwinssl_random(struct Curl_easy *data UNUSED_PARAM, +static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM, unsigned char *entropy, size_t length) { /* arc4random_buf() isn't available on cats older than Lion, so let's @@ -3077,7 +3077,7 @@ static CURLcode Curl_darwinssl_random(struct Curl_easy *data UNUSED_PARAM, return CURLE_OK; } -static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ +static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum, /* output */ size_t md5len) @@ -3087,7 +3087,7 @@ static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ return CURLE_OK; } -static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */ +static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */ size_t tmplen, unsigned char *sha256sum, /* output */ size_t sha256len) @@ -3097,7 +3097,7 @@ static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */ return CURLE_OK; } -static bool Curl_darwinssl_false_start(void) +static bool Curl_sectransp_false_start(void) { #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 if(SSLSetSessionOption != NULL) @@ -3106,7 +3106,7 @@ static bool Curl_darwinssl_false_start(void) return FALSE; } -static ssize_t darwinssl_send(struct connectdata *conn, +static ssize_t sectransp_send(struct connectdata *conn, int sockindex, const void *mem, size_t len, @@ -3172,7 +3172,7 @@ static ssize_t darwinssl_send(struct connectdata *conn, return (ssize_t)processed; } -static ssize_t darwinssl_recv(struct connectdata *conn, +static ssize_t sectransp_recv(struct connectdata *conn, int num, char *buf, size_t buffersize, @@ -3212,48 +3212,48 @@ static ssize_t darwinssl_recv(struct connectdata *conn, return (ssize_t)processed; } -static void *Curl_darwinssl_get_internals(struct ssl_connect_data *connssl, +static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl, CURLINFO info UNUSED_PARAM) { (void)info; return BACKEND->ssl_ctx; } -const struct Curl_ssl Curl_ssl_darwinssl = { - { CURLSSLBACKEND_DARWINSSL, "darwinssl" }, /* info */ +const struct Curl_ssl Curl_ssl_sectransp = { + { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ -#ifdef DARWIN_SSL_PINNEDPUBKEY +#ifdef SECTRANSP_PINNEDPUBKEY SSLSUPP_PINNEDPUBKEY, #else 0, -#endif /* DARWIN_SSL_PINNEDPUBKEY */ +#endif /* SECTRANSP_PINNEDPUBKEY */ sizeof(struct ssl_backend_data), Curl_none_init, /* init */ Curl_none_cleanup, /* cleanup */ - Curl_darwinssl_version, /* version */ - Curl_darwinssl_check_cxn, /* check_cxn */ - Curl_darwinssl_shutdown, /* shutdown */ - Curl_darwinssl_data_pending, /* data_pending */ - Curl_darwinssl_random, /* random */ + Curl_sectransp_version, /* version */ + Curl_sectransp_check_cxn, /* check_cxn */ + Curl_sectransp_shutdown, /* shutdown */ + Curl_sectransp_data_pending, /* data_pending */ + Curl_sectransp_random, /* random */ Curl_none_cert_status_request, /* cert_status_request */ - Curl_darwinssl_connect, /* connect */ - Curl_darwinssl_connect_nonblocking, /* connect_nonblocking */ - Curl_darwinssl_get_internals, /* get_internals */ - Curl_darwinssl_close, /* close_one */ + Curl_sectransp_connect, /* connect */ + Curl_sectransp_connect_nonblocking, /* connect_nonblocking */ + Curl_sectransp_get_internals, /* get_internals */ + Curl_sectransp_close, /* close_one */ Curl_none_close_all, /* close_all */ - Curl_darwinssl_session_free, /* session_free */ + Curl_sectransp_session_free, /* session_free */ Curl_none_set_engine, /* set_engine */ Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ - Curl_darwinssl_false_start, /* false_start */ - Curl_darwinssl_md5sum, /* md5sum */ - Curl_darwinssl_sha256sum /* sha256sum */ + Curl_sectransp_false_start, /* false_start */ + Curl_sectransp_md5sum, /* md5sum */ + Curl_sectransp_sha256sum /* sha256sum */ }; #ifdef __clang__ #pragma clang diagnostic pop #endif -#endif /* USE_DARWINSSL */ +#endif /* USE_SECTRANSP */ diff --git a/lib/vtls/darwinssl.h b/lib/vtls/sectransp.h index 23c7f705..5cec797b 100644 --- a/lib/vtls/darwinssl.h +++ b/lib/vtls/sectransp.h @@ -1,5 +1,5 @@ -#ifndef HEADER_CURL_DARWINSSL_H -#define HEADER_CURL_DARWINSSL_H +#ifndef HEADER_CURL_SECTRANSP_H +#define HEADER_CURL_SECTRANSP_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -8,7 +8,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>. - * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 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 @@ -24,9 +24,9 @@ ***************************************************************************/ #include "curl_setup.h" -#ifdef USE_DARWINSSL +#ifdef USE_SECTRANSP -extern const struct Curl_ssl Curl_ssl_darwinssl; +extern const struct Curl_ssl Curl_ssl_sectransp; -#endif /* USE_DARWINSSL */ -#endif /* HEADER_CURL_DARWINSSL_H */ +#endif /* USE_SECTRANSP */ +#endif /* HEADER_CURL_SECTRANSP_H */ diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 5e75f92e..8a405c05 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.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 @@ -248,7 +248,7 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex) conn->ssl[sockindex].use = TRUE; conn->ssl[sockindex].state = ssl_connection_negotiating; - result = Curl_ssl->connect(conn, sockindex); + result = Curl_ssl->connect_blocking(conn, sockindex); if(!result) Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */ @@ -513,7 +513,7 @@ void Curl_ssl_close_all(struct Curl_easy *data) } #if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ - defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \ + defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \ defined(USE_MBEDTLS) || defined(USE_CYASSL) int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) @@ -546,7 +546,7 @@ int Curl_ssl_getsock(struct connectdata *conn, (void)numsocks; return GETSOCK_BLANK; } -/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */ +/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */ #endif void Curl_ssl_close(struct connectdata *conn, int sockindex) @@ -557,7 +557,7 @@ void Curl_ssl_close(struct connectdata *conn, int sockindex) CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) { - if(Curl_ssl->shutdown(conn, sockindex)) + if(Curl_ssl->shut_down(conn, sockindex)) return CURLE_SSL_SHUTDOWN_FAILED; conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */ @@ -1114,7 +1114,7 @@ static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex) { if(multissl_init(NULL)) return CURLE_FAILED_INIT; - return Curl_ssl->connect(conn, sockindex); + return Curl_ssl->connect_blocking(conn, sockindex); } static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn, @@ -1172,8 +1172,8 @@ const struct Curl_ssl *Curl_ssl = &Curl_ssl_multi; #elif defined(USE_CYASSL) &Curl_ssl_cyassl; -#elif defined(USE_DARWINSSL) - &Curl_ssl_darwinssl; +#elif defined(USE_SECTRANSP) + &Curl_ssl_sectransp; #elif defined(USE_GNUTLS) &Curl_ssl_gnutls; #elif defined(USE_GSKIT) @@ -1198,8 +1198,8 @@ static const struct Curl_ssl *available_backends[] = { #if defined(USE_CYASSL) &Curl_ssl_cyassl, #endif -#if defined(USE_DARWINSSL) - &Curl_ssl_darwinssl, +#if defined(USE_SECTRANSP) + &Curl_ssl_sectransp, #endif #if defined(USE_GNUTLS) &Curl_ssl_gnutls, diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index 1f163631..2a87ca1f 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -7,7 +7,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 @@ -47,7 +47,7 @@ struct Curl_ssl { size_t (*version)(char *buffer, size_t size); int (*check_cxn)(struct connectdata *cxn); - int (*shutdown)(struct connectdata *conn, int sockindex); + int (*shut_down)(struct connectdata *conn, int sockindex); bool (*data_pending)(const struct connectdata *conn, int connindex); @@ -56,7 +56,7 @@ struct Curl_ssl { size_t length); bool (*cert_status_request)(void); - CURLcode (*connect)(struct connectdata *conn, int sockindex); + CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex); CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex, bool *done); void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); @@ -105,7 +105,7 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, #include "polarssl.h" /* PolarSSL versions */ #include "cyassl.h" /* CyaSSL versions */ #include "schannel.h" /* Schannel SSPI version */ -#include "darwinssl.h" /* SecureTransport (Darwin) version */ +#include "sectransp.h" /* SecureTransport (Darwin) version */ #include "mbedtls.h" /* mbedTLS versions */ #include "mesalink.h" /* MesaLink versions */ diff --git a/lib/warnless.c b/lib/warnless.c index 05d9038d..cfd5e8e1 100644 --- a/lib/warnless.c +++ b/lib/warnless.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, 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 @@ -401,44 +401,6 @@ unsigned short curlx_uitous(unsigned int uinum) } /* -** unsigned int to unsigned char -*/ - -unsigned char curlx_uitouc(unsigned int uinum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - DEBUGASSERT(uinum <= (unsigned int) CURL_MASK_UCHAR); - return (unsigned char) (uinum & (unsigned int) CURL_MASK_UCHAR); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* -** unsigned int to signed int -*/ - -int curlx_uitosi(unsigned int uinum) -{ -#ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ -#endif - - DEBUGASSERT(uinum <= (unsigned int) CURL_MASK_SINT); - return (int) (uinum & (unsigned int) CURL_MASK_SINT); - -#ifdef __INTEL_COMPILER -# pragma warning(pop) -#endif -} - -/* ** signed int to unsigned size_t */ diff --git a/lib/warnless.h b/lib/warnless.h index 284ea1e7..ea4c4395 100644 --- a/lib/warnless.h +++ b/lib/warnless.h @@ -7,7 +7,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 @@ -57,10 +57,6 @@ int curlx_sztosi(ssize_t sznum); unsigned short curlx_uitous(unsigned int uinum); -unsigned char curlx_uitouc(unsigned int uinum); - -int curlx_uitosi(unsigned int uinum); - size_t curlx_sitouz(int sinum); #ifdef USE_WINSOCK diff --git a/lib/x509asn1.c b/lib/x509asn1.c index 746e1e8e..25231921 100644 --- a/lib/x509asn1.c +++ b/lib/x509asn1.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 @@ -120,7 +120,7 @@ static const char *getASN1Element(curl_asn1Element *elem, if an error occurs. */ if(!beg || !end || beg >= end || !*beg || (size_t)(end - beg) > CURL_ASN1_MAX) - return (const char *) NULL; + return NULL; /* Process header byte. */ elem->header = beg; @@ -129,12 +129,12 @@ static const char *getASN1Element(curl_asn1Element *elem, elem->class = (b >> 6) & 3; b &= 0x1F; if(b == 0x1F) - return (const char *) NULL; /* Long tag values not supported here. */ + return NULL; /* Long tag values not supported here. */ elem->tag = b; /* Process length. */ if(beg >= end) - return (const char *) NULL; + return NULL; b = (unsigned char) *beg++; if(!(b & 0x80)) len = b; @@ -142,69 +142,72 @@ static const char *getASN1Element(curl_asn1Element *elem, /* Unspecified length. Since we have all the data, we can determine the effective length by skipping element until an end element is found. */ if(!elem->constructed) - return (const char *) NULL; + return NULL; elem->beg = beg; while(beg < end && *beg) { beg = getASN1Element(&lelem, beg, end); if(!beg) - return (const char *) NULL; + return NULL; } if(beg >= end) - return (const char *) NULL; + return NULL; elem->end = beg; return beg + 1; } else if((unsigned)b > (size_t)(end - beg)) - return (const char *) NULL; /* Does not fit in source. */ + return NULL; /* Does not fit in source. */ else { /* Get long length. */ len = 0; do { if(len & 0xFF000000L) - return (const char *) NULL; /* Lengths > 32 bits are not supported. */ + return NULL; /* Lengths > 32 bits are not supported. */ len = (len << 8) | (unsigned char) *beg++; } while(--b); } if(len > (size_t)(end - beg)) - return (const char *) NULL; /* Element data does not fit in source. */ + return NULL; /* Element data does not fit in source. */ elem->beg = beg; elem->end = beg + len; return elem->end; } +/* + * Search the null terminated OID or OID identifier in local table. + * Return the table entry pointer or NULL if not found. + */ static const curl_OID * searchOID(const char *oid) { const curl_OID *op; - - /* Search the null terminated OID or OID identifier in local table. - Return the table entry pointer or NULL if not found. */ - for(op = OIDtable; op->numoid; op++) if(!strcmp(op->numoid, oid) || strcasecompare(op->textoid, oid)) return op; - return (const curl_OID *) NULL; + return NULL; } +/* + * Convert an ASN.1 Boolean value into its string representation. Return the + * dynamically allocated string, or NULL if source is not an ASN.1 Boolean + * value. + */ + static const char *bool2str(const char *beg, const char *end) { - /* Convert an ASN.1 Boolean value into its string representation. - Return the dynamically allocated string, or NULL if source is not an - ASN.1 Boolean value. */ - if(end - beg != 1) - return (const char *) NULL; + return NULL; return strdup(*beg? "TRUE": "FALSE"); } +/* + * Convert an ASN.1 octet string to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *octet2str(const char *beg, const char *end) { size_t n = end - beg; char *buf = NULL; - /* Convert an ASN.1 octet string to a printable string. - Return the dynamically allocated string, or NULL if an error occurs. */ - if(n <= (SIZE_T_MAX - 1) / 3) { buf = malloc(3 * n + 1); if(buf) @@ -220,21 +223,22 @@ static const char *bit2str(const char *beg, const char *end) Return the dynamically allocated string, or NULL if an error occurs. */ if(++beg > end) - return (const char *) NULL; + return NULL; return octet2str(beg, end); } +/* + * Convert an ASN.1 integer value into its string representation. + * Return the dynamically allocated string, or NULL if source is not an + * ASN.1 integer value. + */ static const char *int2str(const char *beg, const char *end) { unsigned long val = 0; size_t n = end - beg; - /* Convert an ASN.1 integer value into its string representation. - Return the dynamically allocated string, or NULL if source is not an - ASN.1 integer value. */ - if(!n) - return (const char *) NULL; + return NULL; if(n > 4) return octet2str(beg, end); @@ -249,6 +253,13 @@ static const char *int2str(const char *beg, const char *end) return curl_maprintf("%s%lx", val >= 10? "0x": "", val); } +/* + * Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the + * destination buffer dynamically. The allocation size will normally be too + * large: this is to avoid buffer overflows. + * Terminate the string with a nul byte and return the converted + * string length. + */ static ssize_t utf8asn1str(char **to, int type, const char *from, const char *end) { @@ -259,13 +270,7 @@ utf8asn1str(char **to, int type, const char *from, const char *end) unsigned int wc; char *buf; - /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the - destination buffer dynamically. The allocation size will normally be too - large: this is to avoid buffer overflows. - Terminate the string with a nul byte and return the converted - string length. */ - - *to = (char *) NULL; + *to = NULL; switch(type) { case CURL_ASN1_BMP_STRING: size = 2; @@ -341,96 +346,105 @@ utf8asn1str(char **to, int type, const char *from, const char *end) return outlength; } +/* + * Convert an ASN.1 String into its UTF-8 string representation. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *string2str(int type, const char *beg, const char *end) { char *buf; - - /* Convert an ASN.1 String into its UTF-8 string representation. - Return the dynamically allocated string, or NULL if an error occurs. */ - if(utf8asn1str(&buf, type, beg, end) < 0) - return (const char *) NULL; + return NULL; return buf; } -static int encodeUint(char *buf, int n, unsigned int x) +/* + * Decimal ASCII encode unsigned integer `x' into the buflen sized buffer at + * buf. Return the total number of encoded digits, even if larger than + * `buflen'. + */ +static size_t encodeUint(char *buf, size_t buflen, unsigned int x) { - int i = 0; + size_t i = 0; unsigned int y = x / 10; - /* Decimal ASCII encode unsigned integer `x' in the `n'-byte buffer at `buf'. - Return the total number of encoded digits, even if larger than `n'. */ - if(y) { - i += encodeUint(buf, n, y); + i = encodeUint(buf, buflen, y); x -= y * 10; } - if(i < n) + if(i < buflen) buf[i] = (char) ('0' + x); i++; - if(i < n) + if(i < buflen) buf[i] = '\0'; /* Store a terminator if possible. */ return i; } -static int encodeOID(char *buf, int n, const char *beg, const char *end) +/* + * Convert an ASN.1 OID into its dotted string representation. + * Store the result in th `n'-byte buffer at `buf'. + * Return the converted string length, or 0 on errors. + */ +static size_t encodeOID(char *buf, size_t buflen, + const char *beg, const char *end) { - int i = 0; + size_t i; unsigned int x; unsigned int y; - /* Convert an ASN.1 OID into its dotted string representation. - Store the result in th `n'-byte buffer at `buf'. - Return the converted string length, or -1 if an error occurs. */ - /* Process the first two numbers. */ y = *(const unsigned char *) beg++; x = y / 40; y -= x * 40; - i += encodeUint(buf + i, n - i, x); - if(i < n) + i = encodeUint(buf, buflen, x); + if(i < buflen) buf[i] = '.'; i++; - i += encodeUint(buf + i, n - i, y); + if(i >= buflen) + i += encodeUint(NULL, 0, y); + else + i += encodeUint(buf + i, buflen - i, y); /* Process the trailing numbers. */ while(beg < end) { - if(i < n) + if(i < buflen) buf[i] = '.'; i++; x = 0; do { if(x & 0xFF000000) - return -1; + return 0; y = *(const unsigned char *) beg++; x = (x << 7) | (y & 0x7F); } while(y & 0x80); - i += encodeUint(buf + i, n - i, x); + if(i >= buflen) + i += encodeUint(NULL, 0, x); + else + i += encodeUint(buf + i, buflen - i, x); } - if(i < n) + if(i < buflen) buf[i] = '\0'; return i; } +/* + * Convert an ASN.1 OID into its dotted or symbolic string representation. + * Return the dynamically allocated string, or NULL if an error occurs. + */ + static const char *OID2str(const char *beg, const char *end, bool symbolic) { - char *buf = (char *) NULL; - const curl_OID * op; - int n; - - /* Convert an ASN.1 OID into its dotted or symbolic string representation. - Return the dynamically allocated string, or NULL if an error occurs. */ - + char *buf = NULL; if(beg < end) { - n = encodeOID((char *) NULL, -1, beg, end); - if(n >= 0) { - buf = malloc(n + 1); + size_t buflen = encodeOID(NULL, 0, beg, end); + if(buflen) { + buf = malloc(buflen + 1); /* one extra for the zero byte */ if(buf) { - encodeOID(buf, n, beg, end); - buf[n] = '\0'; + encodeOID(buf, buflen, beg, end); + buf[buflen] = '\0'; if(symbolic) { - op = searchOID(buf); + const curl_OID *op = searchOID(buf); if(op) { free(buf); buf = strdup(op->textoid); @@ -470,7 +484,7 @@ static const char *GTime2str(const char *beg, const char *end) sec2 = fracp[-1]; break; default: - return (const char *) NULL; + return NULL; } /* Scan for timezone, measure fractional seconds. */ @@ -506,15 +520,16 @@ static const char *GTime2str(const char *beg, const char *end) sep, tzl, tzp); } +/* + * Convert an ASN.1 UTC time to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *UTime2str(const char *beg, const char *end) { const char *tzp; size_t tzl; const char *sec; - /* Convert an ASN.1 UTC time to a printable string. - Return the dynamically allocated string, or NULL if an error occurs. */ - for(tzp = beg; tzp < end && *tzp >= '0' && *tzp <= '9'; tzp++) ; /* Get the seconds. */ @@ -525,12 +540,12 @@ static const char *UTime2str(const char *beg, const char *end) case 2: break; default: - return (const char *) NULL; + return NULL; } /* Process timezone. */ if(tzp >= end) - return (const char *) NULL; + return NULL; if(*tzp == 'Z') { tzp = "GMT"; end = tzp + 3; @@ -545,13 +560,14 @@ static const char *UTime2str(const char *beg, const char *end) tzl, tzp); } +/* + * Convert an ASN.1 element to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *ASN1tostr(curl_asn1Element *elem, int type) { - /* Convert an ASN.1 element to a printable string. - Return the dynamically allocated string, or NULL if an error occurs. */ - if(elem->constructed) - return (const char *) NULL; /* No conversion of structured elements. */ + return NULL; /* No conversion of structured elements. */ if(!type) type = elem->tag; /* Type not forced: use element tag as type. */ @@ -585,10 +601,14 @@ static const char *ASN1tostr(curl_asn1Element *elem, int type) return string2str(type, elem->beg, elem->end); } - return (const char *) NULL; /* Unsupported. */ + return NULL; /* Unsupported. */ } -static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) +/* + * ASCII encode distinguished name at `dn' into the `buflen'-sized buffer at + * `buf'. Return the total string length, even if larger than `buflen'. + */ +static ssize_t encodeDN(char *buf, size_t buflen, curl_asn1Element *dn) { curl_asn1Element rdn; curl_asn1Element atv; @@ -600,9 +620,6 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) const char *p3; const char *str; - /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'. - Return the total string length, even if larger than `n'. */ - for(p1 = dn->beg; p1 < dn->end;) { p1 = getASN1Element(&rdn, p1, dn->end); if(!p1) @@ -626,7 +643,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) for(p3 = str; isupper(*p3); p3++) ; for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) { - if(l < n) + if(l < buflen) buf[l] = *p3; l++; } @@ -634,14 +651,14 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) /* Encode attribute name. */ for(p3 = str; *p3; p3++) { - if(l < n) + if(l < buflen) buf[l] = *p3; l++; } free((char *) str); /* Generate equal sign. */ - if(l < n) + if(l < buflen) buf[l] = '='; l++; @@ -650,7 +667,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) if(!str) return -1; for(p3 = str; *p3; p3++) { - if(l < n) + if(l < buflen) buf[l] = *p3; l++; } @@ -661,28 +678,30 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) return l; } +/* + * Convert an ASN.1 distinguished name into a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. + */ static const char *DNtostr(curl_asn1Element *dn) { - char *buf = (char *) NULL; - ssize_t n = encodeDN(buf, 0, dn); - - /* Convert an ASN.1 distinguished name into a printable string. - Return the dynamically allocated string, or NULL if an error occurs. */ + char *buf = NULL; + ssize_t buflen = encodeDN(NULL, 0, dn); - if(n >= 0) { - buf = malloc(n + 1); + if(buflen >= 0) { + buf = malloc(buflen + 1); if(buf) { - encodeDN(buf, n + 1, dn); - buf[n] = '\0'; + encodeDN(buf, buflen + 1, dn); + buf[buflen] = '\0'; } } - return (const char *) buf; + return buf; } /* - * X509 parser. + * ASN.1 parse an X509 certificate into structure subfields. + * Syntax is assumed to have already been checked by the SSL backend. + * See RFC 5280. */ - int Curl_parseX509(curl_X509certificate *cert, const char *beg, const char *end) { @@ -691,10 +710,6 @@ int Curl_parseX509(curl_X509certificate *cert, const char *ccp; static const char defaultVersion = 0; /* v1. */ - /* ASN.1 parse an X509 certificate into structure subfields. - Syntax is assumed to have already been checked by the SSL backend. - See RFC 5280. */ - cert->certificate.header = NULL; cert->certificate.beg = beg; cert->certificate.end = end; @@ -801,13 +816,14 @@ int Curl_parseX509(curl_X509certificate *cert, return 0; } + +/* + * Copy at most 64-characters, terminate with a newline and returns the + * effective number of stored characters. + */ static size_t copySubstring(char *to, const char *from) { size_t i; - - /* Copy at most 64-characters, terminate with a newline and returns the - effective number of stored characters. */ - for(i = 0; i < 64; i++) { to[i] = *from; if(!*from++) @@ -1104,15 +1120,15 @@ static const char *checkOID(const char *beg, const char *end, ccp = getASN1Element(&e, beg, end); if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER) - return (const char *) NULL; + return NULL; p = OID2str(e.beg, e.end, FALSE); if(!p) - return (const char *) NULL; + return NULL; matched = !strcmp(p, oid); free((char *) p); - return matched? ccp: (const char *) NULL; + return matched? ccp: NULL; } CURLcode Curl_verifyhost(struct connectdata *conn, |