Source-Changes-HG archive

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

[src/trunk]: src/libexec/httpd rewrite much of the SSL code:



details:   https://anonhg.NetBSD.org/src/rev/98675495ecac
branches:  trunk
changeset: 330656:98675495ecac
user:      mrg <mrg%NetBSD.org@localhost>
date:      Thu Jul 17 06:27:52 2014 +0000

description:
rewrite much of the SSL code:
- handle errors in many places they weren't properly
- make SSL_accept() an error the main code notices
- expand bozo_ssl_err() to include bozo_ssl_warn(), bozo_clear_ssl_queue()
- remove empty bozo_ssl_flush()

diffstat:

 libexec/httpd/bozohttpd.c |    5 +-
 libexec/httpd/bozohttpd.h |    6 +-
 libexec/httpd/ssl-bozo.c  |  158 ++++++++++++++++++++++++++++-----------------
 3 files changed, 104 insertions(+), 65 deletions(-)

diffs (291 lines):

diff -r 8e74edcd3b63 -r 98675495ecac libexec/httpd/bozohttpd.c
--- a/libexec/httpd/bozohttpd.c Thu Jul 17 06:24:57 2014 +0000
+++ b/libexec/httpd/bozohttpd.c Thu Jul 17 06:27:52 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bozohttpd.c,v 1.54 2014/07/08 14:06:17 mrg Exp $       */
+/*     $NetBSD: bozohttpd.c,v 1.55 2014/07/17 06:27:52 mrg Exp $       */
 
 /*     $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $      */
 
@@ -527,7 +527,8 @@
         */
        if (bozo_daemon_fork(httpd))
                return NULL;
-       bozo_ssl_accept(httpd);
+       if (bozo_ssl_accept(httpd))
+               return NULL;
 
        request = bozomalloc(httpd, sizeof(*request));
        memset(request, 0, sizeof(*request));
diff -r 8e74edcd3b63 -r 98675495ecac libexec/httpd/bozohttpd.h
--- a/libexec/httpd/bozohttpd.h Thu Jul 17 06:24:57 2014 +0000
+++ b/libexec/httpd/bozohttpd.h Thu Jul 17 06:27:52 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bozohttpd.h,v 1.32 2014/02/09 01:46:10 mrg Exp $       */
+/*     $NetBSD: bozohttpd.h,v 1.33 2014/07/17 06:27:52 mrg Exp $       */
 
 /*     $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $       */
 
@@ -235,12 +235,12 @@
 #ifdef NO_SSL_SUPPORT
 #define bozo_ssl_set_opts(w, x, y)     do { /* nothing */ } while (0)
 #define bozo_ssl_init(x)               do { /* nothing */ } while (0)
-#define bozo_ssl_accept(x)             do { /* nothing */ } while (0)
+#define bozo_ssl_accept(x)             (0)
 #define bozo_ssl_destroy(x)            do { /* nothing */ } while (0)
 #else
 void   bozo_ssl_set_opts(bozohttpd_t *, const char *, const char *);
 void   bozo_ssl_init(bozohttpd_t *);
-void   bozo_ssl_accept(bozohttpd_t *);
+int    bozo_ssl_accept(bozohttpd_t *);
 void   bozo_ssl_destroy(bozohttpd_t *);
 #endif
 
diff -r 8e74edcd3b63 -r 98675495ecac libexec/httpd/ssl-bozo.c
--- a/libexec/httpd/ssl-bozo.c  Thu Jul 17 06:24:57 2014 +0000
+++ b/libexec/httpd/ssl-bozo.c  Thu Jul 17 06:27:52 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ssl-bozo.c,v 1.17 2014/07/17 06:14:46 mrg Exp $        */
+/*     $NetBSD: ssl-bozo.c,v 1.18 2014/07/17 06:27:52 mrg Exp $        */
 
 /*     $eterna: ssl-bozo.c,v 1.15 2011/11/18 09:21:15 mrg Exp $        */
 
@@ -30,7 +30,7 @@
  *
  */
 
-/* this code implements SSL for bozohttpd */
+/* this code implements SSL and backend IO for bozohttpd */
 
 #include <stdarg.h>
 #include <stdio.h>
