From af4611d4e02c8a5b0c72cae08c1d944528d63787 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 25 Mar 2010 02:04:50 +0000 Subject: [PATCH] uhttpd: move Lua and TLS support into loadable plugins --- contrib/package/uhttpd/Makefile | 44 +++++++++- contrib/package/uhttpd/src/Makefile | 42 ++++++---- contrib/package/uhttpd/src/uhttpd-lua.c | 6 ++ contrib/package/uhttpd/src/uhttpd-lua.h | 2 + contrib/package/uhttpd/src/uhttpd-tls.c | 22 +++++ contrib/package/uhttpd/src/uhttpd-tls.h | 6 +- contrib/package/uhttpd/src/uhttpd-utils.c | 4 +- contrib/package/uhttpd/src/uhttpd.c | 133 ++++++++++++++++++++++++------ contrib/package/uhttpd/src/uhttpd.h | 21 +++++ 9 files changed, 234 insertions(+), 46 deletions(-) diff --git a/contrib/package/uhttpd/Makefile b/contrib/package/uhttpd/Makefile index 802fb209e..c7e18c9ba 100644 --- a/contrib/package/uhttpd/Makefile +++ b/contrib/package/uhttpd/Makefile @@ -14,11 +14,15 @@ PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) include $(INCLUDE_DIR)/package.mk -define Package/uhttpd +define Package/uhttpd/default SECTION:=net CATEGORY:=Network TITLE:=uHTTPd - tiny, single threaded HTTP server - DEPENDS:=+liblua +libcyassl +zlib +endef + +define Package/uhttpd + $(Package/uhttpd/default) + MENU:=1 endef define Package/uhttpd/description @@ -27,6 +31,29 @@ define Package/uhttpd/description HTTP daemon. endef + +define Package/uhttpd-mod-tls + $(Package/uhttpd/default) + TITLE+= (TLS plugin) + DEPENDS:=uhttpd +libcyassl +endef + +define Package/uhttpd-mod-tls/description + The TLS plugin adds HTTPS support to uHTTPd. +endef + + +define Package/uhttpd-mod-lua + $(Package/uhttpd/default) + TITLE+= (Lua plugin) + DEPENDS:=uhttpd +liblua +endef + +define Package/uhttpd-mod-lua/description + The Lua plugin adds a CGI-like Lua runtime interface to uHTTPd. +endef + + # hack to use CyASSL headers TARGET_CFLAGS += -I$(firstword $(wildcard $(BUILD_DIR)/cyassl-*/include)) @@ -48,4 +75,17 @@ define Package/uhttpd/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd $(1)/usr/sbin/uhttpd endef +define Package/uhttpd-mod-tls/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_tls.so $(1)/usr/lib/ +endef + +define Package/uhttpd-mod-lua/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_BIN) $(PKG_BUILD_DIR)/uhttpd_lua.so $(1)/usr/lib/ +endef + + $(eval $(call BuildPackage,uhttpd)) +$(eval $(call BuildPackage,uhttpd-mod-tls)) +$(eval $(call BuildPackage,uhttpd-mod-lua)) diff --git a/contrib/package/uhttpd/src/Makefile b/contrib/package/uhttpd/src/Makefile index 7bbb23afc..06d61bdef 100644 --- a/contrib/package/uhttpd/src/Makefile +++ b/contrib/package/uhttpd/src/Makefile @@ -3,36 +3,50 @@ LUA_SUPPORT ?= 1 TLS_SUPPORT ?= 1 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 -lm +LDFLAGS ?= -L./lua-5.1.4/src -L./cyassl-1.4.0/src/.libs CFLAGS += -Wall --std=gnu99 -LDFLAGS += -lm -lcrypt OBJ = uhttpd.o uhttpd-file.o uhttpd-utils.o +LIB = -Wl,--export-dynamic -lcrypt -ldl + +TLSLIB = +LUALIB = + + +world: compile ifeq ($(CGI_SUPPORT),1) - OBJ += uhttpd-cgi.o - CFLAGS += -DHAVE_CGI + OBJ += uhttpd-cgi.o + CFLAGS += -DHAVE_CGI endif ifeq ($(LUA_SUPPORT),1) - OBJ += uhttpd-lua.o - CFLAGS += -DHAVE_LUA - LDFLAGS += -ldl -llua + CFLAGS += -DHAVE_LUA + LUALIB = uhttpd_lua.so + + $(LUALIB): uhttpd-lua.c + $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \ + -shared -lm -llua -ldl \ + -o $(LUALIB) uhttpd-lua.c endif ifeq ($(TLS_SUPPORT),1) - OBJ += uhttpd-tls.o - CFLAGS += -DHAVE_TLS - LDFLAGS += -lpthread -lz -lcyassl + CFLAGS += -DHAVE_TLS + TLSLIB = uhttpd_tls.so + + $(TLSLIB): uhttpd-tls.c + $(CC) $(CFLAGS) $(LDFLAGS) $(FPIC) \ + -shared -lcyassl \ + -o $(TLSLIB) uhttpd-tls.c endif %.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< + $(CC) $(CFLAGS) -c -o $@ $< -compile: $(OBJ) - $(CC) -o uhttpd $(LDFLAGS) $(OBJ) +compile: $(OBJ) $(TLSLIB) $(LUALIB) + $(CC) -o uhttpd $(LDFLAGS) $(LIB) $(OBJ) clean: - rm -f *.o uhttpd + rm -f *.o *.so uhttpd diff --git a/contrib/package/uhttpd/src/uhttpd-lua.c b/contrib/package/uhttpd/src/uhttpd-lua.c index db14eda45..ab09841cd 100644 --- a/contrib/package/uhttpd/src/uhttpd-lua.c +++ b/contrib/package/uhttpd/src/uhttpd-lua.c @@ -533,3 +533,9 @@ void uh_lua_request(struct client *cl, struct http_request *req, lua_State *L) } } +void uh_lua_close(lua_State *L) +{ + lua_close(L); +} + + diff --git a/contrib/package/uhttpd/src/uhttpd-lua.h b/contrib/package/uhttpd/src/uhttpd-lua.h index 518c2bc83..730466500 100644 --- a/contrib/package/uhttpd/src/uhttpd-lua.h +++ b/contrib/package/uhttpd/src/uhttpd-lua.h @@ -38,4 +38,6 @@ void uh_lua_request( struct client *cl, struct http_request *req, lua_State *L ); +void uh_lua_close(lua_State *L); + #endif diff --git a/contrib/package/uhttpd/src/uhttpd-tls.c b/contrib/package/uhttpd/src/uhttpd-tls.c index bbec7509d..cb5061638 100644 --- a/contrib/package/uhttpd/src/uhttpd-tls.c +++ b/contrib/package/uhttpd/src/uhttpd-tls.c @@ -33,6 +33,16 @@ SSL_CTX * uh_tls_ctx_init() return c; } +int uh_tls_ctx_cert(SSL_CTX *c, const char *file) +{ + return SSL_CTX_use_certificate_file(c, file, SSL_FILETYPE_ASN1); +} + +int uh_tls_ctx_key(SSL_CTX *c, const char *file) +{ + return SSL_CTX_use_PrivateKey_file(c, file, SSL_FILETYPE_ASN1); +} + void uh_tls_ctx_free(struct listener *l) { SSL_CTX_free(l->tls); @@ -48,6 +58,16 @@ void uh_tls_client_accept(struct client *c) } } +int uh_tls_client_recv(struct client *c, void *buf, int len) +{ + return SSL_read(c->tls, buf, len); +} + +int uh_tls_client_send(struct client *c, void *buf, int len) +{ + return SSL_write(c->tls, buf, len); +} + void uh_tls_client_close(struct client *c) { if( c->tls ) @@ -58,3 +78,5 @@ void uh_tls_client_close(struct client *c) c->tls = NULL; } } + + diff --git a/contrib/package/uhttpd/src/uhttpd-tls.h b/contrib/package/uhttpd/src/uhttpd-tls.h index 2de2d26d8..4a98b78c6 100644 --- a/contrib/package/uhttpd/src/uhttpd-tls.h +++ b/contrib/package/uhttpd/src/uhttpd-tls.h @@ -22,9 +22,13 @@ SSL_CTX * uh_tls_ctx_init(); - +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_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/contrib/package/uhttpd/src/uhttpd-utils.c b/contrib/package/uhttpd/src/uhttpd-utils.c index 01cfa121b..c1e08b069 100644 --- a/contrib/package/uhttpd/src/uhttpd-utils.c +++ b/contrib/package/uhttpd/src/uhttpd-utils.c @@ -104,7 +104,7 @@ int uh_tcp_send(struct client *cl, const char *buf, int len) { #ifdef HAVE_TLS if( cl->tls ) - return SSL_write(cl->tls, buf, len); + return cl->server->conf->tls_send(cl, (void *)buf, len); else #endif return send(cl->socket, buf, len, 0); @@ -147,7 +147,7 @@ int uh_tcp_recv(struct client *cl, char *buf, int len) { #ifdef HAVE_TLS if( cl->tls ) - rsz = SSL_read(cl->tls, (void *)&buf[sz], len); + rsz = cl->server->conf->tls_recv(cl, (void *)&buf[sz], len); else #endif rsz = recv(cl->socket, (void *)&buf[sz], len, 0); diff --git a/contrib/package/uhttpd/src/uhttpd.c b/contrib/package/uhttpd/src/uhttpd.c index 401749fae..a7db794a5 100644 --- a/contrib/package/uhttpd/src/uhttpd.c +++ b/contrib/package/uhttpd/src/uhttpd.c @@ -417,6 +417,10 @@ int main (int argc, char **argv) char bind[128]; char *port = NULL; + /* library handles */ + void *tls_lib; + void *lua_lib; + /* clear the master and temp sets */ FD_ZERO(&used_fds); FD_ZERO(&serv_fds); @@ -445,11 +449,39 @@ int main (int argc, char **argv) memset(bind, 0, sizeof(bind)); #ifdef HAVE_TLS - /* init SSL context */ - if( ! (conf.tls = uh_tls_ctx_init()) ) + /* load TLS plugin */ + if( ! (tls_lib = dlopen("uhttpd_tls.so", RTLD_LAZY | RTLD_GLOBAL)) ) { - fprintf(stderr, "Failed to initalize SSL context\n"); - exit(1); + fprintf(stderr, + "Notice: Unable to load TLS plugin - disabling SSL support! " + "(Reason: %s)\n", dlerror() + ); + } + else + { + /* resolve functions */ + if( !(conf.tls_init = dlsym(tls_lib, "uh_tls_ctx_init")) || + !(conf.tls_cert = dlsym(tls_lib, "uh_tls_ctx_cert")) || + !(conf.tls_key = dlsym(tls_lib, "uh_tls_ctx_key")) || + !(conf.tls_free = dlsym(tls_lib, "uh_tls_ctx_free")) || + !(conf.tls_accept = dlsym(tls_lib, "uh_tls_client_accept")) || + !(conf.tls_close = dlsym(tls_lib, "uh_tls_client_close")) || + !(conf.tls_recv = dlsym(tls_lib, "uh_tls_client_recv")) || + !(conf.tls_send = dlsym(tls_lib, "uh_tls_client_send")) + ) { + fprintf(stderr, + "Error: Failed to lookup required symbols " + "in TLS plugin: %s\n", dlerror() + ); + exit(1); + } + + /* init SSL context */ + if( ! (conf.tls = conf.tls_init()) ) + { + fprintf(stderr, "Error: Failed to initalize SSL context\n"); + exit(1); + } } #endif @@ -477,12 +509,23 @@ int main (int argc, char **argv) } if( opt == 's' ) + { + if( !conf.tls ) + { + fprintf(stderr, + "Notice: TLS support is disabled, " + "ignoring '-s %s'\n", optarg + ); + continue; + } + tls = 1; + } /* bind sockets */ bound += uh_socket_bind( &serv_fds, &max_fd, bind[0] ? bind : NULL, port, - &hints, tls, &conf + &hints, (opt == 's'), &conf ); break; @@ -490,24 +533,34 @@ int main (int argc, char **argv) #ifdef HAVE_TLS /* certificate */ case 'C': - if( SSL_CTX_use_certificate_file(conf.tls, optarg, SSL_FILETYPE_ASN1) < 1 ) + if( conf.tls ) { - fprintf(stderr, "Invalid certificate file given\n"); - exit(1); + if( conf.tls_cert(conf.tls, optarg) < 1 ) + { + fprintf(stderr, + "Error: Invalid certificate file given\n"); + exit(1); + } + + keys++; } - keys++; break; /* key */ case 'K': - if( SSL_CTX_use_PrivateKey_file(conf.tls, optarg, SSL_FILETYPE_ASN1) < 1 ) + if( conf.tls ) { - fprintf(stderr, "Invalid private key file given\n"); - exit(1); + if( conf.tls_key(conf.tls, optarg) < 1 ) + { + fprintf(stderr, + "Error: Invalid private key file given\n"); + exit(1); + } + + keys++; } - keys++; break; #endif @@ -515,7 +568,8 @@ int main (int argc, char **argv) case 'h': if( ! realpath(optarg, conf.docroot) ) { - fprintf(stderr, "Invalid directory %s: %s\n", optarg, strerror(errno)); + fprintf(stderr, "Error: Invalid directory %s: %s\n", + optarg, strerror(errno)); exit(1); } break; @@ -604,21 +658,21 @@ int main (int argc, char **argv) #ifdef HAVE_TLS if( (tls == 1) && (keys < 2) ) { - fprintf(stderr, "Missing private key or certificate file\n"); + fprintf(stderr, "Error: Missing private key or certificate file\n"); exit(1); } #endif if( bound < 1 ) { - fprintf(stderr, "No sockets bound, unable to continue\n"); + fprintf(stderr, "Error: No sockets bound, unable to continue\n"); exit(1); } /* default docroot */ if( !conf.docroot[0] && !realpath(".", conf.docroot) ) { - fprintf(stderr, "Can not determine default document root: %s\n", + fprintf(stderr, "Error: Can not determine default document root: %s\n", strerror(errno)); exit(1); } @@ -637,14 +691,37 @@ int main (int argc, char **argv) #endif #ifdef HAVE_LUA - /* init Lua runtime if handler is specified */ - if( conf.lua_handler ) + /* load Lua plugin */ + if( ! (lua_lib = dlopen("uhttpd_lua.so", RTLD_LAZY | RTLD_GLOBAL)) ) { - /* default lua prefix */ - if( ! conf.lua_prefix ) - conf.lua_prefix = "/lua"; + fprintf(stderr, + "Notice: Unable to load Lua plugin - disabling Lua support! " + "(Reason: %s)\n", dlerror() + ); + } + else + { + /* resolve functions */ + if( !(conf.lua_init = dlsym(lua_lib, "uh_lua_init")) || + !(conf.lua_close = dlsym(lua_lib, "uh_lua_close")) || + !(conf.lua_request = dlsym(lua_lib, "uh_lua_request")) + ) { + fprintf(stderr, + "Error: Failed to lookup required symbols " + "in Lua plugin: %s\n", dlerror() + ); + exit(1); + } + + /* init Lua runtime if handler is specified */ + if( conf.lua_handler ) + { + /* default lua prefix */ + if( ! conf.lua_prefix ) + conf.lua_prefix = "/lua"; - L = uh_lua_init(conf.lua_handler); + L = conf.lua_init(conf.lua_handler); + } } #endif @@ -711,7 +788,8 @@ int main (int argc, char **argv) { #ifdef HAVE_TLS /* setup client tls context */ - uh_tls_client_accept(cl); + if( conf.tls ) + conf.tls_accept(cl); #endif /* add client socket to global fdset */ @@ -753,7 +831,7 @@ int main (int argc, char **argv) /* Lua request? */ if( L && uh_path_match(conf.lua_prefix, req->url) ) { - uh_lua_request(cl, req, L); + conf.lua_request(cl, req, L); } else #endif @@ -793,7 +871,8 @@ int main (int argc, char **argv) #ifdef HAVE_TLS /* free client tls context */ - uh_tls_client_close(cl); + if( conf.tls ) + conf.tls_close(cl); #endif cleanup: @@ -812,7 +891,7 @@ int main (int argc, char **argv) #ifdef HAVE_LUA /* destroy the Lua state */ if( L != NULL ) - lua_close(L); + conf.lua_close(L); #endif return 0; diff --git a/contrib/package/uhttpd/src/uhttpd.h b/contrib/package/uhttpd/src/uhttpd.h index d26835a70..bb08afa1a 100644 --- a/contrib/package/uhttpd/src/uhttpd.h +++ b/contrib/package/uhttpd/src/uhttpd.h @@ -32,6 +32,13 @@ #include #include +#include + + +#ifdef HAVE_LUA +#include +#endif + #ifdef HAVE_TLS #include #endif @@ -48,6 +55,9 @@ #define UH_HTTP_MSG_HEAD 1 #define UH_HTTP_MSG_POST 2 +struct listener; +struct client; +struct http_request; struct config { char docroot[PATH_MAX]; @@ -59,11 +69,22 @@ struct config { #ifdef HAVE_LUA char *lua_prefix; char *lua_handler; + lua_State * (*lua_init) (const char *handler); + void (*lua_close) (lua_State *L); + void (*lua_request) (struct client *cl, struct http_request *req, lua_State *L); #endif #ifdef HAVE_TLS char *cert; char *key; SSL_CTX *tls; + SSL_CTX * (*tls_init) (void); + 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); + 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); #endif }; -- 2.11.0