Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/httpd from CHANGES:



details:   https://anonhg.NetBSD.org/src/rev/a30c7f8141b2
branches:  trunk
changeset: 446004:a30c7f8141b2
user:      mrg <mrg%NetBSD.org@localhost>
date:      Tue Nov 20 01:06:46 2018 +0000

description:
from CHANGES:

o  reduce default timeouts, and add expand timeouts to handle the
   initial line, each header, and the total time spent
o  add -T option to expose new timeout settings
o  minor RFC fixes related to timeout handling responses

old timeouts:
60 seconds for initial request like, 60 seconds per header line,
and no whole timeout (though the recent total header size changes
do introduce one that would be about 11 hours.)
new timeouts:
30 seconds for initial request like, 10 seconds per header line,
and a total request time of 600 seconds.


the new global timeout is implemented using CLOCK_MONOTONIC, with
a fallback to CLOCK_REALTIME if monotonic time is unavailable.


reject multiple Host: headers.  besides being protocol standard,
this closes one additional memory leak found by JP.  add a simple
test to check this.


clean up option and usage handling some.

diffstat:

 libexec/httpd/CHANGES            |    8 +-
 libexec/httpd/auth-bozo.c        |    4 +-
 libexec/httpd/bozohttpd.8        |   22 +++-
 libexec/httpd/bozohttpd.c        |  134 ++++++++++++++++++++++---
 libexec/httpd/bozohttpd.h        |   12 +-
 libexec/httpd/cgi-bozo.c         |    4 +-
 libexec/httpd/content-bozo.c     |    4 +-
 libexec/httpd/daemon-bozo.c      |    4 +-
 libexec/httpd/dir-index-bozo.c   |    4 +-
 libexec/httpd/main.c             |  201 ++++++++++++++++++++++++++------------
 libexec/httpd/ssl-bozo.c         |    4 +-
 libexec/httpd/testsuite/Makefile |    2 +-
 libexec/httpd/testsuite/t15.in   |    4 +
 libexec/httpd/testsuite/t15.out  |   11 ++
 libexec/httpd/tilde-luzah-bozo.c |    4 +-
 15 files changed, 316 insertions(+), 106 deletions(-)

diffs (truncated from 773 to 300 lines):

diff -r b0569cd34ade -r a30c7f8141b2 libexec/httpd/CHANGES
--- a/libexec/httpd/CHANGES     Mon Nov 19 22:21:32 2018 +0000
+++ b/libexec/httpd/CHANGES     Tue Nov 20 01:06:46 2018 +0000
@@ -1,10 +1,14 @@
-$NetBSD: CHANGES,v 1.26 2018/11/19 04:14:59 mrg Exp $
+$NetBSD: CHANGES,v 1.27 2018/11/20 01:06:46 mrg Exp $
 
 changes in bozohttpd 20181118:
        o  add url remap support via .bzremap file, from martin%netbsd.org@localhost
        o  handle redirections for any protocol, not just http:
        o  fix a denial of service attack against header contents, which
-          is now bounded at 16KiB.  reported by JP.
+          is now bounded at 16KiB.  reported by JP
+       o  reduce default timeouts, and add expand timeouts to handle the
+          initial line, each header, and the total time spent
+       o  add -T option to expose new timeout settings
+       o  minor RFC fixes related to timeout handling
 
 changes in bozohttpd 20170201:
        o  fix an infinite loop in cgi processing
