improve libtls return code handling, check header for truncation - hurl - Gopher/HTTP/HTTPS file grabber
 (HTM) git clone git://git.codemadness.org/hurl
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit e0b2498d20b2082339ac02a098b40a11bdbe3ab7
 (DIR) parent ea0fa924213696c5be26a10a20044c23ed83de9e
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Mon, 18 May 2020 19:15:04 +0200
       
       improve libtls return code handling, check header for truncation
       
       Diffstat:
         M hurl.c                              |      40 ++++++++++++++++++++++---------
       
       1 file changed, 29 insertions(+), 11 deletions(-)
       ---
 (DIR) diff --git a/hurl.c b/hurl.c
       @@ -209,7 +209,7 @@ https_request(void)
                stdport = u.port[0] == '\0' || strcmp(u.port, "443") == 0;
        
                /* create and send HTTP header */
       -        snprintf(buf, sizeof(buf),
       +        r = snprintf(buf, sizeof(buf),
                        "GET %s HTTP/1.0\r\n"
                        "Host: %s%s%s\r\n"
                        "Connection: close\r\n"
       @@ -218,22 +218,36 @@ https_request(void)
                        stdport ? "" : ":",
                        stdport ? "" : u.port,
                        config_headers, config_headers[0] ? "\r\n" : "");
       -        if ((r = tls_write(t, buf, strlen(buf))) < 0) {
       -                fprintf(stderr, "tls_write: %s\n", tls_error(t));
       -                goto err;
       +        if (r < 0 || (size_t)r >= sizeof(buf))
       +                errx(1, "not writing header because it is truncated");
       +
       +        for (len = r, p = buf; len > 0; ) {
       +                r = tls_write(t, p, len);
       +                if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) {
       +                        continue;
       +                } else if (r == -1) {
       +                        fprintf(stderr, "tls_write: %s\n", tls_error(t));
       +                        goto err;
       +                }
       +                p += r;
       +                len -= r;
                }
        
                /* NOTE: HTTP header must fit in the buffer */
       -        for (len = 0; len < sizeof(buf); len += r) {
       +        for (len = 0; len < sizeof(buf);) {
                        /* NOTE: buffer size is -1 to NUL terminate the buffer for a
                                 string comparison. */
       -                if ((r = tls_read(t, &buf[len], sizeof(buf) - len - 1)) == 0)
       +                r = tls_read(t, &buf[len], sizeof(buf) - len - 1);
       +                if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) {
       +                        continue;
       +                } else if (r == 0) {
                                break;
       -                if (r < 0) {
       +                } else if (r == -1) {
                                errstr = tls_error(t);
                                fprintf(stderr, "tls_read: %s\n", errstr ? errstr : "");
                                goto err;
                        }
       +                len += r;
                }
                buf[len] = '\0';
        
       @@ -264,9 +278,11 @@ https_request(void)
        
                while (1) {
                        r = tls_read(t, &buf, sizeof(buf));
       -                if (r == 0)
       +                if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) {
       +                        continue;
       +                } else if (r == 0) {
                                break;
       -                if (r < 0) {
       +                } else if (r == -1) {
                                errstr = tls_error(t);
                                fprintf(stderr, "tls_read: %s\n", errstr ? errstr : "");
                                goto err;
       @@ -319,7 +335,7 @@ http_request(void)
                stdport = u.port[0] == '\0' || strcmp(u.port, "80") == 0;
        
                /* create and send HTTP header */
       -        snprintf(buf, sizeof(buf),
       +        r = snprintf(buf, sizeof(buf),
                        "GET %s HTTP/1.0\r\n"
                        "Host: %s%s%s\r\n"
                        "Connection: close\r\n"
       @@ -328,7 +344,9 @@ http_request(void)
                        stdport ? "" : ":",
                        stdport ? "" : u.port,
                        config_headers, config_headers[0] ? "\r\n" : "");
       -        if ((r = write(fd, buf, strlen(buf))) == -1) {
       +        if (r < 0 || (size_t)r >= sizeof(buf))
       +                errx(1, "not writing header because it is truncated");
       +        if ((r = write(fd, buf, r)) == -1) {
                        fprintf(stderr, "write: %s\n", strerror(errno));
                        goto err;
                }