Browse Source

curl 2020-06-30 (5a1fc8d3)

Code extracted from:

    https://github.com/curl/curl.git

at commit 5a1fc8d33808d7b22f57bdf9403cda7ff07b0670 (curl-7_71_1).
Curl Upstream 5 years ago
parent
commit
4446fda8e0
39 changed files with 250 additions and 218 deletions
  1. 3 3
      include/curl/curl.h
  2. 3 3
      include/curl/curlver.h
  3. 1 1
      include/curl/multi.h
  4. 1 1
      lib/cookie.c
  5. 2 2
      lib/curl_path.c
  6. 2 1
      lib/dict.c
  7. 5 5
      lib/dotdot.c
  8. 1 1
      lib/dynbuf.c
  9. 1 1
      lib/dynbuf.h
  10. 18 6
      lib/escape.c
  11. 9 2
      lib/escape.h
  12. 1 1
      lib/file.c
  13. 2 2
      lib/formdata.c
  14. 11 7
      lib/ftp.c
  15. 1 1
      lib/gopher.c
  16. 6 4
      lib/http.c
  17. 44 0
      lib/http2.c
  18. 8 5
      lib/if2ip.c
  19. 6 4
      lib/imap.c
  20. 4 3
      lib/ldap.c
  21. 1 1
      lib/mime.c
  22. 2 1
      lib/mqtt.c
  23. 4 118
      lib/multi.c
  24. 0 4
      lib/multihandle.h
  25. 2 2
      lib/pingpong.c
  26. 2 2
      lib/pop3.c
  27. 1 1
      lib/sendf.c
  28. 2 2
      lib/smb.c
  29. 3 2
      lib/smtp.c
  30. 1 1
      lib/strerror.c
  31. 2 2
      lib/strtok.c
  32. 1 1
      lib/tftp.c
  33. 24 13
      lib/url.c
  34. 8 5
      lib/urlapi.c
  35. 4 1
      lib/urldata.h
  36. 3 1
      lib/vquic/ngtcp2.c
  37. 10 0
      lib/vtls/mbedtls.c
  38. 6 5
      lib/vtls/openssl.c
  39. 45 3
      lib/vtls/vtls.c

+ 3 - 3
include/curl/curl.h

@@ -774,7 +774,7 @@ enum curl_khtype {
 };
 };
 
 
 struct curl_khkey {
 struct curl_khkey {
-  const char *key; /* points to a zero-terminated string encoded with base64
+  const char *key; /* points to a null-terminated string encoded with base64
                       if len is zero, otherwise to the "raw" data */
                       if len is zero, otherwise to the "raw" data */
   size_t len;
   size_t len;
   enum curl_khtype keytype;
   enum curl_khtype keytype;
@@ -1446,7 +1446,7 @@ typedef enum {
   /* 132 OBSOLETE. Gone in 7.16.0 */
   /* 132 OBSOLETE. Gone in 7.16.0 */
   /* 133 OBSOLETE. Gone in 7.16.0 */
   /* 133 OBSOLETE. Gone in 7.16.0 */
 
 
-  /* zero terminated string for pass on to the FTP server when asked for
+  /* null-terminated string for pass on to the FTP server when asked for
      "account" info */
      "account" info */
   CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134),
   CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134),
 
 
@@ -2118,7 +2118,7 @@ typedef enum {
   CURL_TIMECOND_LAST
   CURL_TIMECOND_LAST
 } curl_TimeCond;
 } curl_TimeCond;
 
 
-/* Special size_t value signaling a zero-terminated string. */
+/* Special size_t value signaling a null-terminated string. */
 #define CURL_ZERO_TERMINATED ((size_t) -1)
 #define CURL_ZERO_TERMINATED ((size_t) -1)
 
 
 /* curl_strequal() and curl_strnequal() are subject for removal in a future
 /* curl_strequal() and curl_strnequal() are subject for removal in a future

+ 3 - 3
include/curl/curlver.h

@@ -30,13 +30,13 @@
 
 
 /* This is the version number of the libcurl package from which this header
 /* This is the version number of the libcurl package from which this header
    file origins: */
    file origins: */
-#define LIBCURL_VERSION "7.71.0-DEV"
+#define LIBCURL_VERSION "7.71.1-DEV"
 
 
 /* The numeric version number is also available "in parts" by using these
 /* The numeric version number is also available "in parts" by using these
    defines: */
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
 #define LIBCURL_VERSION_MAJOR 7
 #define LIBCURL_VERSION_MINOR 71
 #define LIBCURL_VERSION_MINOR 71
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_PATCH 1
 
 
 /* This is the numeric version of the libcurl version number, meant for easier
 /* This is the numeric version of the libcurl version number, meant for easier
    parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
    parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -57,7 +57,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
    and needs it to contain the full number.
 */
 */
-#define LIBCURL_VERSION_NUM 0x074700
+#define LIBCURL_VERSION_NUM 0x074701
 
 
 /*
 /*
  * This is the date and time when the full source package was created. The
  * This is the date and time when the full source package was created. The

+ 1 - 1
include/curl/multi.h

@@ -267,7 +267,7 @@ CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
  *          value into the equivalent human readable error string.  This is
  *          value into the equivalent human readable error string.  This is
  *          useful for printing meaningful error messages.
  *          useful for printing meaningful error messages.
  *
  *
- * Returns: A pointer to a zero-terminated error message.
+ * Returns: A pointer to a null-terminated error message.
  */
  */
 CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
 CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
 
 

+ 1 - 1
lib/cookie.c

@@ -755,7 +755,7 @@ Curl_cookie_add(struct Curl_easy *data,
         co->path = malloc(pathlen + 1); /* one extra for the zero byte */
         co->path = malloc(pathlen + 1); /* one extra for the zero byte */
         if(co->path) {
         if(co->path) {
           memcpy(co->path, path, pathlen);
           memcpy(co->path, path, pathlen);
-          co->path[pathlen] = 0; /* zero terminate */
+          co->path[pathlen] = 0; /* null-terminate */
           co->spath = sanitize_cookie_path(co->path);
           co->spath = sanitize_cookie_path(co->path);
           if(!co->spath)
           if(!co->spath)
             badcookie = TRUE; /* out of memory bad */
             badcookie = TRUE; /* out of memory bad */

+ 2 - 2
lib/curl_path.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -42,7 +42,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
   size_t working_path_len;
   size_t working_path_len;
   CURLcode result =
   CURLcode result =
     Curl_urldecode(data, data->state.up.path, 0, &working_path,
     Curl_urldecode(data, data->state.up.path, 0, &working_path,
-                   &working_path_len, FALSE);
+                   &working_path_len, REJECT_ZERO);
   if(result)
   if(result)
     return result;
     return result;
 
 

+ 2 - 1
lib/dict.c

@@ -99,7 +99,8 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
   char *dictp;
   char *dictp;
   size_t len;
   size_t len;
 
 
-  CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
+  CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len,
+                                   REJECT_NADA);
   if(!newp || result)
   if(!newp || result)
     return NULL;
     return NULL;
 
 

+ 5 - 5
lib/dotdot.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
  * Curl_dedotdotify()
  * Curl_dedotdotify()
  * @unittest: 1395
  * @unittest: 1395
  *
  *
- * This function gets a zero-terminated path with dot and dotdot sequences
+ * This function gets a null-terminated path with dot and dotdot sequences
  * passed in and strips them off according to the rules in RFC 3986 section
  * passed in and strips them off according to the rules in RFC 3986 section
  * 5.2.4.
  * 5.2.4.
  *
  *
@@ -62,7 +62,7 @@ char *Curl_dedotdotify(const char *input)
   if(!out)
   if(!out)
     return NULL; /* out of memory */
     return NULL; /* out of memory */
 
 
-  *out = 0; /* zero terminates, for inputs like "./" */
+  *out = 0; /* null-terminates, for inputs like "./" */
 
 
   /* get a cloned copy of the input */
   /* get a cloned copy of the input */
   clone = strdup(input);
   clone = strdup(input);
@@ -129,7 +129,7 @@ char *Curl_dedotdotify(const char *input)
         if(*outptr == '/')
         if(*outptr == '/')
           break;
           break;
       }
       }
