[backfire] merge all uhttpd changes from trunk
authorJo-Philipp Wich <jow@openwrt.org>
Sun, 6 Nov 2011 21:17:42 +0000 (21:17 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Sun, 6 Nov 2011 21:17:42 +0000 (21:17 +0000)
SVN-Revision: 28790

package/uhttpd/Makefile
package/uhttpd/files/uhttpd.init
package/uhttpd/src/Makefile
package/uhttpd/src/uhttpd-tls.c
package/uhttpd/src/uhttpd-tls.h
package/uhttpd/src/uhttpd-utils.c
package/uhttpd/src/uhttpd-utils.h
package/uhttpd/src/uhttpd.c
package/uhttpd/src/uhttpd.h

index a43b1014f8c9d10cbc6e4d0a3a8b346073857c54..14b1559c31b686f26bbbfe9f4d23ffd045824d05 100644 (file)
@@ -8,17 +8,23 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=uhttpd
-PKG_RELEASE:=23.3
+PKG_RELEASE:=28
 
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
-PKG_BUILD_DEPENDS := libcyassl liblua
+PKG_CONFIG_DEPENDS := \
+       CONFIG_PACKAGE_uhttpd-mod-lua \
+       CONFIG_PACKAGE_uhttpd-mod-tls \
+       CONFIG_PACKAGE_uhttpd-mod-tls_cyassl \
+       CONFIG_PACKAGE_uhttpd-mod-tls_openssl
 
 include $(INCLUDE_DIR)/package.mk
 
 define Package/uhttpd/default
   SECTION:=net
   CATEGORY:=Network
+  SUBMENU:=Web Servers/Proxies
   TITLE:=uHTTPd - tiny, single threaded HTTP server
+  MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
 endef
 
 define Package/uhttpd
@@ -36,13 +42,43 @@ endef
 define Package/uhttpd-mod-tls
   $(Package/uhttpd/default)
   TITLE+= (TLS plugin)
-  DEPENDS:=uhttpd +libcyassl
+  DEPENDS:=uhttpd +PACKAGE_uhttpd-mod-tls_cyassl:libcyassl +PACKAGE_uhttpd-mod-tls_openssl:libopenssl
 endef
 
 define Package/uhttpd-mod-tls/description
  The TLS plugin adds HTTPS support to uHTTPd.
 endef
 
+define Package/uhttpd-mod-tls/config
+        choice
+                depends on PACKAGE_uhttpd-mod-tls
+                prompt "TLS Provider"
+                default PACKAGE_uhttpd-mod-tls_cyassl
+
+                config PACKAGE_uhttpd-mod-tls_cyassl
+                        bool "CyaSSL"
+
+                config PACKAGE_uhttpd-mod-tls_openssl
+                        bool "OpenSSL"
+        endchoice
+endef
+
+UHTTPD_TLS:=
+TLS_CFLAGS:=
+TLS_LDFLAGS:=
+
+ifneq ($(CONFIG_PACKAGE_uhttpd-mod-tls_cyassl),)
+  UHTTPD_TLS:=cyassl
+  TLS_CFLAGS:=-I$(STAGING_DIR)/usr/include/cyassl -DTLS_IS_CYASSL
+  TLS_LDFLAGS:=-lcyassl -lm
+endif
+
+ifneq ($(CONFIG_PACKAGE_uhttpd-mod-tls_openssl),)
+  UHTTPD_TLS:=openssl
+  TLS_CFLAGS:=-DTLS_IS_OPENSSL
+  TLS_LDFLAGS:=-lssl
+endif
+
 
 define Package/uhttpd-mod-lua
   $(Package/uhttpd/default)
@@ -55,10 +91,15 @@ define Package/uhttpd-mod-lua/description
 endef
 
 
-# hack to use CyASSL headers
-TARGET_CFLAGS += -I$(firstword $(wildcard $(BUILD_DIR)/cyassl-*/include))
-TARGET_LDFLAGS += -lm
-MAKE_VARS += FPIC="$(FPIC)"
+TARGET_CFLAGS += $(TLS_CFLAGS)
+TARGET_LDFLAGS += $(TLS_LDFLAGS)
+MAKE_VARS += \
+       FPIC="$(FPIC)" \
+       LUA_SUPPORT="$(if $(CONFIG_PACKAGE_uhttpd-mod-lua),1)" \
+       TLS_SUPPORT="$(if $(CONFIG_PACKAGE_uhttpd-mod-tls),1)" \
+       UHTTPD_TLS="$(UHTTPD_TLS)" \
+       TLS_CFLAGS="$(TLS_CFLAGS)" \
+       TLS_LDFLAGS="$(TLS_LDFLAGS)"
 
 define Build/Prepare
        mkdir -p $(PKG_BUILD_DIR)
index 069e16fff1ca769028d98764e615294230a2ade9..1ec009663b5f5f0217292f51d1d8929545c66a7d 100755 (executable)
@@ -44,7 +44,7 @@ generate_keys() {
        [ -x "$PX5G_BIN" ] && {
                $PX5G_BIN selfsigned -der \
                        -days ${days:-730} -newkey rsa:${bits:-1024} -keyout "$UHTTPD_KEY" -out "$UHTTPD_CERT" \
-                       -subj /C=${country:-DE}/ST=${state:-Saxony}/L=${location:-Leipzig}/CN=${commonname:-OpenWrt}
+                       -subj /C="${country:-DE}"/ST="${state:-Saxony}"/L="${location:-Leipzig}"/CN="${commonname:-OpenWrt}"
        }
 }
 
index 06d61bdef3b3e7b9d64aa2edb764c8d815ffa247..5e98ab8750ac49d28b55cac24b181a64e443c095 100644 (file)
@@ -1,29 +1,55 @@
 CGI_SUPPORT ?= 1
 LUA_SUPPORT ?= 1
 TLS_SUPPORT ?= 1
+UHTTPD_TLS ?= cyassl
 
-CFLAGS ?= -I./lua-5.1.4/src -I./cyassl-1.4.0/include -O0 -ggdb3
-LDFLAGS ?= -L./lua-5.1.4/src -L./cyassl-1.4.0/src/.libs
+CFLAGS ?= -I./lua-5.1.4/src $(TLS_CFLAGS) -O0 -ggdb3
+LDFLAGS ?= -L./lua-5.1.4/src
 
 CFLAGS += -Wall --std=gnu99
 
-OBJ = uhttpd.o uhttpd-file.o uhttpd-utils.o
-LIB = -Wl,--export-dynamic -lcrypt -ldl
+ifeq ($(UHTTPD_TLS),openssl)
+  TLS_LDFLAGS ?= -L./openssl-0.9.8m -lssl
+  TLS_CFLAGS ?= -I./openssl-0.9.8m/include -DTLS_IS_OPENSSL
+else
+  TLS_LDFLAGS ?= -L./cyassl-1.4.0/src/.libs -lcyassl
+  TLS_CFLAGS ?= -I./cyassl-1.4.0/include -DTLS_IS_CYASSL
+endif
 
-TLSLIB =
-LUALIB =
+OBJ := uhttpd.o uhttpd-file.o uhttpd-utils.o
+LIB := -Wl,--export-dynamic -lcrypt -ldl
 
+TLSLIB :=
+LUALIB :=
 
-world: compile
+HAVE_SHADOW=$(shell echo 'int main(void){ return !getspnam("root"); }' | \
+       $(CC) -include shadow.h -xc -o/dev/null - 2>/dev/null && echo yes)
+
+ifeq ($(HAVE_SHADOW),yes)
+  CFLAGS += -DHAVE_SHADOW
+endif
+
+ifeq ($(TLS_SUPPORT),1)
+  CFLAGS += -DHAVE_TLS
+endif
 
 ifeq ($(CGI_SUPPORT),1)
-  OBJ += uhttpd-cgi.o
   CFLAGS += -DHAVE_CGI
 endif
 
 ifeq ($(LUA_SUPPORT),1)
   CFLAGS += -DHAVE_LUA
-  LUALIB = uhttpd_lua.so
+endif
+
+
+world: compile
+
+ifeq ($(CGI_SUPPORT),1)
+  OBJ += uhttpd-cgi.o
+endif
+
+ifeq ($(LUA_SUPPORT),1)
+  LUALIB := uhttpd_lua.so
 
   $(LUALIB): uhttpd-lua.c
                $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \
@@ -32,12 +58,11 @@ ifeq ($(LUA_SUPPORT),1)
 endif
 
 ifeq ($(TLS_SUPPORT),1)
-  CFLAGS += -DHAVE_TLS
-  TLSLIB = uhttpd_tls.so
+  TLSLIB := uhttpd_tls.so
 
   $(TLSLIB): uhttpd-tls.c
                $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \
-                       -shared -lcyassl \
+                       -shared $(TLS_LDFLAGS) \
                        -o $(TLSLIB) uhttpd-tls.c
 endif
 
@@ -49,4 +74,3 @@ compile: $(OBJ) $(TLSLIB) $(LUALIB)
 
 clean:
        rm -f *.o *.so uhttpd
-
index 008f8e0df6a7e873a96ec0a3182cad60243155a5..4a9e907922cab2b6460f883efeeb15643adf7be8 100644 (file)
 #include "uhttpd-tls.h"
 #include "uhttpd-utils.h"
 
+#include <syslog.h>
+#define dbg(...) syslog(LOG_INFO, __VA_ARGS__)
+
+#ifdef TLS_IS_CYASSL
+static int uh_cyassl_recv_cb(char *buf, int sz, void *ctx)
+{
+       int rv;
+       int socket = *(int *)ctx;
+       struct client *cl;
+
+       if (!(cl = uh_client_lookup(socket)))
+               return -1; /* unexpected error */
+
+       rv = uh_tcp_recv_lowlevel(cl, buf, sz);
+
+       if (rv < 0)
+               return -4; /* interrupted */
+
+       if (rv == 0)
+               return -5; /* connection closed */
+
+       return rv;
+}
+
+static int uh_cyassl_send_cb(char *buf, int sz, void *ctx)
+{
+       int rv;
+       int socket = *(int *)ctx;
+       struct client *cl;
+
+       if (!(cl = uh_client_lookup(socket)))
+               return -1; /* unexpected error */
+
+       rv = uh_tcp_send_lowlevel(cl, buf, sz);
+
+       if (rv <= 0)
+               return -5; /* connection dead */
+
+       return rv;
+}
+
+void SetCallbackIORecv_Ctx(SSL_CTX*, int (*)(char *, int, void *));
+void SetCallbackIOSend_Ctx(SSL_CTX*, int (*)(char *, int, void *));
+
+static void uh_tls_ctx_setup(SSL_CTX *ctx)
+{
+       SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
+       SetCallbackIORecv_Ctx(ctx, uh_cyassl_recv_cb);
+       SetCallbackIOSend_Ctx(ctx, uh_cyassl_send_cb);
+       return;
+}
+
+static int uh_tls_client_ctx_setup(SSL *ssl, int socket)
+{
+       return SSL_set_fd(ssl, socket);
+}
+#endif /* TLS_IS_CYASSL */
+
+#ifdef TLS_IS_OPENSSL
+static long uh_openssl_bio_ctrl_cb(BIO *b, int cmd, long num, void *ptr)
+{
+       long rv = 1;
+
+       switch (cmd)
+       {
+               case BIO_C_SET_FD:
+                       b->num      = *((int *)ptr);
+                       b->shutdown = (int)num;
+                       b->init     = 1;
+                       break;
+
+               case BIO_C_GET_FD:
+                       if (!b->init)
+                               return -1;
+
+                       if (ptr)
+                               *((int *)ptr) = b->num;
+
+                       rv = b->num;
+                       break;
+       }
+
+       return rv;
+}
+
+static int uh_openssl_bio_read_cb(BIO *b, char *out, int outl)
+{
+       int rv = 0;
+       struct client *cl;
+
+       if (!(cl = uh_client_lookup(b->num)))
+               return -1;
+
+       if (out != NULL)
+               rv = uh_tcp_recv_lowlevel(cl, out, outl);
+
+       return rv;
+}
+
+static int uh_openssl_bio_write_cb(BIO *b, const char *in, int inl)
+{
+       struct client *cl;
+
+       if (!(cl = uh_client_lookup(b->num)))
+               return -1;
+
+       return uh_tcp_send_lowlevel(cl, in, inl);
+}
+
+static BIO_METHOD uh_openssl_bio_methods = {
+       .type   = BIO_TYPE_SOCKET,
+       .name   = "uhsocket",
+       .ctrl   = uh_openssl_bio_ctrl_cb,
+       .bwrite = uh_openssl_bio_write_cb,
+       .bread  = uh_openssl_bio_read_cb
+};
+
+static void uh_tls_ctx_setup(SSL_CTX *ctx)
+{
+       SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
+       return;
+}
+
+static int uh_tls_client_ctx_setup(SSL *ssl, int socket)
+{
+       BIO *b;
+
+       if (!(b = BIO_new(&uh_openssl_bio_methods)))
+               return 0;
+
+       BIO_set_fd(b, socket, BIO_NOCLOSE);
+       SSL_set_bio(ssl, b, b);
+
+       return 1;
+}
+#endif /* TLS_IS_OPENSSL */
+
 
 SSL_CTX * uh_tls_ctx_init()
 {
-       SSL_CTX *c = NULL;
+       SSL_CTX *c;
+
        SSL_load_error_strings();
        SSL_library_init();
 
-       if( (c = SSL_CTX_new(TLSv1_server_method())) != NULL )
-               SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
+       if ((c = SSL_CTX_new(TLSv1_server_method())) != NULL)
+               uh_tls_ctx_setup(c);
 
        return c;
 }
@@ -59,13 +197,37 @@ void uh_tls_ctx_free(struct listener *l)
 }
 
 