@@ -58,26 +58,13 @@
 } sslinfo_t;
 
 /*
- * bozo_ssl_err
- *
- * bozo_ssl_err works just like bozo_err except in addition to printing
- * the error provided by the caller at the point of error it pops and
- * prints all errors from the SSL error queue.
+ * bozo_clear_ssl_queue:  print the contents of the SSL error queue
  */
-BOZO_PRINTFLIKE(3, 4) BOZO_DEAD static void
-bozo_ssl_err(bozohttpd_t *httpd, int code, const char *fmt, ...)
+static void
+bozo_clear_ssl_queue(bozohttpd_t *httpd)
 {
-        va_list ap;
+       unsigned long sslcode = ERR_get_error();
 
-        va_start(ap, fmt);
-        if (httpd->logstderr || isatty(STDERR_FILENO)) {
-                vfprintf(stderr, fmt, ap);
-                fputs("\n", stderr);
-        } else
-                vsyslog(LOG_ERR, fmt, ap);
-        va_end(ap);
-
-       unsigned int sslcode = ERR_get_error();
        do {
                static const char sslfmt[] = "SSL Error: %s:%s:%s";
 
@@ -93,19 +80,77 @@
                            ERR_reason_error_string(sslcode));
                }
        } while (0 != (sslcode = ERR_get_error()));
+}
+
+/*
+ * bozo_ssl_warn works just like bozo_warn, plus the SSL error queue
+ */
+BOZO_PRINTFLIKE(2, 3) static void
+bozo_ssl_warn(bozohttpd_t *httpd, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       if (httpd->logstderr || isatty(STDERR_FILENO)) {
+               vfprintf(stderr, fmt, ap);
+               fputs("\n", stderr);
+       } else
+               vsyslog(LOG_ERR, fmt, ap);
+       va_end(ap);
+
+       bozo_clear_ssl_queue(httpd);
+}
+
+
+/*
+ * bozo_ssl_err works just like bozo_err, plus the SSL error queue
+ */
+BOZO_PRINTFLIKE(3, 4) BOZO_DEAD static void
+bozo_ssl_err(bozohttpd_t *httpd, int code, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       if (httpd->logstderr || isatty(STDERR_FILENO)) {
+               vfprintf(stderr, fmt, ap);
+               fputs("\n", stderr);
+       } else
+               vsyslog(LOG_ERR, fmt, ap);
+       va_end(ap);
+
+       bozo_clear_ssl_queue(httpd);
        exit(code);
 }
 
