Clean up request host properly - quark - quark web server | |
git clone git://git.suckless.org/quark | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit 3ff82c514becd08922fcf9bc9f4870941650932a | |
parent c3ddb2dd14bd7a39dedbbf3520c9a2052dd3e1ff | |
Author: Laslo Hunhold <[email protected]> | |
Date: Tue, 3 Apr 2018 00:55:52 +0200 | |
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 <[email protected]> for his wonderful input and | |
his dedication to read the RFCs 3986 and 2732 in such great detail. | |
Diffstat: | |
M http.c | 38 +++++++++++++++++++++++++++++… | |
1 file changed, 38 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/http.c b/http.c | |
@@ -95,6 +95,7 @@ decode(char src[PATH_MAX], char dest[PATH_MAX]) | |
int | |
http_get_request(int fd, struct request *r) | |
{ | |
+ struct in6_addr res; | |
size_t hlen, i, mlen; | |
ssize_t off; | |
char h[HEADER_MAX], *p, *q; | |
@@ -232,6 +233,43 @@ http_get_request(int fd, struct request *r) | |
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; | |
} | |