-      *outptr = 0; /* zero-terminate where it stops */
+      *outptr = 0; /* null-terminate where it stops */
     }
     }
     else if(!strcmp("/..", clone)) {
     else if(!strcmp("/..", clone)) {
       clone[2]='/';
       clone[2]='/';
@@ -141,7 +141,7 @@ char *Curl_dedotdotify(const char *input)
         if(*outptr == '/')
         if(*outptr == '/')
           break;
           break;
       }
       }
-      *outptr = 0; /* zero-terminate where it stops */
+      *outptr = 0; /* null-terminate where it stops */
     }
     }
 
 
     /*  D.  if the input buffer consists only of "." or "..", then remove
     /*  D.  if the input buffer consists only of "." or "..", then remove

+ 1 - 1
lib/dynbuf.c

@@ -161,7 +161,7 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
 }
 }
 
 
 /*
 /*
- * Append a zero terminated string at the end.
+ * Append a null-terminated string at the end.
  */
  */
 CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
 CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
 {
 {

+ 1 - 1
lib/dynbuf.h

@@ -23,7 +23,7 @@
  ***************************************************************************/
  ***************************************************************************/
 
 
 struct dynbuf {
 struct dynbuf {
-  char *bufr;    /* point to a zero terminated allocated buffer */
+  char *bufr;    /* point to a null-terminated allocated buffer */
   size_t leng;   /* number of bytes *EXCLUDING* the zero terminator */
   size_t leng;   /* number of bytes *EXCLUDING* the zero terminator */
   size_t allc;   /* size of the current allocation */
   size_t allc;   /* size of the current allocation */
   size_t toobig; /* size limit for the buffer */
   size_t toobig; /* size limit for the buffer */

+ 18 - 6
lib/escape.c

@@ -89,6 +89,9 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
   Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH);
   Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH);
 
 
   length = (inlength?(size_t)inlength:strlen(string));
   length = (inlength?(size_t)inlength:strlen(string));
+  if(!length)
+    return strdup("");
+
   while(length--) {
   while(length--) {
     unsigned char in = *string; /* we need to treat the characters unsigned */
     unsigned char in = *string; /* we need to treat the characters unsigned */
 
 
@@ -120,19 +123,26 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
 /*
 /*
  * Curl_urldecode() URL decodes the given string.
  * Curl_urldecode() URL decodes the given string.
  *
  *
- * Optionally detects control characters (byte codes lower than 32) in the
- * data and rejects such data.
- *
  * Returns a pointer to a malloced string in *ostring with length given in
  * Returns a pointer to a malloced string in *ostring with length given in
  * *olen. If length == 0, the length is assumed to be strlen(string).
  * *olen. If length == 0, the length is assumed to be strlen(string).
  *
  *
  * 'data' can be set to NULL but then this function can't convert network
  * 'data' can be set to NULL but then this function can't convert network
  * data to host for non-ascii.
  * data to host for non-ascii.
+ *
+ * ctrl options:
+ * - REJECT_NADA: accept everything
+ * - REJECT_CTRL: rejects control characters (byte codes lower than 32) in
+ *                the data
+ * - REJECT_ZERO: rejects decoded zero bytes
+ *
+ * The values for the enum starts at 2, to make the assert detect legacy
+ * invokes that used TRUE/FALSE (0 and 1).
  */
  */
+
 CURLcode Curl_urldecode(struct Curl_easy *data,
 CURLcode Curl_urldecode(struct Curl_easy *data,
                         const char *string, size_t length,
                         const char *string, size_t length,
                         char **ostring, size_t *olen,
                         char **ostring, size_t *olen,
-                        bool reject_ctrl)
+                        enum urlreject ctrl)
 {
 {
   size_t alloc;
   size_t alloc;
   char *ns;
   char *ns;
@@ -141,6 +151,7 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
 
 
   DEBUGASSERT(string);
   DEBUGASSERT(string);
+  DEBUGASSERT(ctrl >= REJECT_NADA); /* crash on TRUE/FALSE */
 
 
   alloc = (length?length:strlen(string)) + 1;
   alloc = (length?length:strlen(string)) + 1;
   ns = malloc(alloc);
   ns = malloc(alloc);
@@ -176,7 +187,8 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
       alloc -= 2;
       alloc -= 2;
     }
     }
 
 
-    if(reject_ctrl && (in < 0x20)) {
+    if(((ctrl == REJECT_CTRL) && (in < 0x20)) ||
+       ((ctrl == REJECT_ZERO) && (in == 0))) {
       free(ns);
       free(ns);
       return CURLE_URL_MALFORMAT;
       return CURLE_URL_MALFORMAT;
     }
     }
@@ -210,7 +222,7 @@ char *curl_easy_unescape(struct Curl_easy *data, const char *string,
     size_t inputlen = length;
     size_t inputlen = length;
     size_t outputlen;
     size_t outputlen;
     CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
     CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
-                                  FALSE);
+                                  REJECT_NADA);
     if(res)
     if(res)
       return NULL;
       return NULL;
 
 

+ 9 - 2
lib/escape.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -25,9 +25,16 @@
  * allocated string or NULL if an error occurred.  */
  * allocated string or NULL if an error occurred.  */
 
 
 bool Curl_isunreserved(unsigned char in);
 bool Curl_isunreserved(unsigned char in);
+
+enum urlreject {
+  REJECT_NADA = 2,
+  REJECT_CTRL,
+  REJECT_ZERO
+};
+
 CURLcode Curl_urldecode(struct Curl_easy *data,
 CURLcode Curl_urldecode(struct Curl_easy *data,
                         const char *string, size_t length,
                         const char *string, size_t length,
                         char **ostring, size_t *olen,
                         char **ostring, size_t *olen,
-                        bool reject_crlf);
+                        enum urlreject ctrl);
 
 
 #endif /* HEADER_CURL_ESCAPE_H */
 #endif /* HEADER_CURL_ESCAPE_H */

+ 1 - 1
lib/file.c

@@ -144,7 +144,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
   size_t real_path_len;
   size_t real_path_len;
 
 
   CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &real_path,
   CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &real_path,
-                                   &real_path_len, FALSE);
+                                   &real_path_len, REJECT_ZERO);
   if(result)
   if(result)
     return result;
     return result;
 
 

+ 2 - 2
lib/formdata.c

@@ -602,7 +602,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         /* Note that there's small risk that form->name is NULL here if the
         /* Note that there's small risk that form->name is NULL here if the
            app passed in a bad combo, so we better check for that first. */
            app passed in a bad combo, so we better check for that first. */
         if(form->name) {
         if(form->name) {
-          /* copy name (without strdup; possibly not nul-terminated) */
+          /* copy name (without strdup; possibly not null-terminated) */
           form->name = Curl_memdup(form->name, form->namelength?
           form->name = Curl_memdup(form->name, form->namelength?
                                    form->namelength:
                                    form->namelength:
                                    strlen(form->name) + 1);
                                    strlen(form->name) + 1);
@@ -771,7 +771,7 @@ void curl_formfree(struct curl_httppost *form)
 }
 }
 
 
 
 
-/* Set mime part name, taking care of non nul-terminated name string. */
+/* Set mime part name, taking care of non null-terminated name string. */
 static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
 static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
 {
 {
   char *zname;
   char *zname;

+ 11 - 7
lib/ftp.c

@@ -1043,6 +1043,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   } /* data->set.ftpport */
   } /* data->set.ftpport */
 
 
   if(!host) {
   if(!host) {
+    const char *r;
     /* not an interface and not a host name, get default by extracting
     /* not an interface and not a host name, get default by extracting
        the IP from the control connection */
        the IP from the control connection */
     sslen = sizeof(ss);
     sslen = sizeof(ss);
@@ -1055,13 +1056,15 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
     switch(sa->sa_family) {
     switch(sa->sa_family) {
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
     case AF_INET6:
     case AF_INET6:
-      Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
+      r = Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
       break;
       break;
 #endif
 #endif
     default:
     default:
-      Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
+      r = Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
       break;
       break;
     }
     }
+    if(!r)
+      return CURLE_FTP_PORT_FAILED;
     host = hbuf; /* use this host name */
     host = hbuf; /* use this host name */
     possibly_non_local = FALSE; /* we know it is local now */
     possibly_non_local = FALSE; /* we know it is local now */
   }
   }
@@ -1449,7 +1452,7 @@ static CURLcode ftp_state_list(struct connectdata *conn)
     /* url-decode before evaluation: e.g. paths starting/ending with %2f */
     /* url-decode before evaluation: e.g. paths starting/ending with %2f */
     const char *slashPos = NULL;
     const char *slashPos = NULL;
     char *rawPath = NULL;
     char *rawPath = NULL;
-    result = Curl_urldecode(data, ftp->path, 0, &rawPath, NULL, TRUE);
+    result = Curl_urldecode(data, ftp->path, 0, &rawPath, NULL, REJECT_CTRL);
     if(result)
     if(result)
       return result;
       return result;
 
 
@@ -2824,7 +2827,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
             store++;
             store++;
             ptr++;
             ptr++;
           }
           }
