# Revision 2695 Index: src/base.h =================================================================== --- src/base.h (.../tags/lighttpd-1.4.24) +++ src/base.h (.../branches/lighttpd-1.4.x) @@ -280,6 +280,7 @@ unsigned short ssl_verifyclient_enforce; unsigned short ssl_verifyclient_depth; buffer *ssl_verifyclient_username; + unsigned short ssl_verifyclient_export_cert; unsigned short use_ipv6; unsigned short defer_accept; Index: src/mod_rewrite.c =================================================================== --- src/mod_rewrite.c (.../tags/lighttpd-1.4.24) +++ src/mod_rewrite.c (.../branches/lighttpd-1.4.x) @@ -9,10 +9,9 @@ #include #include -typedef struct { #ifdef HAVE_PCRE_H +typedef struct { pcre *key; -#endif buffer *value; @@ -70,7 +69,6 @@ } static int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) { -#ifdef HAVE_PCRE_H size_t i; const char *errptr; int erroff; @@ -109,18 +107,9 @@ kvb->used++; return 0; -#else - UNUSED(kvb); - UNUSED(value); - UNUSED(once); - UNUSED(key); - - return -1; -#endif } static void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) { -#ifdef HAVE_PCRE_H size_t i; for (i = 0; i < kvb->size; i++) { @@ -130,7 +119,6 @@ } if (kvb->ptr) free(kvb->ptr); -#endif free(kvb); } @@ -201,24 +189,29 @@ ((data_string *)(da->value->data[j]))->key, ((data_string *)(da->value->data[j]))->value, once)) { -#ifdef HAVE_PCRE_H log_error_write(srv, __FILE__, __LINE__, "sb", "pcre-compile failed for", da->value->data[j]->key); -#else - log_error_write(srv, __FILE__, __LINE__, "s", - "pcre support is missing, please install libpcre and the headers"); -#endif } } } return 0; } +#else +static int parse_config_entry(server *srv, array *ca, const char *option) { + static int logged_message = 0; + if (logged_message) return 0; + if (NULL != array_get_element(ca, option)) { + logged_message = 1; + log_error_write(srv, __FILE__, __LINE__, "s", + "pcre support is missing, please install libpcre and the headers"); + } + return 0; +} +#endif SETDEFAULTS_FUNC(mod_rewrite_set_defaults) { - plugin_data *p = p_d; size_t i = 0; - config_values_t cv[] = { { "url.rewrite-repeat", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "url.rewrite-once", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ @@ -243,33 +236,37 @@ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; +#ifdef HAVE_PCRE_H + plugin_data *p = p_d; + if (!p) return HANDLER_ERROR; /* 0 */ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); +#else + UNUSED(p_d); +#endif for (i = 0; i < srv->config_context->used; i++) { - plugin_config *s; array *ca; +#ifdef HAVE_PCRE_H + plugin_config *s; s = calloc(1, sizeof(plugin_config)); s->rewrite = rewrite_rule_buffer_init(); s->rewrite_NF = rewrite_rule_buffer_init(); - - cv[0].destination = s->rewrite; - cv[1].destination = s->rewrite; - cv[2].destination = s->rewrite_NF; - cv[3].destination = s->rewrite_NF; - cv[4].destination = s->rewrite; - cv[5].destination = s->rewrite; - p->config_storage[i] = s; +#endif + ca = ((data_config *)srv->config_context->data[i])->value; if (0 != config_insert_values_global(srv, ca, cv)) { return HANDLER_ERROR; } +#ifndef HAVE_PCRE_H +# define parse_config_entry(srv, ca, x, option, y) parse_config_entry(srv, ca, option) +#endif parse_config_entry(srv, ca, s->rewrite, "url.rewrite-once", 1); parse_config_entry(srv, ca, s->rewrite, "url.rewrite-final", 1); parse_config_entry(srv, ca, s->rewrite_NF, "url.rewrite-if-not-file", 1); @@ -280,7 +277,9 @@ return HANDLER_GO_ON; } + #ifdef HAVE_PCRE_H + #define PATCH(x) \ p->conf.x = s->x; static int mod_rewrite_patch_connection(server *srv, connection *con, plugin_data *p) { @@ -330,7 +329,7 @@ return 0; } -#endif + URIHANDLER_FUNC(mod_rewrite_con_reset) { plugin_data *p = p_d; @@ -345,7 +344,6 @@ } static int process_rewrite_rules(server *srv, connection *con, plugin_data *p, rewrite_rule_buffer *kvb) { -#ifdef HAVE_PCRE_H size_t i; handler_ctx *hctx; @@ -444,19 +442,11 @@ } #undef N } -#else - UNUSED(srv); - UNUSED(con); - UNUSED(p); - UNUSED(hctx); - UNUSED(kvb); -#endif return HANDLER_GO_ON; } URIHANDLER_FUNC(mod_rewrite_physical) { -#ifdef HAVE_PCRE_H plugin_data *p = p_d; handler_t r; stat_cache_entry *sce; @@ -480,17 +470,11 @@ default: return r; } -#else - UNUSED(srv); - UNUSED(con); - UNUSED(p_d); -#endif return HANDLER_GO_ON; } URIHANDLER_FUNC(mod_rewrite_uri_handler) { -#ifdef HAVE_PCRE_H plugin_data *p = p_d; mod_rewrite_patch_connection(srv, con, p); @@ -498,29 +482,27 @@ if (!p->conf.rewrite) return HANDLER_GO_ON; return process_rewrite_rules(srv, con, p, p->conf.rewrite); -#else - UNUSED(srv); - UNUSED(con); - UNUSED(p_d); -#endif return HANDLER_GO_ON; } +#endif int mod_rewrite_plugin_init(plugin *p); int mod_rewrite_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("rewrite"); +#ifdef HAVE_PCRE_H p->init = mod_rewrite_init; /* it has to stay _raw as we are matching on uri + querystring */ p->handle_uri_raw = mod_rewrite_uri_handler; p->handle_physical = mod_rewrite_physical; - p->set_defaults = mod_rewrite_set_defaults; p->cleanup = mod_rewrite_free; p->connection_reset = mod_rewrite_con_reset; +#endif + p->set_defaults = mod_rewrite_set_defaults; p->data = NULL; Index: src/connections.c =================================================================== --- src/connections.c (.../tags/lighttpd-1.4.24) +++ src/connections.c (.../branches/lighttpd-1.4.x) @@ -807,6 +807,9 @@ CLEAN(authed_user); CLEAN(server_name); CLEAN(error_handler); +#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT + CLEAN(tlsext_server_name); +#endif #undef CLEAN #define CLEAN(x) \ @@ -1250,8 +1253,10 @@ if (b > 0) { char buf[1024]; +#if 0 log_error_write(srv, __FILE__, __LINE__, "sdd", "CLOSE-read()", con->fd, b); +#endif /* */ read(con->fd, buf, sizeof(buf)); @@ -1621,8 +1626,10 @@ } if (b > 0) { char buf[1024]; +#if 0 log_error_write(srv, __FILE__, __LINE__, "sdd", "CLOSE-read()", con->fd, b); +#endif /* */ read(con->fd, buf, sizeof(buf)); Index: src/configfile.c =================================================================== --- src/configfile.c (.../tags/lighttpd-1.4.24) +++ src/configfile.c (.../branches/lighttpd-1.4.x) @@ -99,6 +99,7 @@ { "ssl.verifyclient.enforce", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 57 */ { "ssl.verifyclient.depth", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 58 */ { "ssl.verifyclient.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 59 */ + { "ssl.verifyclient.exportcert", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 60 */ { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, @@ -187,6 +188,7 @@ s->ssl_verifyclient_enforce = 1; s->ssl_verifyclient_username = buffer_init(); s->ssl_verifyclient_depth = 9; + s->ssl_verifyclient_export_cert = 0; cv[2].destination = s->errorfile_prefix; @@ -238,6 +240,7 @@ cv[57].destination = &(s->ssl_verifyclient_enforce); cv[58].destination = &(s->ssl_verifyclient_depth); cv[59].destination = s->ssl_verifyclient_username; + cv[60].destination = &(s->ssl_verifyclient_export_cert); srv->config_storage[i] = s; @@ -325,6 +328,7 @@ PATCH(ssl_verifyclient_enforce); PATCH(ssl_verifyclient_depth); PATCH(ssl_verifyclient_username); + PATCH(ssl_verifyclient_export_cert); return 0; } @@ -425,6 +429,8 @@ PATCH(ssl_verifyclient_depth); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) { PATCH(ssl_verifyclient_username); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) { + PATCH(ssl_verifyclient_export_cert); } } } Index: src/mod_rrdtool.c =================================================================== --- src/mod_rrdtool.c (.../tags/lighttpd-1.4.24) +++ src/mod_rrdtool.c (.../branches/lighttpd-1.4.x) @@ -237,11 +237,11 @@ "not a regular file:", s->path_rrd); return HANDLER_ERROR; } - } - /* still create DB if it's empty file */ - if (st.st_size > 0) { - return HANDLER_GO_ON; + /* still create DB if it's empty file */ + if (st.st_size > 0) { + return HANDLER_GO_ON; + } } /* create a new one */ Index: src/response.c =================================================================== --- src/response.c (.../tags/lighttpd-1.4.24) +++ src/response.c (.../branches/lighttpd-1.4.x) @@ -131,8 +131,77 @@ return 0; } +#ifdef USE_OPENSSL +static void https_add_ssl_entries(connection *con) { + X509 *xs; + X509_NAME *xn; + X509_NAME_ENTRY *xe; + if ( + SSL_get_verify_result(con->ssl) != X509_V_OK + || !(xs = SSL_get_peer_certificate(con->ssl)) + ) { + return; + } + xn = X509_get_subject_name(xs); + for (int i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) { + int xobjnid; + const char * xobjsn; + data_string *envds; + if (!(xe = X509_NAME_get_entry(xn, i))) { + continue; + } + xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe)); + xobjsn = OBJ_nid2sn(xobjnid); + if (!xobjsn) { + continue; + } + + if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { + envds = data_string_init(); + } + buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_S_DN_")); + buffer_append_string(envds->key, xobjsn); + buffer_copy_string_len( + envds->value, + (const char *)xe->value->data, xe->value->length + ); + /* pick one of the exported values as "authed user", for example + * ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID" or "SSL_CLIENT_S_DN_emailAddress" + */ + if (buffer_is_equal(con->conf.ssl_verifyclient_username, envds->key)) { + buffer_copy_string_buffer(con->authed_user, envds->value); + } + array_insert_unique(con->environment, (data_unset *)envds); + } + if (con->conf.ssl_verifyclient_export_cert) { + BIO *bio; + if (NULL != (bio = BIO_new(BIO_s_mem()))) { + data_string *envds; + int n; + + PEM_write_bio_X509(bio, xs); + n = BIO_pending(bio); + + if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { + envds = data_string_init(); + } + + buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_CERT")); + buffer_prepare_copy(envds->value, n+1); + BIO_read(bio, envds->value->ptr, n); + BIO_free(bio); + envds->value->ptr[n] = '\0'; + envds->value->used = n+1; + array_insert_unique(con->environment, (data_unset *)envds); + } + } + X509_free(xs); +} +#endif + + handler_t http_response_prepare(server *srv, connection *con) { handler_t r; @@ -279,6 +348,12 @@ log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path); } +#ifdef USE_OPENSSL + if (con->conf.is_ssl && con->conf.ssl_verifyclient) { + https_add_ssl_entries(con); + } +#endif + /** * * call plugins Index: src/mod_fastcgi.c =================================================================== --- src/mod_fastcgi.c (.../tags/lighttpd-1.4.24) +++ src/mod_fastcgi.c (.../branches/lighttpd-1.4.x) @@ -2416,8 +2416,8 @@ static int fastcgi_get_packet(server *srv, handler_ctx *hctx, fastcgi_response_packet *packet) { chunk * c; - size_t offset = 0; - size_t toread = 0; + size_t offset; + size_t toread; FCGI_Header *header; if (!hctx->rb->first) return -1; @@ -2428,20 +2428,22 @@ packet->padding = 0; packet->request_id = 0; + offset = 0; toread = 8; /* get at least the FastCGI header */ for (c = hctx->rb->first; c; c = c->next) { - size_t weWant = sizeof(*header) - (packet->b->used - 1); size_t weHave = c->mem->used - c->offset - 1; - if (weHave > weWant) weHave = weWant; + if (weHave > toread) weHave = toread; if (packet->b->used == 0) { buffer_copy_string_len(packet->b, c->mem->ptr + c->offset, weHave); } else { buffer_append_string_len(packet->b, c->mem->ptr + c->offset, weHave); } + toread -= weHave; + offset = weHave; /* skip offset bytes in chunk for "real" data */ - if (packet->b->used >= sizeof(*header) + 1) break; + if (0 == toread) break; } if ((packet->b->used == 0) || @@ -2449,7 +2451,9 @@ /* no header */ buffer_free(packet->b); - log_error_write(srv, __FILE__, __LINE__, "sdsds", "FastCGI: header too small:", packet->b->used, "bytes <", sizeof(FCGI_Header), "bytes"); + if (hctx->plugin_data->conf.debug) { + log_error_write(srv, __FILE__, __LINE__, "sdsds", "FastCGI: header too small:", packet->b->used, "bytes <", sizeof(FCGI_Header), "bytes, waiting for more data"); + } return -1; } @@ -2461,9 +2465,6 @@ packet->type = header->type; packet->padding = header->paddingLength; - /* the first bytes in packet->b are the header */ - offset = sizeof(*header); - /* ->b should only be the content */ buffer_copy_string_len(packet->b, CONST_STR_LEN("")); /* used == 1 */ @@ -2477,7 +2478,7 @@ buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave); - /* we only skipped the first 8 bytes as they are the fcgi header */ + /* we only skipped the first bytes as they belonged to the fcgi header */ offset = 0; } @@ -3080,34 +3081,17 @@ if (ret < 0) { switch(errno) { + case EPIPE: case ENOTCONN: + case ECONNRESET: /* the connection got dropped after accept() - * - * this is most of the time a PHP which dies - * after PHP_FCGI_MAX_REQUESTS - * + * we don't care about that - if you accept() it, you have to handle it. */ - if (hctx->wb->bytes_out == 0 && - hctx->reconnects < 5) { - usleep(10000); /* take away the load of the webserver - * to give the php a chance to restart - */ - fcgi_reconnect(srv, hctx); - - return HANDLER_WAIT_FOR_FD; - } - - /* not reconnected ... why - * - * far@#lighttpd report this for FreeBSD - * - */ - - log_error_write(srv, __FILE__, __LINE__, "ssosd", - "[REPORT ME] connection was dropped after accept(). reconnect() denied:", + log_error_write(srv, __FILE__, __LINE__, "ssosb", + "connection was dropped after accept() (perhaps the fastcgi process died),", "write-offset:", hctx->wb->bytes_out, - "reconnect attempts:", hctx->reconnects); + "socket:", hctx->proc->connection_name); return HANDLER_ERROR; default: Index: src/mod_magnet.c =================================================================== --- src/mod_magnet.c (.../tags/lighttpd-1.4.24) +++ src/mod_magnet.c (.../branches/lighttpd-1.4.x) @@ -170,6 +170,7 @@ return lua_gettop(L); } else { lua_pushvalue(L, lua_upvalueindex(1)); + lua_insert(L, 1); lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); return lua_gettop(L); } @@ -824,9 +825,36 @@ return 0; } +static int traceback (lua_State *L) { + if (!lua_isstring(L, 1)) /* 'message' not a string? */ + return 1; /* keep it intact */ + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); /* pass error message */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback */ + return 1; +} + +static int push_traceback(lua_State *L, int narg) { + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, traceback); + lua_insert(L, base); + return base; +} + static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, buffer *name) { lua_State *L; int lua_return_value = -1; + int errfunc; /* get the script-context */ @@ -955,7 +983,9 @@ lua_setfenv(L, -2); /* on the stack should be a modified env (sp -= 1) */ - if (lua_pcall(L, 0, 1, 0)) { + errfunc = push_traceback(L, 0); + if (lua_pcall(L, 0, 1, errfunc)) { + lua_remove(L, errfunc); log_error_write(srv, __FILE__, __LINE__, "ss", "lua_pcall():", @@ -969,6 +999,7 @@ return HANDLER_FINISHED; } + lua_remove(L, errfunc); /* we should have the function-copy and the return value on the stack */ assert(lua_gettop(L) == 2); Index: configure.ac =================================================================== Index: doc/Makefile.am =================================================================== --- doc/Makefile.am (.../tags/lighttpd-1.4.24) +++ doc/Makefile.am (.../branches/lighttpd-1.4.x) @@ -89,7 +89,7 @@ rst2html $^ > $@ -html: $(HTMLDOCS) +html-local: $(HTMLDOCS) #%.ps.gz: %.ps # gzip $^ Index: SConstruct =================================================================== Index: NEWS =================================================================== --- NEWS (.../tags/lighttpd-1.4.24) +++ NEWS (.../branches/lighttpd-1.4.x) @@ -3,7 +3,22 @@ NEWS ==== -- 1.4.24 - +- 1.4.26 - + * + +- 1.4.25 - 2009-11-21 + * mod_magnet: fix pairs() for normal tables and strings (fixes #1307) + * mod_magnet: add traceback for printing lua errors + * mod_rewrite: fix compile error if compiled without pcre + * disable warning "CLOSE-read" (fixes #2091) + * mod_rrdtool: fix creating file if it doesn't exist (#1788) + * reset tlsext_server_name in connection_reset - fixes random hostnames in the $HTTP["host"] conditional + * export some SSL_CLIENT_* vars for client cert validation (fixes #1288, thx presbrey) + * mod_fastcgi: fix mod_fastcgi packet parsing + * mod_fastcgi: Don't reconnect after connect() succeeded (fixes #2096) + * Fix configure.ac to allow autoreconf, also enables make V=0 + +- 1.4.24 - 2009-10-25 * Add T_CONFIG_INT for bigger integers from the config (needed for #1966) * Use unsigned int (and T_CONFIG_INT) for max_request_size * Use unsigned int for secdownload.timeout (fixes #1966) Index: CMakeLists.txt ===================================================================