-void uh_tls_client_accept(struct client *c)
+int uh_tls_client_accept(struct client *c)
 {
+       int rv;
+
        if( c->server && c->server->tls )
        {
                c->tls = SSL_new(c->server->tls);
-               SSL_set_fd(c->tls, c->socket);
+               if( c->tls )
+               {
+                       if( (rv = uh_tls_client_ctx_setup(c->tls, c->socket)) < 1 )
+                               goto cleanup;
+
+                       if( (rv = SSL_accept(c->tls)) < 1 )
+                               goto cleanup;
+               }
+               else
+                       rv = 0;
        }
+       else
+       {
+               c->tls = NULL;
+               rv = 1;
+       }
+
+done:
+       return rv;
+
+cleanup:
+       SSL_free(c->tls);
+       c->tls = NULL;
+       goto done;
 }
 
 int uh_tls_client_recv(struct client *c, void *buf, int len)
@@ -90,5 +252,3 @@ void uh_tls_client_close(struct client *c)
                c->tls = NULL;
        }
 }
-
-
index 4a98b78c69c079350d448086507b656b1d35ae0d..24dfb440744417c537ea484c5875a6df80de5ff0 100644 (file)
@@ -26,10 +26,9 @@ int uh_tls_ctx_cert(SSL_CTX *c, const char *file);
 int uh_tls_ctx_key(SSL_CTX *c, const char *file);
 void uh_tls_ctx_free(struct listener *l);
 