-          *store = '\0'; /* zero terminate */
+          *store = '\0'; /* null-terminate */
         }
         }
         if(entry_extracted) {
         if(entry_extracted) {
           /* If the path name does not look like an absolute path (i.e.: it
           /* If the path name does not look like an absolute path (i.e.: it
@@ -2888,7 +2891,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
           ptr++;
           ptr++;
         for(store = os; *ptr && *ptr != ' ';)
         for(store = os; *ptr && *ptr != ' ';)
           *store++ = *ptr++;
           *store++ = *ptr++;
-        *store = '\0'; /* zero terminate */
+        *store = '\0'; /* null-terminate */
 
 
         /* Check for special servers here. */
         /* Check for special servers here. */
 
 
@@ -3191,7 +3194,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
 
 
   if(!result)
   if(!result)
     /* get the url-decoded "raw" path */
     /* get the url-decoded "raw" path */
-    result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
+    result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen,
+                            REJECT_CTRL);
   if(result) {
   if(result) {
     /* We can limp along anyway (and should try to since we may already be in
     /* We can limp along anyway (and should try to since we may already be in
      * the error path) */
      * the error path) */
@@ -4107,7 +4111,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
   ftpc->cwdfail = FALSE;
   ftpc->cwdfail = FALSE;
 
 
   /* url-decode ftp path before further evaluation */
   /* url-decode ftp path before further evaluation */
-  result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
+  result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, REJECT_CTRL);
   if(result)
   if(result)
     return result;
     return result;
 
 

+ 1 - 1
lib/gopher.c

@@ -116,7 +116,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
     newp += 2;
     newp += 2;
 
 
     /* ... and finally unescape */
     /* ... and finally unescape */
-    result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
+    result = Curl_urldecode(data, newp, 0, &sel, &len, REJECT_ZERO);
     free(gopherpath);
     free(gopherpath);
     if(result)
     if(result)
       return result;
       return result;

+ 6 - 4
lib/http.c

@@ -125,7 +125,8 @@ const struct Curl_handler Curl_handler_http = {
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* connection_check */
   PORT_HTTP,                            /* defport */
   PORT_HTTP,                            /* defport */
   CURLPROTO_HTTP,                       /* protocol */
   CURLPROTO_HTTP,                       /* protocol */
-  PROTOPT_CREDSPERREQUEST               /* flags */
+  PROTOPT_CREDSPERREQUEST |             /* flags */
+  PROTOPT_USERPWDCTRL
 };
 };
 
 
 #ifdef USE_SSL
 #ifdef USE_SSL
@@ -150,7 +151,8 @@ const struct Curl_handler Curl_handler_https = {
   ZERO_NULL,                            /* connection_check */
   ZERO_NULL,                            /* connection_check */
   PORT_HTTPS,                           /* defport */
   PORT_HTTPS,                           /* defport */
   CURLPROTO_HTTPS,                      /* protocol */
   CURLPROTO_HTTPS,                      /* protocol */
-  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN /* flags */
+  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
+  PROTOPT_USERPWDCTRL
 };
 };
 #endif
 #endif
 
 
@@ -268,7 +270,7 @@ char *Curl_copy_header_value(const char *header)
     return NULL;
     return NULL;
 
 
   memcpy(value, start, len);
   memcpy(value, start, len);
-  value[len] = 0; /* zero terminate */
+  value[len] = 0; /* null-terminate */
 
 
   return value;
   return value;
 }
 }
@@ -306,7 +308,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
     pwd = conn->passwd;
     pwd = conn->passwd;
   }
   }
 
 
-  out = aprintf("%s:%s", user, pwd);
+  out = aprintf("%s:%s", user, pwd ? pwd : "");
   if(!out)
   if(!out)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
 
 

+ 44 - 0
lib/http2.c

@@ -469,6 +469,46 @@ static struct Curl_easy *duphandle(struct Curl_easy *data)
   return second;
   return second;
 }
 }
 
 
+static int set_transfer_url(struct Curl_easy *data,
+                            struct curl_pushheaders *hp)
+{
+  const char *v;
+  CURLU *u = curl_url();
+  CURLUcode uc;
+  char *url;
+
+  v = curl_pushheader_byname(hp, ":scheme");
+  if(v) {
+    uc = curl_url_set(u, CURLUPART_SCHEME, v, 0);
+    if(uc)
+      return 1;
+  }
+
+  v = curl_pushheader_byname(hp, ":authority");
+  if(v) {
+    uc = curl_url_set(u, CURLUPART_HOST, v, 0);
+    if(uc)
+      return 2;
+  }
+
+  v = curl_pushheader_byname(hp, ":path");
+  if(v) {
+    uc = curl_url_set(u, CURLUPART_PATH, v, 0);
+    if(uc)
+      return 3;
+  }
+
+  uc = curl_url_get(u, CURLUPART_URL, &url, 0);
+  if(uc)
+    return 4;
+  curl_url_cleanup(u);
+
+  if(data->change.url_alloc)
+    free(data->change.url);
+  data->change.url_alloc = TRUE;
+  data->change.url = url;
+  return 0;
+}
 
 
 static int push_promise(struct Curl_easy *data,
 static int push_promise(struct Curl_easy *data,
                         struct connectdata *conn,
                         struct connectdata *conn,
@@ -505,6 +545,10 @@ static int push_promise(struct Curl_easy *data,
       goto fail;
       goto fail;
     }
     }
 
 
+    rv = set_transfer_url(newhandle, &heads);
+    if(rv)
+      goto fail;
+
     Curl_set_in_callback(data, true);
     Curl_set_in_callback(data, true);
     rv = data->multi->push_cb(data, newhandle,
     rv = data->multi->push_cb(data, newhandle,
                               stream->push_headers_used, &heads,
                               stream->push_headers_used, &heads,

+ 8 - 5
lib/if2ip.c

@@ -118,7 +118,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
         if(iface->ifa_addr->sa_family == af) {
         if(iface->ifa_addr->sa_family == af) {
           if(strcasecompare(iface->ifa_name, interf)) {
           if(strcasecompare(iface->ifa_name, interf)) {
             void *addr;
             void *addr;
-            char *ip;
+            const char *ip;
             char scope[12] = "";
             char scope[12] = "";
             char ipstr[64];
             char ipstr[64];
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
@@ -153,15 +153,15 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
               }
               }
 
 
               if(scopeid)
               if(scopeid)
-                  msnprintf(scope, sizeof(scope), "%%%u", scopeid);
+                msnprintf(scope, sizeof(scope), "%%%u", scopeid);
 #endif
 #endif
             }
             }
             else
             else
 #endif
 #endif
               addr =
               addr =
-                  &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
+                &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
             res = IF2IP_FOUND;
             res = IF2IP_FOUND;
-            ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
+            ip = Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
             msnprintf(buf, buf_size, "%s%s", ip, scope);
             msnprintf(buf, buf_size, "%s%s", ip, scope);
             break;
             break;
           }
           }
@@ -190,6 +190,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
   struct sockaddr_in *s;
   struct sockaddr_in *s;
   curl_socket_t dummy;
   curl_socket_t dummy;
   size_t len;
   size_t len;
+  const char *r;
 
 
   (void)remote_scope;
   (void)remote_scope;
   (void)local_scope_id;
   (void)local_scope_id;
@@ -219,9 +220,11 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 
   s = (struct sockaddr_in *)(void *)&req.ifr_addr;
   s = (struct sockaddr_in *)(void *)&req.ifr_addr;
   memcpy(&in, &s->sin_addr, sizeof(in));
   memcpy(&in, &s->sin_addr, sizeof(in));
-  Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
+  r = Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
 
 
   sclose(dummy);
   sclose(dummy);
+  if(!r)
+    return IF2IP_NOT_FOUND;
   return IF2IP_FOUND;
   return IF2IP_FOUND;
 }
 }
 
 