+/*
+ * bozo_check_error_queue:  print warnings if the error isn't expected
+ */
+static void
+bozo_check_error_queue(bozohttpd_t *httpd, const char *tag, int ret)
+{
+       if (ret > 0)
+               return;
+
+       const sslinfo_t *sslinfo = httpd->sslinfo;
+       const int sslerr = SSL_get_error(sslinfo->bozossl, ret);
+
+       if (sslerr != SSL_ERROR_ZERO_RETURN &&
+           sslerr != SSL_ERROR_SYSCALL &&
+           sslerr != SSL_ERROR_NONE)
+               bozo_ssl_warn(httpd, "%s: SSL_ERROR %d", tag, sslerr);
+}
+
 static BOZO_PRINTFLIKE(2, 0) int
 bozo_ssl_printf(bozohttpd_t *httpd, const char * fmt, va_list ap)
 {
-       const sslinfo_t *sslinfo = httpd->sslinfo;
-       char            *buf;
-       int              nbytes;
+       char    *buf;
+       int      nbytes;
 
-       /* XXX we need more elegant/proper handling of SSL_write return */
-       if ((nbytes = vasprintf(&buf, fmt, ap)) != -1) 
-               SSL_write(sslinfo->bozossl, buf, nbytes);
+       if ((nbytes = vasprintf(&buf, fmt, ap)) != -1)  {
+               const sslinfo_t *sslinfo = httpd->sslinfo;
+               int ret = SSL_write(sslinfo->bozossl, buf, nbytes);
+               bozo_check_error_queue(httpd, "write", ret);
+       }
 
        free(buf);
 
@@ -116,42 +161,26 @@
 bozo_ssl_read(bozohttpd_t *httpd, int fd, void *buf, size_t nbytes)
 {
        const sslinfo_t *sslinfo = httpd->sslinfo;
-       ssize_t          rbytes;
+       int     ret;
 
        USE_ARG(fd);
-       /* XXX we need elegant/proper handling of SSL_read return */
-       rbytes = (ssize_t)SSL_read(sslinfo->bozossl, buf, (int)nbytes);
-       if (rbytes < 1) {
-               if (SSL_get_error(sslinfo->bozossl, rbytes) ==
-                               SSL_ERROR_WANT_READ)
-                       bozo_warn(httpd, "SSL_ERROR_WANT_READ");
-               else
-                       bozo_warn(httpd, "SSL_ERROR OTHER");
-       }
+       ret = SSL_read(sslinfo->bozossl, buf, (int)nbytes);
+       bozo_check_error_queue(httpd, "read", ret);
 
-       return rbytes;
+       return (ssize_t)ret;
 }
 
 static ssize_t
 bozo_ssl_write(bozohttpd_t *httpd, int fd, const void *buf, size_t nbytes)
 {
        const sslinfo_t *sslinfo = httpd->sslinfo;
-       ssize_t          wbytes;
+       int     ret;
 
        USE_ARG(fd);
-       /* XXX we need elegant/proper handling of SSL_write return */
-       wbytes = (ssize_t)SSL_write(sslinfo->bozossl, buf, (int)nbytes);
-
-       return wbytes;
-}
+       ret = SSL_write(sslinfo->bozossl, buf, (int)nbytes);
+       bozo_check_error_queue(httpd, "write", ret);
 
-static int
-bozo_ssl_flush(bozohttpd_t *httpd, FILE *fp)
-{
-       USE_ARG(httpd);
-       USE_ARG(fp);
-       /* nothing to see here, move right along */
-       return 0;
+       return (ssize_t)ret;
 }
 
 void
@@ -167,7 +196,6 @@
        sslinfo->ssl_method = SSLv23_server_method();
        sslinfo->ssl_context = SSL_CTX_new(sslinfo->ssl_method);
 
-       /* XXX we need to learn how to check the SSL stack for more info */
        if (NULL == sslinfo->ssl_context)
                bozo_ssl_err(httpd, EXIT_FAILURE,
                    "SSL context creation failed");
@@ -190,17 +218,28 @@
                    "Check private key failed");
 }
 
-void
+/*
+ * returns non-zero for failure
+ */
+int
 bozo_ssl_accept(bozohttpd_t *httpd)
 {
        sslinfo_t *sslinfo = httpd->sslinfo;
 
-       if (sslinfo != NULL && sslinfo->ssl_context) {
-               sslinfo->bozossl = SSL_new(sslinfo->ssl_context);
-               SSL_set_rfd(sslinfo->bozossl, 0);
-               SSL_set_wfd(sslinfo->bozossl, 1);
-               SSL_accept(sslinfo->bozossl);
-       }
+       if (sslinfo == NULL || !sslinfo->ssl_context)
+               return 0;
+
+       sslinfo->bozossl = SSL_new(sslinfo->ssl_context);
+       if (sslinfo->bozossl == NULL)
+               bozo_err(httpd, 1, "SSL_new failed");
+
+       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);
+
+       return ret != 1;
 }
 
 void
@@ -219,9 +258,8 @@
 
        if (sslinfo == NULL) {
                sslinfo = bozomalloc(httpd, sizeof(*sslinfo));
-               if (sslinfo == NULL) {
+               if (sslinfo == NULL)
                        bozo_err(httpd, 1, "sslinfo allocation failed");
-               }
                httpd->sslinfo = sslinfo;
        }
        sslinfo->certificate_file = strdup(cert);
@@ -277,7 +315,7 @@
 {
 #ifndef NO_SSL_SUPPORT
        if (httpd->sslinfo)
-               return bozo_ssl_flush(httpd, fp);
+               return 0;
 #endif
        return fflush(fp);
 }



Home | Main Index | Thread Index | Old Index