diff -r b0569cd34ade -r a30c7f8141b2 libexec/httpd/auth-bozo.c
--- a/libexec/httpd/auth-bozo.c Mon Nov 19 22:21:32 2018 +0000
+++ b/libexec/httpd/auth-bozo.c Tue Nov 20 01:06:46 2018 +0000
@@ -1,9 +1,9 @@
-/*     $NetBSD: auth-bozo.c,v 1.19 2018/11/19 04:13:09 mrg Exp $       */
+/*     $NetBSD: auth-bozo.c,v 1.20 2018/11/20 01:06:46 mrg Exp $       */
 
 /*     $eterna: auth-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $       */
 
 /*
- * Copyright (c) 1997-2014 Matthew R. Green
+ * Copyright (c) 1997-2018 Matthew R. Green
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
diff -r b0569cd34ade -r a30c7f8141b2 libexec/httpd/bozohttpd.8
--- a/libexec/httpd/bozohttpd.8 Mon Nov 19 22:21:32 2018 +0000
+++ b/libexec/httpd/bozohttpd.8 Tue Nov 20 01:06:46 2018 +0000
@@ -1,8 +1,8 @@
-.\"    $NetBSD: bozohttpd.8,v 1.72 2018/11/19 04:14:59 mrg Exp $
+.\"    $NetBSD: bozohttpd.8,v 1.73 2018/11/20 01:06:46 mrg Exp $
 .\"
 .\"    $eterna: bozohttpd.8,v 1.101 2011/11/18 01:25:11 mrg Exp $
 .\"
-.\" Copyright (c) 1997-2017 Matthew R. Green
+.\" Copyright (c) 1997-2018 Matthew R. Green
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd August 24, 2018
+.Dd November 19, 2018
 .Dt BOZOHTTPD 8
 .Os
 .Sh NAME
@@ -41,6 +41,7 @@
 .Op Fl M Ar suffix type encoding encoding11
 .Op Fl P Ar pidfile
 .Op Fl S Ar server_software
+.Op Fl T Ar type timeout
 .Op Fl U Ar username
 .Op Fl Z Ar cert privkey
 .Op Fl c Ar cgibin
@@ -236,6 +237,19 @@
 .Ar server_software .
 .It Fl s
 Forces logging to be set to stderr always.
+.It Fl T Ar type timeout
+Set the timeout for
+.Ar type
+to
+.Ar timeout .
+The valid values of
+.Ar type
+are
+.Dq initial timeout ,
+.Dq header timeout ,
+and
+.Dq request timeout .
+The default values are 30 seconds, 10 seconds and 600 seconds, respectively.
 .It Fl t Ar chrootdir
 Makes
 .Nm
@@ -585,7 +599,7 @@
 and regular code audits.
 This manual documents
 .Nm
-version 20181118.
+version 20181119.
 .Sh AUTHORS
 .An -nosplit
 .Nm
diff -r b0569cd34ade -r a30c7f8141b2 libexec/httpd/bozohttpd.c
--- a/libexec/httpd/bozohttpd.c Mon Nov 19 22:21:32 2018 +0000
+++ b/libexec/httpd/bozohttpd.c Tue Nov 20 01:06:46 2018 +0000
@@ -1,9 +1,9 @@
-/*     $NetBSD: bozohttpd.c,v 1.89 2018/11/19 04:12:22 mrg Exp $       */
+/*     $NetBSD: bozohttpd.c,v 1.90 2018/11/20 01:06:46 mrg Exp $       */
 
 /*     $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $      */
 
 /*
- * Copyright (c) 1997-2017 Matthew R. Green
+ * Copyright (c) 1997-2018 Matthew R. Green
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -109,7 +109,7 @@
 #define INDEX_HTML             "index.html"
 #endif
 #ifndef SERVER_SOFTWARE
-#define SERVER_SOFTWARE                "bozohttpd/20181118"
+#define SERVER_SOFTWARE                "bozohttpd/20181119"
 #endif
 #ifndef DIRECT_ACCESS_FILE
 #define DIRECT_ACCESS_FILE     ".bzdirect"
@@ -166,8 +166,19 @@
 
 #include "bozohttpd.h"
 
-#ifndef MAX_WAIT_TIME
-#define        MAX_WAIT_TIME   60      /* hang around for 60 seconds max */
+#ifndef INITIAL_TIMEOUT
+#define        INITIAL_TIMEOUT         "30"    /* wait for 30 seconds initially */
+#endif
+#ifndef HEADER_WAIT_TIME
+#define        HEADER_WAIT_TIME        "10"    /* need more headers every 10 seconds */
+#endif
+#ifndef TOTAL_MAX_REQ_TIME
+#define        TOTAL_MAX_REQ_TIME      "600"   /* must have total request in 600 */
+#endif                                 /* seconds */
+
+/* if monotonic time is not available try real time. */
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC CLOCK_REALTIME
 #endif
 
 /* variables and functions */
@@ -175,7 +186,7 @@
 #define LOG_FTP LOG_DAEMON
 #endif
 
