NetBSD-Bugs archive

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

bin/50655: bozohttpd can be hung infinitely in SSL mode



>Number:         50655
>Category:       bin
>Synopsis:       bozohttpd can be hung infinitely in SSL mode
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jan 13 14:30:00 +0000 2016
>Originator:     Steffen
>Release:        current
>Organization:
>Environment:
any
>Description:
Try "telnet ADDRESS 80" that bozohttpd serves without SSL and then enter a space.  Wait a minute.  Then do the same on "443" via SSL and notice the difference.

Despite having no alarm, other tested servers simply close a connection without a HTTP timeout indication if no data was ever received.
So different to the patch etc. that shattered my nerves in private the one below doesn't do anything else but fixing the first issue and adjusting the second, too.
Thank you.
>How-To-Repeat:
See above
>Fix:

    Add an alarm to avoid "infinite" SSL accept waits..
    
    When doing
    
      ?0[sdaoden@wales tmp]$ time telnet www.XXX.eu 443
      Trying XXX.XXX.XXX.XXX...
      Connected to www.XXX.eu.
      Escape character is '^]'.
    
    and typing just a single character then no TCP timeout comes into
    play, and since no socket timeout is set and SSL_accept() doesn't
    know about timeouts the connection would stuck forever:
    
      ^C
      Connection closed by foreign host.
          9m27.94s real     0m0.01s user     0m0.02s system
    
    Therefore export a portion of the existing alarm facility and use
    it to ensure that MAX_WAIT_TIME is honoured also for the SSL
    handshake phase.
---
 bozohttpd.c | 29 ++++++++++++++++++++---------
 bozohttpd.h | 14 ++++++++++----
 ssl-bozo.c  |  8 ++++++--
 3 files changed, 36 insertions(+), 15 deletions(-)
diff --git a/bozohttpd.c b/bozohttpd.c
index 0ef800e..49b59ba 100644
--- a/bozohttpd.c
+++ b/bozohttpd.c
@@ -146,7 +146,6 @@
 #include <netdb.h>
 #include <pwd.h>
 #include <grp.h>
-#include <signal.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
@@ -165,7 +164,7 @@
 #define LOG_FTP LOG_DAEMON
 #endif
 
-volatile sig_atomic_t  alarmhit;
+volatile sig_atomic_t  bozo_alarmhit;
 
 /*
  * check there's enough space in the prefs and names arrays.
@@ -368,7 +367,7 @@ bozo_clean_request(bozo_httpreq_t *request)
 static void
 alarmer(int sig)
 {
-       alarmhit = 1;
+       bozo_alarmhit = 1;
 }
 
 /*
@@ -563,8 +562,6 @@ bozo_read_request(bozohttpd_t *httpd)
         */
        if (bozo_daemon_fork(httpd))
                return NULL;
-       if (bozo_ssl_accept(httpd))
-               return NULL;
 
        request = bozomalloc(httpd, sizeof(*request));
        memset(request, 0, sizeof(*request));
@@ -635,12 +632,26 @@ bozo_read_request(bozohttpd_t *httpd)
        sa.sa_flags = 0;
        sigaction(SIGALRM, &sa, NULL);
 
+       if (bozo_has_ssl(httpd)) {
+               alarm(MAX_WAIT_TIME);
+
+               /* Simply close connection if the SSL handshake fails */
+               if (bozo_ssl_accept(httpd)) {
+                       alarm(0);
+                       goto cleanup;
+               }
+       }
+
        alarm(MAX_WAIT_TIME);
-       while ((str = bozodgetln(httpd, STDIN_FILENO, &len, bozo_read)) != NULL) {
+
+       while ((str = bozodgetln(httpd, STDIN_FILENO, &len, bozo_read))
+                       != NULL) {
                alarm(0);
-               if (alarmhit) {
-                       (void)bozo_http_error(httpd, 408, NULL,
-                                       "request timed out");
+               if (bozo_alarmhit) {
+                       /* Don't use HTML if no data was ever seen */
+                       if (line > 0)
+                               (void)bozo_http_error(httpd, 408, NULL,
+                                               "request timed out");
                        goto cleanup;
                }
                line++;
diff --git a/bozohttpd.h b/bozohttpd.h
index 41f271f..629d4c4 100644
--- a/bozohttpd.h
+++ b/bozohttpd.h
@@ -29,17 +29,19 @@
  * SUCH DAMAGE.
  *
  */
-#ifndef BOZOHTTOPD_H_
-#define BOZOHTTOPD_H_  1
+#ifndef BOZOHTTPD_H_
+#define BOZOHTTPD_H_   1
 
 #include "netbsd_queue.h"
 
 #include <sys/stat.h>
 
+#include <signal.h>
+#include <stdio.h>
+
 #ifndef NO_LUA_SUPPORT
 #include <lua.h>
 #endif
-#include <stdio.h>
 
 /* QNX provides a lot of NetBSD things in nbutil.h */
 #ifdef HAVE_NBUTIL_H
@@ -205,6 +207,8 @@ typedef struct bozoprefs_t {
 #define DEBUG_OBESE    3
 #define DEBUG_EXPLODING        4
 
+extern volatile sig_atomic_t   bozo_alarmhit;
+
 #define        strornull(x)    ((x) ? (x) : "<null>")
 
 #if defined(__GNUC__) && __GNUC__ >= 3
@@ -247,12 +251,14 @@ char      *bozostrdup(bozohttpd_t *, bozo_httpreq_t *, const char *);
 
 /* ssl-bozo.c */
 #ifdef NO_SSL_SUPPORT
+#define bozo_has_ssl(x)                        (0)
 #define bozo_ssl_set_opts(w, x, y)     bozo_noop
 #define bozo_ssl_set_ciphers(w, x, y)  bozo_noop
 #define bozo_ssl_init(x)               bozo_noop
 #define bozo_ssl_accept(x)             (0)
 #define bozo_ssl_destroy(x)            bozo_noop
 #else
+# define bozo_has_ssl(x)               ((x)->sslinfo != NULL)
 void   bozo_ssl_set_opts(bozohttpd_t *, const char *, const char *);
 void   bozo_ssl_set_ciphers(bozohttpd_t *, const char *);
 void   bozo_ssl_init(bozohttpd_t *);
@@ -366,4 +372,4 @@ bozoheaders_t *addmerge_replheader(bozo_httpreq_t *, const char *,
 int bozo_set_pref(bozohttpd_t *, bozoprefs_t *, const char *, const char *);
 char *bozo_get_pref(bozoprefs_t *, const char *);
 
-#endif /* BOZOHTTOPD_H_ */
+#endif /* BOZOHTTPD_H_ */
diff --git a/ssl-bozo.c b/ssl-bozo.c
index 3cf8727..4297ed7 100644
--- a/ssl-bozo.c
+++ b/ssl-bozo.c
@@ -269,8 +269,12 @@ bozo_ssl_accept(bozohttpd_t *httpd)
        SSL_set_rfd(sslinfo->bozossl, 0);
        SSL_set_wfd(sslinfo->bozossl, 1);
 
-       const int ret = SSL_accept(sslinfo->bozossl);
-       bozo_check_error_queue(httpd, "accept", ret);
+       int ret = SSL_accept(sslinfo->bozossl);
+       if (bozo_alarmhit == 0) {
+               if (ret <= 0)
+                       bozo_check_error_queue(httpd, "accept", ret);
+       } else
+               ret = 0;
 
        return ret != 1;
 }



Home | Main Index | Thread Index | Old Index