-void uh_tls_client_accept(struct client *c);
+int uh_tls_client_accept(struct client *c);
 int uh_tls_client_recv(struct client *c, void *buf, int len);
 int uh_tls_client_send(struct client *c, void *buf, int len);
 void uh_tls_client_close(struct client *c);
 
 #endif
-
index a9980982c3dfd7c5a809d68f2c894bfcfa11820d..318ff559cc3628440e9c34e86109dccb127c7eaa 100644 (file)
@@ -124,7 +124,7 @@ int select_intr(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
 }
 
 
-int uh_tcp_send(struct client *cl, const char *buf, int len)
+int uh_tcp_send_lowlevel(struct client *cl, const char *buf, int len)
 {
        fd_set writer;
        struct timeval timeout;
@@ -135,21 +135,28 @@ int uh_tcp_send(struct client *cl, const char *buf, int len)
        timeout.tv_sec = cl->server->conf->network_timeout;
        timeout.tv_usec = 0;
 
-       if( select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0 )
-       {
-#ifdef HAVE_TLS
-               if( cl->tls )
-                       return cl->server->conf->tls_send(cl, (void *)buf, len);
-               else
-#endif
-                       return send(cl->socket, buf, len, 0);
-       }
+       if (select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0)
+               return send(cl->socket, buf, len, 0);
 
        return -1;
 }
 
