Clean up request host properly
We all agree that the IPv6 address format is a big clusterfuck and only an insane person would've come up with it given the double colons interfere with the way one actually appends a port to a normal IPv4 address. To counteract in this issue, the RFC specifies that one should enclose IPv6-addresses in square brackets to make the disctinction possible, i.e. host: ::1 port: 80 --> [::1]:80 The host field can contain both a port suffix and, of course by the RFC, have the address enclosed in square brackets. Given I personally see this as a "transport enclosure" I'd rather like to see it gone as soon as possible and thus implement this cleanup in the http-header-parser so the output is nice and clean and we don't have to deal with this garbage later on. Thanks to Josuah Demangeon <mail@josuah.net> for his wonderful input and his dedication to read the RFCs 3986 and 2732 in such great detail.
This commit is contained in:
parent
c3ddb2dd14
commit
3ff82c514b
1 changed files with 38 additions and 0 deletions
38
http.c
38
http.c
|
@ -95,6 +95,7 @@ decode(char src[PATH_MAX], char dest[PATH_MAX])
|
||||||
int
|
int
|
||||||
http_get_request(int fd, struct request *r)
|
http_get_request(int fd, struct request *r)
|
||||||
{
|
{
|
||||||
|
struct in6_addr res;
|
||||||
size_t hlen, i, mlen;
|
size_t hlen, i, mlen;
|
||||||
ssize_t off;
|
ssize_t off;
|
||||||
char h[HEADER_MAX], *p, *q;
|
char h[HEADER_MAX], *p, *q;
|
||||||
|
@ -232,6 +233,43 @@ http_get_request(int fd, struct request *r)
|
||||||
p = q + (sizeof("\r\n") - 1);
|
p = q + (sizeof("\r\n") - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* clean up host
|
||||||
|
*/
|
||||||
|
|
||||||
|
p = strrchr(r->field[REQ_HOST], ':');
|
||||||
|
q = strrchr(r->field[REQ_HOST], ']');
|
||||||
|
|
||||||
|
/* strip port suffix but don't interfere with IPv6 bracket notation
|
||||||
|
* as per RFC 2732 */
|
||||||
|
if (p && (!q || p > q)) {
|
||||||
|
/* port suffix must not be empty */
|
||||||
|
if (*(p + 1) == '\0') {
|
||||||
|
return http_send_status(fd, S_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* strip the brackets from the IPv6 notation and validate the address */
|
||||||
|
if (q) {
|
||||||
|
/* brackets must be on the outside */
|
||||||
|
if (r->field[REQ_HOST][0] != '[' || *(q + 1) != '\0') {
|
||||||
|
return http_send_status(fd, S_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove the right bracket */
|
||||||
|
*q = '\0';
|
||||||
|
p = r->field[REQ_HOST] + 1;
|
||||||
|
|
||||||
|
/* validate the contained IPv6 address */
|
||||||
|
if (inet_pton(AF_INET6, p, &res) != 1) {
|
||||||
|
return http_send_status(fd, S_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy it into the host field */
|
||||||
|
memmove(r->field[REQ_HOST], p, q - p + 1);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue