From: jow Date: Sun, 6 Nov 2011 21:17:42 +0000 (+0000) Subject: [backfire] merge all uhttpd changes from trunk X-Git-Url: http://git.ozo.com/?p=openwrt-10.03%2F.git;a=commitdiff_plain;h=08630dd20825db7f635b73db9be4270ca61ee29c [backfire] merge all uhttpd changes from trunk git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@28790 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- diff --git a/package/uhttpd/Makefile b/package/uhttpd/Makefile index a43b1014f..14b1559c3 100644 --- a/package/uhttpd/Makefile +++ b/package/uhttpd/Makefile @@ -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 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) diff --git a/package/uhttpd/files/uhttpd.init b/package/uhttpd/files/uhttpd.init index 069e16fff..1ec009663 100755 --- a/package/uhttpd/files/uhttpd.init +++ b/package/uhttpd/files/uhttpd.init @@ -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}" } } diff --git a/package/uhttpd/src/Makefile b/package/uhttpd/src/Makefile index 06d61bdef..5e98ab875 100644 --- a/package/uhttpd/src/Makefile +++ b/package/uhttpd/src/Makefile @@ -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 - diff --git a/package/uhttpd/src/uhttpd-tls.c b/package/uhttpd/src/uhttpd-tls.c index 008f8e0df..4a9e90792 100644 --- a/package/uhttpd/src/uhttpd-tls.c +++ b/package/uhttpd/src/uhttpd-tls.c @@ -20,15 +20,153 @@ #include "uhttpd-tls.h" #include "uhttpd-utils.h" +#include +#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; } } - - diff --git a/package/uhttpd/src/uhttpd-tls.h b/package/uhttpd/src/uhttpd-tls.h index 4a98b78c6..24dfb4407 100644 --- a/package/uhttpd/src/uhttpd-tls.h +++ b/package/uhttpd/src/uhttpd-tls.h @@ -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 - diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c index a9980982c..318ff559c 100644 --- a/package/uhttpd/src/uhttpd-utils.c +++ b/package/uhttpd/src/uhttpd-utils.c @@ -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; diff --git a/package/uhttpd/src/uhttpd-utils.h b/package/uhttpd/src/uhttpd-utils.h index 68191a3a6..2d3429af8 100644 --- a/package/uhttpd/src/uhttpd-utils.h +++ b/package/uhttpd/src/uhttpd-utils.h @@ -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, diff --git a/package/uhttpd/src/uhttpd.c b/package/uhttpd/src/uhttpd.c index 4a3bced72..3563d91d1 100644 --- a/package/uhttpd/src/uhttpd.c +++ b/package/uhttpd/src/uhttpd.c @@ -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 */ diff --git a/package/uhttpd/src/uhttpd.h b/package/uhttpd/src/uhttpd.h index ff058d62b..993bf93af 100644 --- a/package/uhttpd/src/uhttpd.h +++ b/package/uhttpd/src/uhttpd.h @@ -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 -