Clean up request host properly - quark - quark web server
 (HTM) git clone git://git.suckless.org/quark
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 3ff82c514becd08922fcf9bc9f4870941650932a
 (DIR) parent c3ddb2dd14bd7a39dedbbf3520c9a2052dd3e1ff
 (HTM) Author: Laslo Hunhold <dev@frign.de>
       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 <mail@josuah.net> 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(-)
       ---
 (DIR) 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;
        }