+ 6 - 4
lib/imap.c

@@ -1957,7 +1957,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
       end--;
       end--;
 
 
     result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL,
     result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL,
-                            TRUE);
+                            REJECT_CTRL);
     if(result)
     if(result)
       return result;
       return result;
   }
   }
@@ -1979,7 +1979,8 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
       return CURLE_URL_MALFORMAT;
       return CURLE_URL_MALFORMAT;
 
 
     /* Decode the name parameter */
     /* Decode the name parameter */
-    result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE);
+    result = Curl_urldecode(data, begin, ptr - begin, &name, NULL,
+                            REJECT_CTRL);
     if(result)
     if(result)
       return result;
       return result;
 
 
@@ -1989,7 +1990,8 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
       ptr++;
       ptr++;
 
 
     /* Decode the value parameter */
     /* Decode the value parameter */
-    result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE);
+    result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen,
+                            REJECT_CTRL);
     if(result) {
     if(result) {
       free(name);
       free(name);
       return result;
       return result;
@@ -2077,7 +2079,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
 
 
   if(custom) {
   if(custom) {
     /* URL decode the custom request */
     /* URL decode the custom request */
-    result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, TRUE);
+    result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, REJECT_CTRL);
 
 
     /* Extract the parameters if specified */
     /* Extract the parameters if specified */
     if(!result) {
     if(!result) {

+ 4 - 3
lib/ldap.c

@@ -883,7 +883,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
     LDAP_TRACE(("DN '%s'\n", dn));
     LDAP_TRACE(("DN '%s'\n", dn));
 
 
     /* Unescape the DN */
     /* Unescape the DN */
-    result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
+    result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, REJECT_ZERO);
     if(result) {
     if(result) {
       rc = LDAP_NO_MEMORY;
       rc = LDAP_NO_MEMORY;
 
 
@@ -949,7 +949,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
 
       /* Unescape the attribute */
       /* Unescape the attribute */
       result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
       result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
-                              FALSE);
+                              REJECT_ZERO);
       if(result) {
       if(result) {
         free(attributes);
         free(attributes);
 
 
@@ -1018,7 +1018,8 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
     LDAP_TRACE(("filter '%s'\n", filter));
     LDAP_TRACE(("filter '%s'\n", filter));
 
 
     /* Unescape the filter */
     /* Unescape the filter */
-    result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
+    result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL,
+                            REJECT_ZERO);
     if(result) {
     if(result) {
       rc = LDAP_NO_MEMORY;
       rc = LDAP_NO_MEMORY;
 
 

+ 1 - 1
lib/mime.c

@@ -1419,7 +1419,7 @@ CURLcode curl_mime_data(curl_mimepart *part,
 
 
     if(datasize)
     if(datasize)
       memcpy(part->data, data, datasize);
       memcpy(part->data, data, datasize);
-    part->data[datasize] = '\0';    /* Set a nul terminator as sentinel. */
+    part->data[datasize] = '\0';    /* Set a null terminator as sentinel. */
 
 
     part->readfunc = mime_mem_read;
     part->readfunc = mime_mem_read;
     part->seekfunc = mime_mem_seek;
     part->seekfunc = mime_mem_seek;

+ 2 - 1
lib/mqtt.c

@@ -211,7 +211,8 @@ static CURLcode mqtt_get_topic(struct connectdata *conn,
   char *path = conn->data->state.up.path;
   char *path = conn->data->state.up.path;
 
 
   if(strlen(path) > 1) {
   if(strlen(path) > 1) {
-    result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen, FALSE);
+    result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen,
+                            REJECT_NADA);
   }
   }
   else {
   else {
     failf(conn->data, "Error: No topic specified.");
     failf(conn->data, "Error: No topic specified.");

+ 4 - 118
lib/multi.c

@@ -374,11 +374,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
   multi->max_concurrent_streams = 100;
   multi->max_concurrent_streams = 100;
   multi->ipv6_works = Curl_ipv6works(NULL);
   multi->ipv6_works = Curl_ipv6works(NULL);
 
 
-#ifdef USE_WINSOCK
-  multi->wsa_event = WSACreateEvent();
-  if(multi->wsa_event == WSA_INVALID_EVENT)
-    goto error;
-#else
 #ifdef ENABLE_WAKEUP
 #ifdef ENABLE_WAKEUP
   if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
   if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
     multi->wakeup_pair[0] = CURL_SOCKET_BAD;
     multi->wakeup_pair[0] = CURL_SOCKET_BAD;
@@ -391,7 +386,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
     multi->wakeup_pair[0] = CURL_SOCKET_BAD;
     multi->wakeup_pair[0] = CURL_SOCKET_BAD;
     multi->wakeup_pair[1] = CURL_SOCKET_BAD;
     multi->wakeup_pair[1] = CURL_SOCKET_BAD;
   }
   }
-#endif
 #endif
 #endif
 
 
   return multi;
   return multi;
@@ -1073,15 +1067,11 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
   unsigned int i;
   unsigned int i;
   unsigned int nfds = 0;
   unsigned int nfds = 0;
   unsigned int curlfds;
   unsigned int curlfds;
+  bool ufds_malloc = FALSE;
   long timeout_internal;
   long timeout_internal;
   int retcode = 0;
   int retcode = 0;
-#ifndef USE_WINSOCK
   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
   struct pollfd *ufds = &a_few_on_stack[0];
   struct pollfd *ufds = &a_few_on_stack[0];
-  bool ufds_malloc = FALSE;
-#else
-  DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
-#endif
 
 
   if(!GOOD_MULTI_HANDLE(multi))
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
     return CURLM_BAD_HANDLE;
@@ -1127,16 +1117,11 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
   nfds += extra_nfds; /* add the externally provided ones */
   nfds += extra_nfds; /* add the externally provided ones */
 
 
 #ifdef ENABLE_WAKEUP
 #ifdef ENABLE_WAKEUP
-#ifdef USE_WINSOCK
-  if(use_wakeup) {
-#else
   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
-#endif
     ++nfds;
     ++nfds;
   }
   }
 #endif
 #endif
 
 
-#ifndef USE_WINSOCK
   if(nfds > NUM_POLLS_ON_STACK) {
   if(nfds > NUM_POLLS_ON_STACK) {
     /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
     /* '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
        big, so at 2^29 sockets this value might wrap. When a process gets
@@ -1147,9 +1132,7 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
       return CURLM_OUT_OF_MEMORY;
       return CURLM_OUT_OF_MEMORY;
     ufds_malloc = TRUE;
     ufds_malloc = TRUE;
   }
   }
-
   nfds = 0;
   nfds = 0;
-#endif
 
 
   /* only do the second loop if we found descriptors in the first stage run
   /* only do the second loop if we found descriptors in the first stage run
      above */
      above */
@@ -1162,36 +1145,22 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
 
 
       for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
       for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
         curl_socket_t s = CURL_SOCKET_BAD;
         curl_socket_t s = CURL_SOCKET_BAD;
-#ifdef USE_WINSOCK
-        long mask = 0;
-#endif
+
         if(bitmap & GETSOCK_READSOCK(i)) {
         if(bitmap & GETSOCK_READSOCK(i)) {
-#ifdef USE_WINSOCK
-          mask |= FD_READ;
-#else
           ufds[nfds].fd = sockbunch[i];
           ufds[nfds].fd = sockbunch[i];
           ufds[nfds].events = POLLIN;
           ufds[nfds].events = POLLIN;
           ++nfds;
           ++nfds;
-#endif
           s = sockbunch[i];
           s = sockbunch[i];
         }
         }
         if(bitmap & GETSOCK_WRITESOCK(i)) {
         if(bitmap & GETSOCK_WRITESOCK(i)) {
-#ifdef USE_WINSOCK
-          mask |= FD_WRITE;
-#else
           ufds[nfds].fd = sockbunch[i];
           ufds[nfds].fd = sockbunch[i];
           ufds[nfds].events = POLLOUT;
           ufds[nfds].events = POLLOUT;
           ++nfds;
           ++nfds;
-#endif
           s = sockbunch[i];
           s = sockbunch[i];
         }
         }
         if(s == CURL_SOCKET_BAD) {
         if(s == CURL_SOCKET_BAD) {
           break;
           break;
         }
         }
-#ifdef USE_WINSOCK
-        if(WSAEventSelect(s, multi->wsa_event, mask) != 0)
-          return CURLM_INTERNAL_ERROR;
-#endif
       }
       }
 
 
       data = data->next; /* check next handle */
       data = data->next; /* check next handle */
@@ -1200,17 +1169,6 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
 
 
   /* Add external file descriptions from poll-like struct curl_waitfd */
   /* Add external file descriptions from poll-like struct curl_waitfd */
   for(i = 0; i < extra_nfds; i++) {
   for(i = 0; i < extra_nfds; i++) {
-#ifdef USE_WINSOCK
-    long events = 0;
-    if(extra_fds[i].events & CURL_WAIT_POLLIN)
-      events |= FD_READ;
-    if(extra_fds[i].events & CURL_WAIT_POLLPRI)
-      events |= FD_OOB;
-    if(extra_fds[i].events & CURL_WAIT_POLLOUT)
-      events |= FD_WRITE;
-    if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, events) != 0)
-      return CURLM_INTERNAL_ERROR;
-#else
     ufds[nfds].fd = extra_fds[i].fd;
     ufds[nfds].fd = extra_fds[i].fd;
     ufds[nfds].events = 0;
     ufds[nfds].events = 0;
     if(extra_fds[i].events & CURL_WAIT_POLLIN)
     if(extra_fds[i].events & CURL_WAIT_POLLIN)
@@ -1220,61 +1178,28 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
     if(extra_fds[i].events & CURL_WAIT_POLLOUT)
     if(extra_fds[i].events & CURL_WAIT_POLLOUT)
       ufds[nfds].events |= POLLOUT;
       ufds[nfds].events |= POLLOUT;
     ++nfds;
     ++nfds;
-#endif
   }
   }
 
 
 #ifdef ENABLE_WAKEUP
 #ifdef ENABLE_WAKEUP
-#ifndef USE_WINSOCK
   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
     ufds[nfds].fd = multi->wakeup_pair[0];
     ufds[nfds].fd = multi->wakeup_pair[0];
     ufds[nfds].events = POLLIN;
     ufds[nfds].events = POLLIN;
     ++nfds;
     ++nfds;
   }
   }
-#endif
 #endif
 #endif
 
 
   if(nfds) {
   if(nfds) {
     int pollrc;
     int pollrc;
     /* wait... */
     /* wait... */
-#ifdef USE_WINSOCK
-    DWORD waitrc = WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE,
-                                            timeout_ms, FALSE);
-    /* WSA_WAIT_EVENT_0 is 0, so waitrc >= WSA_WAIT_EVENT_0 warns */
-    if(waitrc == WSA_WAIT_EVENT_0)
-      pollrc = 1;
-    else
-      pollrc = -1;
-#else
     pollrc = Curl_poll(ufds, nfds, timeout_ms);
     pollrc = Curl_poll(ufds, nfds, timeout_ms);
-#endif
 
 
     if(pollrc > 0) {
     if(pollrc > 0) {
-#ifdef USE_WINSOCK
-      retcode = 0;
-#else
       retcode = pollrc;
       retcode = pollrc;
-#endif
       /* copy revents results from the poll to the curl_multi_wait poll
       /* copy revents results from the poll to the curl_multi_wait poll
          struct, the bit values of the actual underlying poll() implementation
          struct, the bit values of the actual underlying poll() implementation
          may not be the same as the ones in the public libcurl API! */
          may not be the same as the ones in the public libcurl API! */
       for(i = 0; i < extra_nfds; i++) {
       for(i = 0; i < extra_nfds; i++) {
         unsigned short mask = 0;
         unsigned short mask = 0;
-#ifdef USE_WINSOCK
-        WSANETWORKEVENTS events = {0};
-        if(WSAEnumNetworkEvents(extra_fds[i].fd, multi->wsa_event,
-                                &events) == 0) {
-          if(events.lNetworkEvents & FD_READ)
-            mask |= CURL_WAIT_POLLIN;
-          if(events.lNetworkEvents & FD_WRITE)
-            mask |= CURL_WAIT_POLLOUT;
-          if(events.lNetworkEvents & FD_OOB)
-            mask |= CURL_WAIT_POLLPRI;
-
-          if(events.lNetworkEvents != 0)
-            retcode++;
-        }
-        WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
-#else
         unsigned r = ufds[curlfds + i].revents;
         unsigned r = ufds[curlfds + i].revents;
 
 
         if(r & POLLIN)
         if(r & POLLIN)
@@ -1283,39 +1208,10 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
           mask |= CURL_WAIT_POLLOUT;
           mask |= CURL_WAIT_POLLOUT;
         if(r & POLLPRI)
         if(r & POLLPRI)
           mask |= CURL_WAIT_POLLPRI;
           mask |= CURL_WAIT_POLLPRI;
-#endif
 
 
         extra_fds[i].revents = mask;
         extra_fds[i].revents = mask;
       }
       }
 
 
-#ifdef USE_WINSOCK
-      /* Count up all our own sockets that had activity,
-         and remove them from the event. */
-      if(curlfds) {
-        data = multi->easyp;
-        while(data) {
-          bitmap = multi_getsock(data, sockbunch);
-
-          for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
-            if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
-              WSANETWORKEVENTS events = {0};
-              if(WSAEnumNetworkEvents(sockbunch[i], multi->wsa_event,
-                                      &events) == 0) {
-                if(events.lNetworkEvents != 0)
-                  retcode++;
-              }
-              WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
-            }
-            else
-              break;
-          }
-
-          data = data->next;
-        }
-      }
-
-      WSAResetEvent(multi->wsa_event);
-#else
 #ifdef ENABLE_WAKEUP
 #ifdef ENABLE_WAKEUP
       if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
       if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
         if(ufds[curlfds + extra_nfds].revents & POLLIN) {
         if(ufds[curlfds + extra_nfds].revents & POLLIN) {
@@ -1328,8 +1224,10 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
                when there is no more data, breaking the loop. */
                when there is no more data, breaking the loop. */
             nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
             nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
             if(nread <= 0) {
             if(nread <= 0) {
+#ifndef USE_WINSOCK
               if(nread < 0 && EINTR == SOCKERRNO)
               if(nread < 0 && EINTR == SOCKERRNO)
                 continue;
                 continue;
+#endif
               break;
               break;
             }
             }
           }
           }
@@ -1337,15 +1235,12 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
           retcode--;
           retcode--;
         }
         }
       }
       }
