Unverified Commit fa939220 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

url: reject ASCII control characters and space in host names

Host names like "127.0.0.1 moo" would otherwise be accepted by some
getaddrinfo() implementations.

Updated test 1034 and 1035 accordingly.

Fixes #2073
Closes #2092
parent 9554c3c6
Loading
Loading
Loading
Loading
+37 −12
Original line number Diff line number Diff line
@@ -1687,7 +1687,7 @@ static bool is_ASCII_name(const char *hostname)
/*
 * Perform any necessary IDN conversion of hostname
 */
static void fix_hostname(struct connectdata *conn, struct hostname *host)
static CURLcode fix_hostname(struct connectdata *conn, struct hostname *host)
{
  size_t len;
  struct Curl_easy *data = conn->data;
@@ -1727,9 +1727,11 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host)
        /* change the name pointer to point to the encoded hostname */
        host->name = host->encalloc;
      }
      else
        infof(data, "Failed to convert %s to ACE; %s\n", host->name,
      else {
        failf(data, "Failed to convert %s to ACE; %s\n", host->name,
              idn2_strerror(rc));
        return CURLE_URL_MALFORMAT;
      }
    }
#elif defined(USE_WIN32_IDN)
    char *ace_hostname = NULL;
@@ -1739,12 +1741,24 @@ static void fix_hostname(struct connectdata *conn, struct hostname *host)
      /* change the name pointer to point to the encoded hostname */
      host->name = host->encalloc;
    }
    else
      infof(data, "Failed to convert %s to ACE;\n", host->name);
    else {
      failf(data, "Failed to convert %s to ACE;\n", host->name);
      return CURLE_URL_MALFORMAT;
    }
#else
    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;
}

/*
@@ -4178,13 +4192,24 @@ static CURLcode create_conn(struct Curl_easy *data,
  /*************************************************************
   * IDN-fix the hostnames
   *************************************************************/
  fix_hostname(conn, &conn->host);
  if(conn->bits.conn_to_host)
    fix_hostname(conn, &conn->conn_to_host);
  if(conn->bits.httpproxy)
    fix_hostname(conn, &conn->http_proxy.host);
  if(conn->bits.socksproxy)
    fix_hostname(conn, &conn->socks_proxy.host);
  result = fix_hostname(conn, &conn->host);
  if(result)
    goto out;
  if(conn->bits.conn_to_host) {
    result = fix_hostname(conn, &conn->conn_to_host);
    if(result)
      goto out;
  }
  if(conn->bits.httpproxy) {
    result = fix_hostname(conn, &conn->http_proxy.host);
    if(result)
      goto out;
  }
  if(conn->bits.socksproxy) {
    result = fix_hostname(conn, &conn->socks_proxy.host);
    if(result)
      goto out;
  }

  /*************************************************************
   * Check whether the host and the "connect to host" are equal.
+5 −20
Original line number Diff line number Diff line
@@ -13,24 +13,17 @@ config file
#
# Server-side
<reply>
<data>
HTTP/1.0 503 Service Unavailable
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake swsclose
Content-Type: text/html
Funny-head: yesyes

</data>
</reply>

#
# Client-side
<client>
<server>
http
none
</server>
<features>
idn
http
</features>
<setenv>
LC_ALL=
@@ -54,17 +47,9 @@ url = "http://invalid-utf8-
</client>

#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET http://invalid-utf8-.local/page/1034 HTTP/1.1
Host: invalid-utf8-.local
Accept: */*
Proxy-Connection: Keep-Alive

</protocol>
<errorcode>
3
</errorcode>
</verify>
</testcase>
+5 −16
Original line number Diff line number Diff line
@@ -12,24 +12,17 @@ FAILURE
#
# Server-side
<reply>
<data>
HTTP/1.0 503 Service Unavailable
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake swsclose
Content-Type: text/html
Funny-head: yesyes

</data>
</reply>

#
# Client-side
<client>
<server>
http
none
</server>
<features>
idn
http
</features>
<setenv>
LC_ALL=
@@ -52,12 +45,8 @@ http://too-long-IDN-name-cürl-rüles-la-la-la-dee-da-flooby-nooby.local/page/10
<strip>
^User-Agent:.*
</strip>
<protocol>
GET http://too-long-IDN-name-cürl-rüles-la-la-la-dee-da-flooby-nooby.local/page/1035 HTTP/1.1
Host: too-long-IDN-name-cürl-rüles-la-la-la-dee-da-flooby-nooby.local
Accept: */*
Proxy-Connection: Keep-Alive

</protocol>
<errorcode>
3
</errorcode>
</verify>
</testcase>