+int uh_tcp_send(struct client *cl, const char *buf, int len)
+{
+#ifdef HAVE_TLS
+       if (cl->tls)
+               return cl->server->conf->tls_send(cl, (void *)buf, len);
+       else
+#endif
+               return uh_tcp_send_lowlevel(cl, buf, len);
+}
+
 int uh_tcp_peek(struct client *cl, char *buf, int len)
 {
+       /* sanity check, prevent overflowing peek buffer */
+       if (len > sizeof(cl->peekbuf))
+               return -1;
+
        int sz = uh_tcp_recv(cl, buf, len);
 
        /* store received data in peek buffer */
@@ -162,49 +169,51 @@ int uh_tcp_peek(struct client *cl, char *buf, int len)
        return sz;
 }
 
+int uh_tcp_recv_lowlevel(struct client *cl, char *buf, int len)
+{
+       fd_set reader;
+       struct timeval timeout;
+
+       FD_ZERO(&reader);
+       FD_SET(cl->socket, &reader);
+
+       timeout.tv_sec  = cl->server->conf->network_timeout;
+       timeout.tv_usec = 0;
+
+       if (select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0)
+               return recv(cl->socket, buf, len, 0);
+
+       return -1;
+}
+
 int uh_tcp_recv(struct client *cl, char *buf, int len)
 {
        int sz = 0;
        int rsz = 0;
 
-       fd_set reader;
-       struct timeval timeout;
-
        /* first serve data from peek buffer */
-       if( cl->peeklen > 0 )
+       if (cl->peeklen > 0)
        {
                sz = min(cl->peeklen, len);
                len -= sz; cl->peeklen -= sz;
-
                memcpy(buf, cl->peekbuf, sz);
                memmove(cl->peekbuf, &cl->peekbuf[sz], cl->peeklen);
        }
 
        /* caller wants more */
-       if( len > 0 )
+       if (len > 0)
        {
-               FD_ZERO(&reader);
-               FD_SET(cl->socket, &reader);
-
-               timeout.tv_sec  = cl->server->conf->network_timeout;
-               timeout.tv_usec = 0;
-
-               if( select(cl->socket + 1, &reader, NULL, NULL, &timeout) > 0 )
-               {
 #ifdef HAVE_TLS
-                       if( cl->tls )
-                               rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
-                       else
+               if (cl->tls)
+                       rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len);
+               else
 #endif
-                               rsz = recv(cl->socket, (void *)&buf[sz], len, 0);
+                       rsz = uh_tcp_recv_lowlevel(cl, (void *)&buf[sz], len);
 
-                       if( (sz == 0) || (rsz > 0) )
-                               sz += rsz;
-               }
-               else if( sz == 0 )
-               {
-                       sz = -1;
-               }
+               if (rsz < 0)
+                       return rsz;
+
+               sz += rsz;
        }
 
        return sz;