-#endif
 #endif
 #endif
     }
     }
   }
   }
 
 
-#ifndef USE_WINSOCK
   if(ufds_malloc)
   if(ufds_malloc)
     free(ufds);
     free(ufds);
-#endif
   if(ret)
   if(ret)
     *ret = retcode;
     *ret = retcode;
   if(!extrawait || nfds)
   if(!extrawait || nfds)
@@ -1400,10 +1295,6 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
     return CURLM_BAD_HANDLE;
     return CURLM_BAD_HANDLE;
 
 
 #ifdef ENABLE_WAKEUP
 #ifdef ENABLE_WAKEUP
-#ifdef USE_WINSOCK
-  if(WSASetEvent(multi->wsa_event))
-    return CURLM_OK;
-#else
   /* the wakeup_pair variable is only written during init and cleanup,
   /* the wakeup_pair variable is only written during init and cleanup,
      making it safe to access from another thread after the init part
      making it safe to access from another thread after the init part
      and before cleanup */
      and before cleanup */
@@ -1436,7 +1327,6 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
       return CURLM_OK;
       return CURLM_OK;
     }
     }
   }
   }
-#endif
 #endif
 #endif
   return CURLM_WAKEUP_FAILURE;
   return CURLM_WAKEUP_FAILURE;
 }
 }
