r308996 broke IP literals by assuming that a colon could only occur as
a separator between host and port, and using strchr() to search for it. Rewrite fetch_resolve() so it handles bracketed literals correctly, and remove similar code elsewhere to avoid passing unbracketed literals to fetch_resolve(). Remove #ifdef INET6 so we still parse IP literals correctly even if we do not have the ability to connect to them. While there, fix an off-by-one error which caused HTTP 400 errors to be misinterpreted as redirects. PR: 217723 MFC after: 1 week Reported by: bapt, bz, cem, ngie
This commit is contained in:
parent
ff17a6773e
commit
08a49957b3
@ -248,37 +248,51 @@ fetch_resolve(const char *addr, int port, int af)
|
||||
{
|
||||
char hbuf[256], sbuf[8];
|
||||
struct addrinfo hints, *res;
|
||||
const char *sep, *host, *service;
|
||||
const char *hb, *he, *sep;
|
||||
const char *host, *service;
|
||||
int err, len;
|
||||
|
||||
/* split address if necessary */
|
||||
err = EAI_SYSTEM;
|
||||
if ((sep = strchr(addr, ':')) != NULL) {
|
||||
/* first, check for a bracketed IPv6 address */
|
||||
if (*addr == '[') {
|
||||
hb = addr + 1;
|
||||
if ((sep = strchr(hb, ']')) == NULL) {
|
||||
errno = EINVAL;
|
||||
goto syserr;
|
||||
}
|
||||
he = sep++;
|
||||
} else {
|
||||
hb = addr;
|
||||
sep = strchrnul(hb, ':');
|
||||
he = sep;
|
||||
}
|
||||
|
||||
/* see if we need to copy the host name */
|
||||
if (*he != '\0') {
|
||||
len = snprintf(hbuf, sizeof(hbuf),
|
||||
"%.*s", (int)(sep - addr), addr);
|
||||
"%.*s", (int)(he - hb), hb);
|
||||
if (len < 0)
|
||||
return (NULL);
|
||||
goto syserr;
|
||||
if (len >= (int)sizeof(hbuf)) {
|
||||
errno = ENAMETOOLONG;
|
||||
fetch_syserr();
|
||||
return (NULL);
|
||||
goto syserr;
|
||||
}
|
||||
host = hbuf;
|
||||
service = sep + 1;
|
||||
} else if (port != 0) {
|
||||
} else {
|
||||
host = hb;
|
||||
}
|
||||
|
||||
/* was it followed by a service name? */
|
||||
if (*sep == '\0' && port != 0) {
|
||||
if (port < 1 || port > 65535) {
|
||||
errno = EINVAL;
|
||||
fetch_syserr();
|
||||
return (NULL);
|
||||
goto syserr;
|
||||
}
|
||||
if (snprintf(sbuf, sizeof(sbuf), "%d", port) < 0) {
|
||||
fetch_syserr();
|
||||
return (NULL);
|
||||
}
|
||||
host = addr;
|
||||
if (snprintf(sbuf, sizeof(sbuf), "%d", port) < 0)
|
||||
goto syserr;
|
||||
service = sbuf;
|
||||
} else if (*sep != '\0') {
|
||||
service = sep;
|
||||
} else {
|
||||
host = addr;
|
||||
service = NULL;
|
||||
}
|
||||
|
||||
@ -292,6 +306,9 @@ fetch_resolve(const char *addr, int port, int af)
|
||||
return (NULL);
|
||||
}
|
||||
return (res);
|
||||
syserr:
|
||||
fetch_syserr();
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -386,18 +386,17 @@ fetchParseURL(const char *URL)
|
||||
}
|
||||
|
||||
/* hostname */
|
||||
#ifdef INET6
|
||||
if (*p == '[' && (q = strchr(p + 1, ']')) != NULL &&
|
||||
(*++q == '\0' || *q == '/' || *q == ':')) {
|
||||
if ((i = q - p - 2) > MAXHOSTNAMELEN)
|
||||
if ((i = q - p) > MAXHOSTNAMELEN)
|
||||
i = MAXHOSTNAMELEN;
|
||||
strncpy(u->host, ++p, i);
|
||||
strncpy(u->host, p, i);
|
||||
p = q;
|
||||
} else
|
||||
#endif
|
||||
} else {
|
||||
for (i = 0; *p && (*p != '/') && (*p != ':'); p++)
|
||||
if (i < MAXHOSTNAMELEN)
|
||||
u->host[i++] = *p;
|
||||
}
|
||||
|
||||
/* port */
|
||||
if (*p == ':') {
|
||||
@ -444,12 +443,12 @@ fetchParseURL(const char *URL)
|
||||
}
|
||||
|
||||
DEBUG(fprintf(stderr,
|
||||
"scheme: [%s]\n"
|
||||
"user: [%s]\n"
|
||||
"password: [%s]\n"
|
||||
"host: [%s]\n"
|
||||
"port: [%d]\n"
|
||||
"document: [%s]\n",
|
||||
"scheme: \"%s\"\n"
|
||||
"user: \"%s\"\n"
|
||||
"password: \"%s\"\n"
|
||||
"host: \"%s\"\n"
|
||||
"port: \"%d\"\n"
|
||||
"document: \"%s\"\n",
|
||||
u->scheme, u->user, u->pwd,
|
||||
u->host, u->port, u->doc));
|
||||
|
||||
|
@ -118,7 +118,7 @@ __FBSDID("$FreeBSD$");
|
||||
|| (xyz) == HTTP_USE_PROXY \
|
||||
|| (xyz) == HTTP_SEE_OTHER)
|
||||
|
||||
#define HTTP_ERROR(xyz) ((xyz) > 400 && (xyz) < 599)
|
||||
#define HTTP_ERROR(xyz) ((xyz) >= 400 && (xyz) <= 599)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
@ -1604,20 +1604,11 @@ http_request_body(struct url *URL, const char *op, struct url_stat *us,
|
||||
if ((conn = http_connect(url, purl, flags)) == NULL)
|
||||
goto ouch;
|
||||
|
||||
/* append port number only if necessary */
|
||||
host = url->host;
|
||||
#ifdef INET6
|
||||
if (strchr(url->host, ':')) {
|
||||
snprintf(hbuf, sizeof(hbuf), "[%s]", url->host);
|
||||
host = hbuf;
|
||||
}
|
||||
#endif
|
||||
if (url->port != fetch_default_port(url->scheme)) {
|
||||
if (host != hbuf) {
|
||||
strcpy(hbuf, host);
|
||||
host = hbuf;
|
||||
}
|
||||
snprintf(hbuf + strlen(hbuf),
|
||||
sizeof(hbuf) - strlen(hbuf), ":%d", url->port);
|
||||
snprintf(hbuf, sizeof(hbuf), "%s:%d", host, url->port);
|
||||
host = hbuf;
|
||||
}
|
||||
|
||||
/* send request */
|
||||
|
Loading…
Reference in New Issue
Block a user