-volatile sig_atomic_t  alarmhit;
+volatile sig_atomic_t  timeout_hit;
 
 /*
  * check there's enough space in the prefs and names arrays.
@@ -378,7 +389,34 @@
 static void
 alarmer(int sig)
 {
-       alarmhit = 1;
+       timeout_hit = 1;
+}
+
+
+/*
+ * set a timeout for "initial", "header", or "request".
+ */
+int
+bozo_set_timeout(bozohttpd_t *httpd, bozoprefs_t *prefs,
+                const char *target, const char *time)
+{
+       const char *cur, *timeouts[] = {
+               "initial timeout",
+               "header timeout",
+               "request timeout",
+               NULL,
+       };
+       /* adjust minlen if more timeouts appear with conflicting names */
+       const size_t minlen = 1;
+       size_t len = strlen(target);
+
+       for (cur = timeouts[0]; len >= minlen && *cur; cur++) {
+               if (strncmp(target, cur, len) == 0) {
+                       bozo_set_pref(httpd, prefs, cur, time);
+                       return 0;
+               }
+       }
+       return 1;
 }
 
 /*
@@ -575,6 +613,7 @@
        int     line = 0;
        socklen_t slen;
        bozo_httpreq_t *request;
+       struct timespec ots, ts;
 
        /*
         * if we're in daemon mode, bozo_daemon_fork() will return here twice
@@ -657,10 +696,39 @@
        sa.sa_flags = 0;
        sigaction(SIGALRM, &sa, NULL);
 
-       alarm(MAX_WAIT_TIME);
+       
+       if (clock_gettime(CLOCK_MONOTONIC, &ots) != 0) {
+               (void)bozo_http_error(httpd, 500, NULL,
+                       "clock_gettime failed");
+               goto cleanup;
+       }
+
+       alarm(httpd->initial_timeout);
        while ((str = bozodgetln(httpd, STDIN_FILENO, &len, bozo_read)) != NULL) {
                alarm(0);
-               if (alarmhit) {
+
+               if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
+                       (void)bozo_http_error(httpd, 500, NULL,
+                               "clock_gettime failed");
+                       goto cleanup;
+               }
+               /*
+                * don't timeout if old tv_sec is not more than current
+                * tv_sec, or if current tv_sec is less than the request
+                * timeout (these shouldn't happen, but the first could
+                * if monotonic time is not available.)
+                *
+                * the other timeout and header size checks should ensure
+                * that even if time it set backwards or forwards a very
+                * long way, timeout will eventually happen, even if this
+                * one fails.
+                */
+               if (ts.tv_sec > ots.tv_sec &&
+                   ts.tv_sec > httpd->request_timeout &&
+                   ts.tv_sec - httpd->request_timeout > ots.tv_sec)
+                       timeout_hit = 1;
+
+               if (timeout_hit) {
                        (void)bozo_http_error(httpd, 408, NULL,
                                        "request timed out");
                        goto cleanup;
@@ -668,7 +736,6 @@
                line++;
 
                if (line == 1) {
-
                        if (len < 1) {
                                (void)bozo_http_error(httpd, 404, NULL,
                                                "null method");
@@ -744,9 +811,16 @@
                                request->hr_content_type = hdr->h_value;
                        else if (strcasecmp(hdr->h_header, "content-length") == 0)
                                request->hr_content_length = hdr->h_value;
-                       else if (strcasecmp(hdr->h_header, "host") == 0)
+                       else if (strcasecmp(hdr->h_header, "host") == 0) {
+                               if (request->hr_host) {
+                                       /* RFC 7230 (HTTP/1.1): 5.4 */
+                                       (void)bozo_http_error(httpd, 400, request,
+                                               "Only allow one Host: header");
+                                       goto cleanup;
+                               }
                                request->hr_host = bozostrdup(httpd, request,
                                                              hdr->h_value);
+                       }
                        /* RFC 2616 (HTTP/1.1): 14.20 */
                        else if (strcasecmp(hdr->h_header, "expect") == 0) {
                                (void)bozo_http_error(httpd, 417, request,
@@ -769,7 +843,7 @@
                            hdr->h_header, hdr->h_value));
                }
 next_header:
-               alarm(MAX_WAIT_TIME);
+               alarm(httpd->header_timeout);
        }
 
        /* now, clear it all out */
@@ -2146,7 +2220,7 @@
                portbuf[0] = '\0';
 
        if (request && request->hr_file) {
-               char *file = NULL, *user = NULL, *user_escaped = NULL;
+               char *file = NULL, *user = NULL;
                int file_alloc = 0;
                const char *hostname = BOZOHOST(httpd, request);
 
@@ -2159,6 +2233,8 @@
 
 #ifndef NO_USER_SUPPORT
                if (request->hr_user != NULL) {
+                       char *user_escaped;
+
                        user_escaped = bozo_escape_html(NULL, request->hr_user);
                        if (user_escaped == NULL)
                                user_escaped = request->hr_user;
@@ -2205,6 +2281,9 @@
        bozo_printf(httpd, "Server: %s\r\n", httpd->server_software);
        if (request && request->hr_allow)
                bozo_printf(httpd, "Allow: %s\r\n", request->hr_allow);
+       /* RFC 7231 (HTTP/1.1) 6.5.7 */
+       if (code == 408 && request->hr_proto == httpd->consts.http_11)
+               bozo_printf(httpd, "Connection: close\r\n");
        bozo_printf(httpd, "\r\n");
        /* According to the RFC 2616 sec. 9.4 HEAD method MUST NOT return a
         * message-body in the response */
@@ -2399,16 +2478,26 @@



Home | Main Index | Thread Index | Old Index