@@ -2596,13 +2486,9 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
     Curl_hash_destroy(&multi->hostcache);
     Curl_hash_destroy(&multi->hostcache);
     Curl_psl_destroy(&multi->psl);
     Curl_psl_destroy(&multi->psl);
 
 
-#ifdef USE_WINSOCK
-    WSACloseEvent(multi->wsa_event);
-#else
 #ifdef ENABLE_WAKEUP
 #ifdef ENABLE_WAKEUP
     sclose(multi->wakeup_pair[0]);
     sclose(multi->wakeup_pair[0]);
     sclose(multi->wakeup_pair[1]);
     sclose(multi->wakeup_pair[1]);
-#endif
 #endif
 #endif
     free(multi);
     free(multi);
 
 

+ 0 - 4
lib/multihandle.h

@@ -138,13 +138,9 @@ struct Curl_multi {
                                     previous callback */
                                     previous callback */
   unsigned int max_concurrent_streams;
   unsigned int max_concurrent_streams;
 
 
-#ifdef USE_WINSOCK
-  WSAEVENT wsa_event; /* winsock event used for waits */
-#else
 #ifdef ENABLE_WAKEUP
 #ifdef ENABLE_WAKEUP
   curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup
   curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup
                                    0 is used for read, 1 is used for write */
                                    0 is used for read, 1 is used for write */
-#endif
 #endif
 #endif
   /* multiplexing wanted */
   /* multiplexing wanted */
   bool multiplexing;
   bool multiplexing;

+ 2 - 2
lib/pingpong.c

@@ -384,10 +384,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
 
 
           if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
           if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
             /* This is the end of the last line, copy the last line to the
             /* This is the end of the last line, copy the last line to the
-               start of the buffer and zero terminate, for old times sake */
+               start of the buffer and null-terminate, for old times sake */
             size_t n = ptr - pp->linestart_resp;
             size_t n = ptr - pp->linestart_resp;
             memmove(buf, pp->linestart_resp, n);
             memmove(buf, pp->linestart_resp, n);
-            buf[n] = 0; /* zero terminate */
+            buf[n] = 0; /* null-terminate */
             keepon = FALSE;
             keepon = FALSE;
             pp->linestart_resp = ptr + 1; /* advance pointer */
             pp->linestart_resp = ptr + 1; /* advance pointer */
             i++; /* skip this before getting out */
             i++; /* skip this before getting out */

+ 2 - 2
lib/pop3.c

@@ -1390,7 +1390,7 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
   const char *path = &data->state.up.path[1]; /* skip leading path */
   const char *path = &data->state.up.path[1]; /* skip leading path */
 
 
   /* URL decode the path for the message ID */
   /* URL decode the path for the message ID */
-  return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
+  return Curl_urldecode(data, path, 0, &pop3->id, NULL, REJECT_CTRL);
 }
 }
 
 
 /***********************************************************************
 /***********************************************************************
@@ -1408,7 +1408,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
 
 
   /* URL decode the custom request */
   /* URL decode the custom request */
   if(custom)
   if(custom)
-    result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
+    result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, REJECT_CTRL);
 
 
   return result;
   return result;
 }
 }

+ 1 - 1
lib/sendf.c

@@ -593,7 +593,7 @@ static CURLcode chop_write(struct connectdata *conn,
         return pausewrite(data, type, ptr, len);
         return pausewrite(data, type, ptr, len);
       }
       }
       if(wrote != chunklen) {
       if(wrote != chunklen) {
-        failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
+        failf(data, "Failure writing output to destination");
         return CURLE_WRITE_ERROR;
         return CURLE_WRITE_ERROR;
       }
       }
     }
     }

+ 2 - 2
lib/smb.c

@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
  * Copyright (C) 2014, Bill Nagel <[email protected]>, Exacq Technologies
  * Copyright (C) 2014, Bill Nagel <[email protected]>, Exacq Technologies
- * Copyright (C) 2016-2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2016-2020, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -964,7 +964,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn)
 
 
   /* URL decode the path */
   /* URL decode the path */
   CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL,
   CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL,
-                                   TRUE);
+                                   REJECT_CTRL);
   if(result)
   if(result)
     return result;
     return result;
 
 

+ 3 - 2
lib/smtp.c

@@ -1689,7 +1689,8 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
   }
   }
 
 
   /* URL decode the path and use it as the domain in our EHLO */
   /* URL decode the path and use it as the domain in our EHLO */
-  return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
+  return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL,
+                        REJECT_CTRL);
 }
 }
 
 
 /***********************************************************************
 /***********************************************************************
@@ -1707,7 +1708,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn)
 
 
   /* URL decode the custom request */
   /* URL decode the custom request */
   if(custom)
   if(custom)
-    result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE);
+    result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, REJECT_CTRL);
 
 
   return result;
   return result;
 }
 }

+ 1 - 1
lib/strerror.c

@@ -795,7 +795,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
 
 
 #endif /* end of not Windows */
 #endif /* end of not Windows */
 
 
-  buf[max] = '\0'; /* make sure the string is zero terminated */
+  buf[max] = '\0'; /* make sure the string is null-terminated */
 
 
   /* strip trailing '\r\n' or '\n'. */
   /* strip trailing '\r\n' or '\n'. */
   p = strrchr(buf, '\n');
   p = strrchr(buf, '\n');

+ 2 - 2
lib/strtok.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -52,7 +52,7 @@ Curl_strtok_r(char *ptr, const char *sep, char **end)
 
 
     if(**end) {
     if(**end) {
       /* the end is not a null byte */
       /* the end is not a null byte */
-      **end = '\0';  /* zero terminate it! */
+      **end = '\0';  /* null-terminate it! */
       ++*end;        /* advance the last pointer to beyond the null byte */
       ++*end;        /* advance the last pointer to beyond the null byte */
     }
     }
 
 

+ 1 - 1
lib/tftp.c

@@ -487,7 +487,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
        file name so we skip the always-present first letter of the path
        file name so we skip the always-present first letter of the path
        string. */
        string. */
     result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
     result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
