]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
urlapi: guess scheme correct even with credentials given
authorDaniel Stenberg <daniel@haxx.se>
Mon, 27 Jan 2020 16:28:40 +0000 (17:28 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 28 Jan 2020 07:40:16 +0000 (08:40 +0100)
In the "scheme-less" parsing case, we need to strip off credentials
first before we guess scheme based on the host name!

Assisted-by: Jay Satiro
Fixes #4856
Closes #4857

lib/urlapi.c
tests/libtest/lib1560.c

index fa514bce53224ca715ec2b303ba297a1a1c083f6..506e244dc4fb4015e59144261f89b8ecc18775ed 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -428,7 +428,6 @@ static char *concat_url(const char *base, const char *relurl)
  *
  */
 static CURLUcode parse_hostname_login(struct Curl_URL *u,
-                                      const struct Curl_handler *h,
                                       char **hostname,
                                       unsigned int flags)
 {
@@ -437,6 +436,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
   char *userp = NULL;
   char *passwdp = NULL;
   char *optionsp = NULL;
+  const struct Curl_handler *h = NULL;
 
   /* At this point, we're hoping all the other special cases have
    * been taken care of, so conn->host.name is at most
@@ -456,6 +456,10 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
    * ftp://user:password@ftp.my.site:8021/README */
   *hostname = ++ptr;
 
+  /* if this is a known scheme, get some details */
+  if(u->scheme)
+    h = Curl_builtin_scheme(u->scheme);
+
   /* We could use the login information in the URL so extract it. Only parse
      options if the handler says we should. Note that 'h' might be NULL! */
   ccode = Curl_parse_login_details(login, ptr - login - 1,
@@ -571,7 +575,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname)
 }
 
 /* scan for byte values < 31 or 127 */
-static CURLUcode junkscan(char *part)
+static CURLUcode junkscan(const char *part)
 {
   if(part) {
     static const char badbytes[]={
@@ -668,10 +672,9 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
   CURLUcode result;
   bool url_has_scheme = FALSE;
   char schemebuf[MAX_SCHEME_LEN + 1];
-  char *schemep = NULL;
+  const char *schemep = NULL;
   size_t schemelen = 0;
   size_t urllen;
-  const struct Curl_handler *h = NULL;
 
   if(!url)
     return CURLUE_MALFORMED_INPUT;
@@ -798,7 +801,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
       if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME)))
         return CURLUE_MALFORMED_INPUT;
       if(flags & CURLU_DEFAULT_SCHEME)
-        schemep = (char *) DEFAULT_SCHEME;
+        schemep = DEFAULT_SCHEME;
 
       /*
        * The URL was badly formatted, let's try without scheme specified.
@@ -820,36 +823,17 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
         return CURLUE_MALFORMED_INPUT;
     }
 
-    if((flags & CURLU_GUESS_SCHEME) && !schemep) {
-      /* legacy curl-style guess based on host name */
-      if(checkprefix("ftp.", hostname))
-        schemep = (char *)"ftp";
-      else if(checkprefix("dict.", hostname))
-        schemep = (char *)"dict";
-      else if(checkprefix("ldap.", hostname))
-        schemep = (char *)"ldap";
-      else if(checkprefix("imap.", hostname))
-        schemep = (char *)"imap";
-      else if(checkprefix("smtp.", hostname))
-        schemep = (char *)"smtp";
-      else if(checkprefix("pop3.", hostname))
-        schemep = (char *)"pop3";
-      else
-        schemep = (char *)"http";
-    }
-
     len = strlen(p);
     memcpy(path, p, len);
     path[len] = 0;
 
-    u->scheme = strdup(schemep);
-    if(!u->scheme)
-      return CURLUE_OUT_OF_MEMORY;
+    if(schemep) {
+      u->scheme = strdup(schemep);
+      if(!u->scheme)
+        return CURLUE_OUT_OF_MEMORY;
+    }
   }
 
-  /* if this is a known scheme, get some details */
-  h = Curl_builtin_scheme(u->scheme);
-
   if(junkscan(path))
     return CURLUE_MALFORMED_INPUT;
 
@@ -916,7 +900,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
     if(junkscan(hostname))
       return CURLUE_MALFORMED_INPUT;
 
-    result = parse_hostname_login(u, h, &hostname, flags);
+    result = parse_hostname_login(u, &hostname, flags);
     if(result)
       return result;
 
@@ -936,6 +920,28 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags)
     u->host = strdup(hostname);
     if(!u->host)
       return CURLUE_OUT_OF_MEMORY;
+
+    if((flags & CURLU_GUESS_SCHEME) && !schemep) {
+      /* legacy curl-style guess based on host name */
+      if(checkprefix("ftp.", hostname))
+        schemep = "ftp";
+      else if(checkprefix("dict.", hostname))
+        schemep = "dict";
+      else if(checkprefix("ldap.", hostname))
+        schemep = "ldap";
+      else if(checkprefix("imap.", hostname))
+        schemep = "imap";
+      else if(checkprefix("smtp.", hostname))
+        schemep = "smtp";
+      else if(checkprefix("pop3.", hostname))
+        schemep = "pop3";
+      else
+        schemep = "http";
+
+      u->scheme = strdup(schemep);
+      if(!u->scheme)
+        return CURLUE_OUT_OF_MEMORY;
+    }
   }
 
   Curl_safefree(u->scratch);
index 7f8accc7dc6a36ada08cb3c07364c694568ed9bd..6228a137b1162a808115c8444e27b3fc1f381203 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -129,6 +129,14 @@ struct querycase {
 };
 
 static struct testcase get_parts_list[] ={
+  {"user:moo@ftp.example.com/color/#green?no-black",
+   "ftp | user | moo | [13] | ftp.example.com | [15] | /color/ | [16] | "
+   "green?no-black",
+   CURLU_GUESS_SCHEME, 0, CURLUE_OK },
+  {"ftp.user:moo@example.com/color/#green?no-black",
+   "http | ftp.user | moo | [13] | example.com | [15] | /color/ | [16] | "
+   "green?no-black",
+   CURLU_GUESS_SCHEME, 0, CURLUE_OK },
 #ifdef WIN32
   {"file:/C:\\programs\\foo",
    "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",