index 68191a3a6ac520605cff8fe890764b69359a1efe..2d3429af85418da095c98069a8aa03a52144a8b9 100644 (file)
@@ -64,8 +64,10 @@ char *strfind(char *haystack, int hslen, const char *needle, int ndlen);
 int select_intr(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t);
 
 int uh_tcp_send(struct client *cl, const char *buf, int len);
+int uh_tcp_send_lowlevel(struct client *cl, const char *buf, int len);
 int uh_tcp_peek(struct client *cl, char *buf, int len);
 int uh_tcp_recv(struct client *cl, char *buf, int len);
+int uh_tcp_recv_lowlevel(struct client *cl, char *buf, int len);
 
 int uh_http_sendhf(
        struct client *cl, int code, const char *summary,
index 4a3bced722c9ac84107e5aaf771ee33b4ec0d9f1..3563d91d16ef92ad12ed55cae69b410cc5aa2e84 100644 (file)
@@ -512,7 +512,22 @@ static void uh_mainloop(struct config *conf, fd_set serv_fds, int max_fd)
 #ifdef HAVE_TLS
                                                        /* setup client tls context */
                                                        if( conf->tls )
-                                                               conf->tls_accept(cl);
+                                                       {
+                                                               if( conf->tls_accept(cl) < 1 )
+                                                               {
+                                                                       fprintf(stderr,
+                                                                               "tls_accept failed, "
+                                                                               "connection dropped\n");
+
+                                                                       /* close client socket */
+                                                                       close(new_fd);
+
+                                                                       /* remove from global client list */
+                                                                       uh_client_remove(new_fd);
+
+                                                                       continue;
+                                                               }
+                                                       }
 #endif
 
                                                        /* add client socket to global fdset */
index ff058d62bff3e214e4dee0e5c8cb5e35a63050e7..993bf93af1dc0d436864379fbea730df2d196f00 100644 (file)
@@ -98,7 +98,7 @@ struct config {
        int (*tls_cert) (SSL_CTX *c, const char *file);
        int (*tls_key) (SSL_CTX *c, const char *file);
        void (*tls_free) (struct listener *l);
-       void (*tls_accept) (struct client *c);
+       int (*tls_accept) (struct client *c);
        void (*tls_close) (struct client *c);
        int (*tls_recv) (struct client *c, void *buf, int len);
        int (*tls_send) (struct client *c, void *buf, int len);
@@ -159,4 +159,3 @@ struct interpreter {
 #endif
 
 #endif
-