-                            &filename, NULL, FALSE);
+                            &filename, NULL, REJECT_ZERO);
     if(result)
     if(result)
       return result;
       return result;
 
 

+ 24 - 13
lib/url.c

@@ -1894,23 +1894,32 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   if(result)
   if(result)
     return result;
     return result;
 
 
-  uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user,
-                    CURLU_URLDECODE);
+  /* we don't use the URL API's URL decoder option here since it rejects
+     control codes and we want to allow them for some schemes in the user and
+     password fields */
+  uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
   if(!uc) {
   if(!uc) {
-    conn->user = strdup(data->state.up.user);
-    if(!conn->user)
-      return CURLE_OUT_OF_MEMORY;
+    char *decoded;
+    result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL,
+                            conn->handler->flags&PROTOPT_USERPWDCTRL ?
+                            REJECT_ZERO : REJECT_CTRL);
+    if(result)
+      return result;
+    conn->user = decoded;
     conn->bits.user_passwd = TRUE;
     conn->bits.user_passwd = TRUE;
   }
   }
   else if(uc != CURLUE_NO_USER)
   else if(uc != CURLUE_NO_USER)
     return Curl_uc_to_curlcode(uc);
     return Curl_uc_to_curlcode(uc);
 
 
-  uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password,
-                    CURLU_URLDECODE);
+  uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
   if(!uc) {
   if(!uc) {
-    conn->passwd = strdup(data->state.up.password);
-    if(!conn->passwd)
-      return CURLE_OUT_OF_MEMORY;
+    char *decoded;
+    result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL,
+                            conn->handler->flags&PROTOPT_USERPWDCTRL ?
+                            REJECT_ZERO : REJECT_CTRL);
+    if(result)
+      return result;
+    conn->passwd = decoded;
     conn->bits.user_passwd = TRUE;
     conn->bits.user_passwd = TRUE;
   }
   }
   else if(uc != CURLUE_NO_PASSWORD)
   else if(uc != CURLUE_NO_PASSWORD)
@@ -2373,10 +2382,10 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
 
 
   if(proxyuser)
   if(proxyuser)
     result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
     result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
-                            FALSE);
+                            REJECT_ZERO);
   if(!result && proxypasswd)
   if(!result && proxypasswd)
     result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
     result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
-                            NULL, FALSE);
+                            NULL, REJECT_ZERO);
   return result;
   return result;
 }
 }
 
 
@@ -3600,6 +3609,7 @@ static CURLcode create_conn(struct Curl_easy *data,
     data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
     data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
   data->set.ssl.primary.pinned_key =
   data->set.ssl.primary.pinned_key =
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+  data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
 
 
 #ifndef CURL_DISABLE_PROXY
 #ifndef CURL_DISABLE_PROXY
   data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
   data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
@@ -3613,6 +3623,7 @@ static CURLcode create_conn(struct Curl_easy *data,
     data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
     data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
   data->set.proxy_ssl.primary.pinned_key =
   data->set.proxy_ssl.primary.pinned_key =
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
+  data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
   data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
   data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
   data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
   data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
   data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
   data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
@@ -3646,7 +3657,7 @@ static CURLcode create_conn(struct Curl_easy *data,
   data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG];
   data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG];
 
 
   if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
   if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
-     &conn->ssl_config)) {
+                                    &conn->ssl_config)) {
     result = CURLE_OUT_OF_MEMORY;
     result = CURLE_OUT_OF_MEMORY;
     goto out;
     goto out;
   }
   }

+ 8 - 5
lib/urlapi.c

@@ -225,7 +225,7 @@ static void strcpy_url(char *output, const char *url, bool relative)
       break;
       break;
     }
     }
   }
   }
-  *optr = 0; /* zero terminate output buffer */
+  *optr = 0; /* null-terminate output buffer */
 
 
 }
 }
 
 
@@ -584,7 +584,7 @@ static CURLUcode junkscan(const char *part)
       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
       0x7f,
       0x7f,
-      0x00 /* zero terminate */
+      0x00 /* null-terminate */
     };
     };
     size_t n = strlen(part);
     size_t n = strlen(part);
     size_t nfine = strcspn(part, badbytes);
     size_t nfine = strcspn(part, badbytes);
@@ -1185,7 +1185,10 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
     if(urldecode) {
     if(urldecode) {
       char *decoded;
       char *decoded;
       size_t dlen;
       size_t dlen;
-      CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen, TRUE);
+      /* this unconditional rejection of control bytes is documented
+         API behavior */
+      CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen,
+                                    REJECT_CTRL);
       free(*part);
       free(*part);
       if(res) {
       if(res) {
         *part = NULL;
         *part = NULL;
@@ -1395,7 +1398,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
         i = (const unsigned char *)part;
         i = (const unsigned char *)part;
         for(o = enc; *i; ++o, ++i)
         for(o = enc; *i; ++o, ++i)
           *o = (*i == ' ') ? '+' : *i;
           *o = (*i == ' ') ? '+' : *i;
-        *o = 0; /* zero terminate */
+        *o = 0; /* null-terminate */
         part = strdup(enc);
         part = strdup(enc);
         if(!part) {
         if(!part) {
           free(enc);
           free(enc);
@@ -1419,7 +1422,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
           o += 3;
           o += 3;
         }
         }
       }
       }
-      *o = 0; /* zero terminate */
+      *o = 0; /* null-terminate */
       newp = enc;
       newp = enc;
       if(free_part)
       if(free_part)
         free((char *)part);
         free((char *)part);

+ 4 - 1
lib/urldata.h

@@ -229,6 +229,7 @@ struct ssl_primary_config {
   char *cipher_list;     /* list of ciphers to use */
   char *cipher_list;     /* list of ciphers to use */
   char *cipher_list13;   /* list of TLS 1.3 cipher suites to use */
   char *cipher_list13;   /* list of TLS 1.3 cipher suites to use */
   char *pinned_key;
   char *pinned_key;
+  struct curl_blob *cert_blob;
   BIT(verifypeer);       /* set TRUE if this is desired */
   BIT(verifypeer);       /* set TRUE if this is desired */
   BIT(verifyhost);       /* set TRUE if CN/SAN must match hostname */
   BIT(verifyhost);       /* set TRUE if CN/SAN must match hostname */
   BIT(verifystatus);     /* set TRUE if certificate status must be checked */
   BIT(verifystatus);     /* set TRUE if certificate status must be checked */
@@ -766,6 +767,8 @@ struct Curl_handler {
                                          HTTP proxy as HTTP proxies may know
                                          HTTP proxy as HTTP proxies may know
                                          this protocol and act as a gateway */
                                          this protocol and act as a gateway */
 #define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */
 #define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */
+#define PROTOPT_USERPWDCTRL (1<<13) /* Allow "control bytes" (< 32 ascii) in
+                                       user name and password */
 
 
 #define CONNCHECK_NONE 0                 /* No checks */
 #define CONNCHECK_NONE 0                 /* No checks */
 #define CONNCHECK_ISDEAD (1<<0)          /* Check if the connection is dead. */
 #define CONNCHECK_ISDEAD (1<<0)          /* Check if the connection is dead. */
@@ -1562,7 +1565,7 @@ enum dupstring {
   STRING_DNS_LOCAL_IP4,
   STRING_DNS_LOCAL_IP4,
   STRING_DNS_LOCAL_IP6,
   STRING_DNS_LOCAL_IP6,
 
 
-  /* -- end of zero-terminated strings -- */
+  /* -- end of null-terminated strings -- */
 
 
   STRING_LASTZEROTERMINATED,
   STRING_LASTZEROTERMINATED,
 
 

+ 3 - 1
lib/vquic/ngtcp2.c

@@ -757,7 +757,9 @@ static ngtcp2_conn_callbacks ng_callbacks = {
   cb_extend_max_stream_data,
   cb_extend_max_stream_data,
   NULL, /* dcid_status */
   NULL, /* dcid_status */
   NULL, /* handshake_confirmed */
   NULL, /* handshake_confirmed */
-  NULL  /* recv_new_token */
+  NULL, /* recv_new_token */
+  ngtcp2_crypto_delete_crypto_aead_ctx_cb,
+  ngtcp2_crypto_delete_crypto_cipher_ctx_cb
 };
 };
 
 
 /*
 /*

+ 10 - 0
lib/vtls/mbedtls.c

@@ -246,9 +246,14 @@ mbed_connect_step1(struct connectdata *conn,
   const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
   const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
   char * const ssl_cert = SSL_SET_OPTION(cert);
   char * const ssl_cert = SSL_SET_OPTION(cert);
   const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
   const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+#ifndef CURL_DISABLE_PROXY
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
     conn->host.name;
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+#else
+  const char * const hostname = conn->host.name;
+  const long int port = conn->remote_port;
+#endif
   int ret = -1;
   int ret = -1;
   char errorbuf[128];
   char errorbuf[128];
   errorbuf[0] = 0;
   errorbuf[0] = 0;
@@ -538,9 +543,14 @@ mbed_connect_step2(struct connectdata *conn,
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct ssl_backend_data *backend = connssl->backend;
   struct ssl_backend_data *backend = connssl->backend;
   const mbedtls_x509_crt *peercert;
   const mbedtls_x509_crt *peercert;
+#ifndef CURL_DISABLE_PROXY
   const char * const pinnedpubkey = SSL_IS_PROXY() ?
   const char * const pinnedpubkey = SSL_IS_PROXY() ?
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#else
+  const char * const pinnedpubkey =
+    data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#endif
 
 
   conn->recv[sockindex] = mbed_recv;
   conn->recv[sockindex] = mbed_recv;
   conn->send[sockindex] = mbed_send;
   conn->send[sockindex] = mbed_send;

+ 6 - 5
lib/vtls/openssl.c

@@ -31,6 +31,11 @@
 
 
 #include <limits.h>
 #include <limits.h>
 
 
+/* Wincrypt must be included before anything that could include OpenSSL. */
+#if defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+#endif
+
 #include "urldata.h"
 #include "urldata.h"
 #include "sendf.h"
 #include "sendf.h"
 #include "formdata.h" /* for the boundary function */
 #include "formdata.h" /* for the boundary function */
@@ -48,10 +53,6 @@
 #include "strerror.h"
 #include "strerror.h"
 #include "curl_printf.h"
 #include "curl_printf.h"
 
 
-#if defined(USE_WIN32_CRYPTO)
-#include <wincrypt.h>
-#endif
-
 #include <openssl/ssl.h>
 #include <openssl/ssl.h>
 #include <openssl/rand.h>
 #include <openssl/rand.h>
 #include <openssl/x509v3.h>
 #include <openssl/x509v3.h>
@@ -1635,7 +1636,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
              type itself: for example for an IA5String the data will be ASCII"
              type itself: for example for an IA5String the data will be ASCII"
 
 
              It has been however verified that in 0.9.6 and 0.9.7, IA5String
              It has been however verified that in 0.9.6 and 0.9.7, IA5String
-             is always zero-terminated.
+             is always null-terminated.
           */
           */
           if((altlen == strlen(altptr)) &&
           if((altlen == strlen(altptr)) &&
              /* if this isn't true, there was an embedded zero in the name
              /* if this isn't true, there was an embedded zero in the name

+ 45 - 3
lib/vtls/vtls.c

@@ -63,6 +63,7 @@
 #include "warnless.h"
 #include "warnless.h"
 #include "curl_base64.h"
 #include "curl_base64.h"
 #include "curl_printf.h"
 #include "curl_printf.h"
+#include "strdup.h"
 
 
 /* The last #include files should be: */
 /* The last #include files should be: */
 #include "curl_memory.h"
 #include "curl_memory.h"
@@ -82,6 +83,44 @@
   else                                       \
   else                                       \
     dest->var = NULL;
     dest->var = NULL;
 
 
+#define CLONE_BLOB(var)                         \
+  if(blobdup(&dest->var, source->var))         \
+    return FALSE;
+
+static CURLcode blobdup(struct curl_blob **dest,
+                        struct curl_blob *src)
+{
+  DEBUGASSERT(dest);
+  DEBUGASSERT(!*dest);
+  if(src) {
+    /* only if there's data to dupe! */
+    struct curl_blob *d;
+    d = malloc(sizeof(struct curl_blob) + src->len);
+    if(!d)
+      return CURLE_OUT_OF_MEMORY;
+    d->len = src->len;
+    /* Always duplicate because the connection may survive longer than the
+       handle that passed in the blob. */
+    d->flags = CURL_BLOB_COPY;
+    d->data = (void *)((char *)d + sizeof(struct curl_blob));
+    memcpy(d->data, src->data, src->len);
+    *dest = d;
+  }
+  return CURLE_OK;
+}
+
+/* returns TRUE if the blobs are identical */
+static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
+{
+  if(!first && !second) /* both are NULL */
+    return TRUE;
+  if(!first || !second) /* one is NULL */
+    return FALSE;
+  if(first->len != second->len) /* different sizes */
+    return FALSE;
+  return !memcmp(first->data, second->data, first->len); /* same data */
+}
+
 bool
 bool
 Curl_ssl_config_matches(struct ssl_primary_config *data,
 Curl_ssl_config_matches(struct ssl_primary_config *data,
                         struct ssl_primary_config *needle)
                         struct ssl_primary_config *needle)
@@ -91,6 +130,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
      (data->verifypeer == needle->verifypeer) &&
      (data->verifypeer == needle->verifypeer) &&
      (data->verifyhost == needle->verifyhost) &&
      (data->verifyhost == needle->verifyhost) &&
      (data->verifystatus == needle->verifystatus) &&
      (data->verifystatus == needle->verifystatus) &&
+     blobcmp(data->cert_blob, needle->cert_blob) &&
      Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
      Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
      Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
      Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
      Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
      Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
@@ -115,6 +155,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
   dest->verifystatus = source->verifystatus;
   dest->verifystatus = source->verifystatus;
   dest->sessionid = source->sessionid;
   dest->sessionid = source->sessionid;
 
 
+  CLONE_BLOB(cert_blob);
   CLONE_STRING(CApath);
   CLONE_STRING(CApath);
   CLONE_STRING(CAfile);
   CLONE_STRING(CAfile);
   CLONE_STRING(clientcert);
   CLONE_STRING(clientcert);
@@ -137,6 +178,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
   Curl_safefree(sslc->cipher_list);
   Curl_safefree(sslc->cipher_list);
   Curl_safefree(sslc->cipher_list13);
   Curl_safefree(sslc->cipher_list13);
   Curl_safefree(sslc->pinned_key);
   Curl_safefree(sslc->pinned_key);
+  Curl_safefree(sslc->cert_blob);
 }
 }
 
 
 #ifdef USE_SSL
 #ifdef USE_SSL
@@ -706,7 +748,7 @@ CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num)
 }
 }
 
 
 /*
 /*
- * 'value' is NOT a zero terminated string
+ * 'value' is NOT a null-terminated string
  */
  */
 CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
 CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
                                     int certnum,
                                     int certnum,
@@ -728,10 +770,10 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
   /* sprintf the label and colon */
   /* sprintf the label and colon */
   msnprintf(output, outlen, "%s:", label);
   msnprintf(output, outlen, "%s:", label);
 
 
-  /* memcpy the value (it might not be zero terminated) */
+  /* memcpy the value (it might not be null-terminated) */
   memcpy(&output[labellen + 1], value, valuelen);
   memcpy(&output[labellen + 1], value, valuelen);
 
 
-  /* zero terminate the output */
+  /* null-terminate the output */
   output[labellen + 1 + valuelen] = 0;
   output[labellen + 1 + valuelen] = 0;
 
 
   nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
   nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);