diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/base.h | 6 | ||||
-rw-r--r-- | src/configfile.c | 26 | ||||
-rw-r--r-- | src/connections.c | 14 | ||||
-rw-r--r-- | src/etag.c | 24 | ||||
-rw-r--r-- | src/etag.h | 4 | ||||
-rw-r--r-- | src/http_auth.c | 25 | ||||
-rw-r--r-- | src/mod_access.c | 37 | ||||
-rw-r--r-- | src/mod_accesslog.c | 2 | ||||
-rw-r--r-- | src/mod_fastcgi.c | 100 | ||||
-rw-r--r-- | src/mod_scgi.c | 6 | ||||
-rw-r--r-- | src/mod_ssi.c | 2 | ||||
-rw-r--r-- | src/mod_staticfile.c | 19 | ||||
-rw-r--r-- | src/mod_status.c | 11 | ||||
-rw-r--r-- | src/mod_webdav.c | 4 | ||||
-rw-r--r-- | src/proc_open.c | 2 | ||||
-rw-r--r-- | src/request.c | 33 | ||||
-rw-r--r-- | src/server.c | 16 | ||||
-rw-r--r-- | src/spawn-fcgi.c | 2 | ||||
-rw-r--r-- | src/stat_cache.c | 6 |
19 files changed, 248 insertions, 91 deletions
@@ -25,6 +25,7 @@ #include "fdevent.h" #include "sys-socket.h" #include "splaytree.h" +#include "etag.h" #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H @@ -269,6 +270,9 @@ typedef struct { unsigned short use_ipv6; unsigned short is_ssl; unsigned short allow_http11; + unsigned short etag_use_inode; + unsigned short etag_use_mtime; + unsigned short etag_use_size; unsigned short force_lowercase_filenames; /* if the FS is case-insensitive, force all files to lower-case */ unsigned short max_request_size; @@ -410,6 +414,8 @@ typedef struct { SSL *ssl; buffer *ssl_error_want_reuse_buffer; #endif + /* etag handling */ + etag_flags_t etag_flags; } connection; typedef struct { diff --git a/src/configfile.c b/src/configfile.c index 5ff3261..921109f 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -89,7 +89,9 @@ static int config_insert(server *srv) { { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */ { "ssl.cipher-list", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 46 */ { "ssl.use-sslv2", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 47 */ - + { "etag.use-inode", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 48 */ + { "etag.use-mtime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 49 */ + { "etag.use-size", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 50 */ { "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 }, @@ -162,6 +164,9 @@ static int config_insert(server *srv) { #endif s->kbytes_per_second = 0; s->allow_http11 = 1; + s->etag_use_inode = 1; + s->etag_use_mtime = 1; + s->etag_use_size = 1; s->range_requests = 1; s->force_lowercase_filenames = 0; s->global_kbytes_per_second = 0; @@ -206,6 +211,9 @@ static int config_insert(server *srv) { cv[46].destination = s->ssl_cipher_list; cv[47].destination = &(s->ssl_use_sslv2); + cv[48].destination = &(s->etag_use_inode); + cv[49].destination = &(s->etag_use_mtime); + cv[50].destination = &(s->etag_use_size); srv->config_storage[i] = s; @@ -280,8 +288,10 @@ int config_setup_connection(server *srv, connection *con) { PATCH(ssl_ca_file); PATCH(ssl_cipher_list); PATCH(ssl_use_sslv2); - - + PATCH(etag_use_inode); + PATCH(etag_use_mtime); + PATCH(etag_use_size); + return 0; } @@ -323,6 +333,12 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) { PATCH(max_read_idle); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.use-xattr"))) { PATCH(use_xattr); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-inode"))) { + PATCH(etag_use_inode); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-mtime"))) { + PATCH(etag_use_mtime); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-size"))) { + PATCH(etag_use_size); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) { PATCH(ssl_pemfile); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) { @@ -365,6 +381,10 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) { } } + con->etag_flags = (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) | + (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) | + (con->conf.etag_use_size ? ETAG_USE_SIZE : 0); + return 0; } #undef PATCH diff --git a/src/connections.c b/src/connections.c index 806e4b6..2f715ef 100644 --- a/src/connections.c +++ b/src/connections.c @@ -1252,6 +1252,16 @@ connection *connection_accept(server *srv, server_socket *srv_socket) { socklen_t cnt_len; /* accept it and register the fd */ + /** + * check if we can still open a new connections + * + * see #1216 + */ + + if (srv->conns->used >= srv->max_conns) { + return NULL; + } + cnt_len = sizeof(cnt_addr); if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) { @@ -1265,6 +1275,9 @@ connection *connection_accept(server *srv, server_socket *srv_socket) { case ECONNABORTED: /* this is a FreeBSD thingy */ /* we were stopped _after_ we had a connection */ break; + case EMFILE: + /* out of fds */ + break; default: log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno); } @@ -1432,6 +1445,7 @@ int connection_state_machine(server *srv, connection *con) { } else if (con->in_error_handler) { /* error-handler is back and has generated content */ /* if Status: was set, take it otherwise use 200 */ + con->http_status = con->error_handler_saved_status; } if (con->http_status == 0) con->http_status = 200; @@ -8,12 +8,24 @@ int etag_is_equal(buffer *etag, const char *matches) { return 0; } -int etag_create(buffer *etag, struct stat *st) { - buffer_copy_off_t(etag, st->st_ino); - buffer_append_string_len(etag, CONST_STR_LEN("-")); - buffer_append_off_t(etag, st->st_size); - buffer_append_string_len(etag, CONST_STR_LEN("-")); - buffer_append_long(etag, st->st_mtime); +int etag_create(buffer *etag, struct stat *st,etag_flags_t flags) { + if (0 == flags) return 0; + + buffer_reset(etag); + + if (flags & ETAG_USE_INODE) { + buffer_append_off_t(etag, st->st_ino); + buffer_append_string_len(etag, CONST_STR_LEN("-")); + } + + if (flags & ETAG_USE_SIZE) { + buffer_append_off_t(etag, st->st_size); + buffer_append_string_len(etag, CONST_STR_LEN("-")); + } + + if (flags & ETAG_USE_MTIME) { + buffer_append_long(etag, st->st_mtime); + } return 0; } @@ -7,8 +7,10 @@ #include "buffer.h" +typedef enum { ETAG_USE_INODE = 1, ETAG_USE_MTIME = 2, ETAG_USE_SIZE = 4 } etag_flags_t; + int etag_is_equal(buffer *etag, const char *matches); -int etag_create(buffer *etag, struct stat *st); +int etag_create(buffer *etag, struct stat *st, etag_flags_t flags); int etag_mutate(buffer *mut, buffer *etag); diff --git a/src/http_auth.c b/src/http_auth.c index fc125cf..abb69f5 100644 --- a/src/http_auth.c +++ b/src/http_auth.c @@ -830,7 +830,13 @@ int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, username = buffer_init(); - base64_decode(username, realm_str); + if (!base64_decode(username, realm_str)) { + buffer_free(username); + + log_error_write(srv, __FILE__, __LINE__, "sb", "decodeing base64-string failed", username); + + return 0; + } /* r2 == user:password */ if (NULL == (pw = strchr(username->ptr, ':'))) { @@ -967,7 +973,7 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p for (c = b->ptr; *c; c++) { /* skip whitespaces */ while (*c == ' ' || *c == '\t') c++; - if (!c) break; + if (!*c) break; for (i = 0; dkv[i].key; i++) { if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) { @@ -1016,6 +1022,21 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p log_error_write(srv, __FILE__, __LINE__, "s", "digest: missing field"); + + buffer_free(b); + return -1; + } + + /** + * protect the md5-sess against missing cnonce and nonce + */ + if (algorithm && + 0 == strcasecmp(algorithm, "md5-sess") && + (!nonce || !cnonce)) { + log_error_write(srv, __FILE__, __LINE__, "s", + "digest: (md5-sess: missing field"); + + buffer_free(b); return -1; } diff --git a/src/mod_access.c b/src/mod_access.c index 3fc0599..f100c80 100644 --- a/src/mod_access.c +++ b/src/mod_access.c @@ -111,6 +111,15 @@ static int mod_access_patch_connection(server *srv, connection *con, plugin_data } #undef PATCH +/** + * URI handler + * + * we will get called twice: + * - after the clean up of the URL and + * - after the pathinfo checks are done + * + * this handles the issue of trailing slashes + */ URIHANDLER_FUNC(mod_access_uri_handler) { plugin_data *p = p_d; int s_len; @@ -122,28 +131,41 @@ URIHANDLER_FUNC(mod_access_uri_handler) { s_len = con->uri.path->used - 1; + if (con->conf.log_request_handling) { + log_error_write(srv, __FILE__, __LINE__, "s", + "-- mod_access_uri_handler called"); + } + for (k = 0; k < p->conf.access_deny->used; k++) { data_string *ds = (data_string *)p->conf.access_deny->data[k]; int ct_len = ds->value->used - 1; + int denied = 0; - if (ct_len > s_len) continue; + if (ct_len > s_len) continue; if (ds->value->used == 0) continue; /* if we have a case-insensitive FS we have to lower-case the URI here too */ if (con->conf.force_lowercase_filenames) { if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { - con->http_status = 403; - - return HANDLER_FINISHED; + denied = 1; } } else { if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { - con->http_status = 403; + denied = 1; + } + } - return HANDLER_FINISHED; + if (denied) { + con->http_status = 403; + + if (con->conf.log_request_handling) { + log_error_write(srv, __FILE__, __LINE__, "sb", + "url denied as we match:", ds->value); } + + return HANDLER_FINISHED; } } @@ -158,7 +180,8 @@ int mod_access_plugin_init(plugin *p) { p->init = mod_access_init; p->set_defaults = mod_access_set_defaults; - p->handle_uri_clean = mod_access_uri_handler; + p->handle_uri_clean = mod_access_uri_handler; + p->handle_subrequest_start = mod_access_uri_handler; p->cleanup = mod_access_free; p->data = NULL; diff --git a/src/mod_accesslog.c b/src/mod_accesslog.c index 32570a1..a3516d5 100644 --- a/src/mod_accesslog.c +++ b/src/mod_accesslog.c @@ -507,7 +507,7 @@ SETDEFAULTS_FUNC(log_access_open) { * */ - execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL); + execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, (char *)NULL); log_error_write(srv, __FILE__, __LINE__, "sss", "spawning log-process failed: ", strerror(errno), diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index 624c29f..2e7f339 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -69,7 +69,7 @@ typedef struct fcgi_proc { buffer *unixsocket; /* config.socket + "-" + id */ unsigned port; /* config.port + pno */ - buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */ + buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debugging purposes */ pid_t pid; /* PID of the spawned process (0 if not spawned locally) */ @@ -80,7 +80,7 @@ typedef struct fcgi_proc { size_t requests; /* see max_requests */ struct fcgi_proc *prev, *next; /* see first */ - time_t disabled_until; /* this proc is disabled until, use something else until than */ + time_t disabled_until; /* this proc is disabled until, use something else until then */ int is_local; @@ -88,7 +88,7 @@ typedef struct fcgi_proc { PROC_STATE_UNSET, /* init-phase */ PROC_STATE_RUNNING, /* alive */ PROC_STATE_OVERLOADED, /* listen-queue is full, - don't send something to this proc for the next 2 seconds */ + don't send anything to this proc for the next 2 seconds */ PROC_STATE_DIED_WAIT_FOR_PID, /* */ PROC_STATE_DIED, /* marked as dead, should be restarted */ PROC_STATE_KILLED /* was killed as we don't have the load anymore */ @@ -145,7 +145,7 @@ typedef struct { unsigned short disable_time; /* - * same fastcgi processes get a little bit larger + * some fastcgi processes get a little bit larger * than wanted. max_requests_per_proc kills a * process after a number of handled requests. * @@ -184,7 +184,7 @@ typedef struct { * bin-path is the path to the binary * * check min_procs and max_procs for the number - * of process to start-up + * of process to start up */ buffer *bin_path; @@ -217,7 +217,7 @@ typedef struct { unsigned short mode; /* - * check_local tell you if the phys file is stat()ed + * check_local tells you if the phys file is stat()ed * or not. FastCGI doesn't care if the service is * remote. If the web-server side doesn't contain * the fastcgi-files we should not stat() for them @@ -228,7 +228,7 @@ typedef struct { /* * append PATH_INFO to SCRIPT_FILENAME * - * php needs this if cgi.fix_pathinfo is provied + * php needs this if cgi.fix_pathinfo is provided * */ @@ -247,7 +247,7 @@ typedef struct { num_procs. only if a process is killed max_id waits for the process itself - to die and decrements its afterwards */ + to die and decrements it afterwards */ buffer *strip_request_uri; @@ -826,7 +826,7 @@ static int fcgi_spawn_connection(server *srv, } else { struct hostent *he; - /* set a usefull default */ + /* set a useful default */ fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); @@ -869,7 +869,7 @@ static int fcgi_spawn_connection(server *srv, } if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) { - /* server is not up, spawn in */ + /* server is not up, spawn it */ pid_t child; int val; @@ -1029,10 +1029,11 @@ static int fcgi_spawn_connection(server *srv, "child exited with status", WEXITSTATUS(status), host->bin_path); log_error_write(srv, __FILE__, __LINE__, "s", - "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n" + "If you're trying to run PHP as a FastCGI backend, make sure you're using the FastCGI-enabled version.\n" "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' " - "in the output, NOT (cgi) NOR (cli)\n" - "For more information check http://www.lighttpd.net/documentation/fastcgi.html#preparing-php-as-a-fastcgi-program"); + "in the output, NOT '(cgi)' NOR '(cli)'.\n" + "For more information, check http://trac.lighttpd.net/trac/wiki/Docs%3AModFastCGI#preparing-php-as-a-fastcgi-program" + "If this is PHP on Gentoo, add 'fastcgi' to the USE flags."); } else if (WIFSIGNALED(status)) { log_error_write(srv, __FILE__, __LINE__, "sd", "terminated by signal:", @@ -1040,9 +1041,9 @@ static int fcgi_spawn_connection(server *srv, if (WTERMSIG(status) == 11) { log_error_write(srv, __FILE__, __LINE__, "s", - "to be exact: it seg-fault, crashed, died, ... you get the idea." ); + "to be exact: it segfaulted, crashed, died, ... you get the idea." ); log_error_write(srv, __FILE__, __LINE__, "s", - "If this is PHP try to remove the byte-code caches for now and try again."); + "If this is PHP, try removing the bytecode caches for now and try again."); } } else { log_error_write(srv, __FILE__, __LINE__, "sd", @@ -1066,7 +1067,7 @@ static int fcgi_spawn_connection(server *srv, if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sb", - "(debug) socket is already used, won't spawn:", + "(debug) socket is already used; won't spawn:", proc->connection_name); } } @@ -1508,7 +1509,7 @@ static int fcgi_reconnect(server *srv, handler_ctx *hctx) { * * next step is resetting this attemp and setup a connection again * - * if we have more then 5 reconnects for the same request, die + * if we have more than 5 reconnects for the same request, die * * 2. * @@ -1626,7 +1627,7 @@ typedef enum { CONNECTION_UNSET, CONNECTION_OK, CONNECTION_DELAYED, /* retry after event, take same host */ - CONNECTION_OVERLOADED, /* disable for 1 seconds, take another backend */ + CONNECTION_OVERLOADED, /* disable for 1 second, take another backend */ CONNECTION_DEAD /* disable for 60 seconds, take another backend */ } connection_result_t; @@ -1669,7 +1670,7 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h fcgi_addr_in.sin_family = AF_INET; if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) { log_error_write(srv, __FILE__, __LINE__, "sbs", - "converting IP-adress failed for", host->host, + "converting IP address failed for", host->host, "\nBe sure to specify an IP address here"); return -1; @@ -1694,16 +1695,16 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h errno == EINTR) { if (hctx->conf.debug > 2) { log_error_write(srv, __FILE__, __LINE__, "sb", - "connect delayed, will continue later:", proc->connection_name); + "connect delayed; will continue later:", proc->connection_name); } return CONNECTION_DELAYED; } else if (errno == EAGAIN) { if (hctx->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sbsd", - "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. " - "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections." - "The load for this fastcgi backend", proc->connection_name, "is", proc->load); + "This means that you have more incoming requests than your FastCGI backend can handle in parallel." + "It might help to spawn more FastCGI backends or PHP children; if not, decrease server.max-connections." + "The load for this FastCGI backend", proc->connection_name, "is", proc->load); } return CONNECTION_OVERLOADED; @@ -1881,8 +1882,6 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)); if (!buffer_is_empty(con->authed_user)) { - fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"), CONST_BUF_LEN(con->authed_user)); - /* AUTH_TYPE fix by Troy Kruthoff (tkruthoff@gmail.com) * section 4.1.1 of RFC 3875 (cgi spec) requires the server to set a AUTH_TYPE env * declaring the type of authentication used. (see http://tools.ietf.org/html/rfc3875#page-11) @@ -1896,6 +1895,8 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { char *http_authorization = NULL; data_string *ds; + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"), CONST_BUF_LEN(con->authed_user)); + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) { http_authorization = ds->value->ptr; } @@ -2055,8 +2056,8 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { off_t written = 0; off_t weHave = 0; - /* we announce toWrite octects - * now take all the request_content chunk that we need to fill this request + /* we announce toWrite octets + * now take all the request_content chunks that we need to fill this request * */ b = chunkqueue_get_append_buffer(hctx->wb); @@ -2356,7 +2357,7 @@ static int fastcgi_get_packet(server *srv, handler_ctx *hctx, fastcgi_response_p } if (packet->b->used < packet->len + 1) { - /* we didn't got the full packet */ + /* we didn't get the full packet */ buffer_free(packet->b); return -1; @@ -2439,7 +2440,6 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) { b->used = r + 1; /* one extra for the fake \0 */ b->ptr[b->used - 1] = '\0'; } else { - if (errno == EAGAIN) return 0; log_error_write(srv, __FILE__, __LINE__, "ssdsb", "unexpected end-of-file (perhaps the fastcgi process died):", "pid:", proc->pid, @@ -2558,7 +2558,7 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) { if (host->mode != FCGI_AUTHORIZER || !(con->http_status == 0 || con->http_status == 200)) { - /* send chunk-end if nesseary */ + /* send chunk-end if necessary */ http_chunk_append_mem(srv, con, NULL, 0); joblist_append(srv, con); } @@ -2653,7 +2653,7 @@ static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_h if (proc->state != PROC_STATE_DIED) break; case PROC_STATE_DIED: - /* local proc get restarted by us, + /* local procs get restarted by us, * remote ones hopefully by the admin */ if (proc->is_local) { @@ -2774,7 +2774,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { proc && proc->state != PROC_STATE_RUNNING; proc = proc->next); - /* all childs are dead */ + /* all children are dead */ if (proc == NULL) { hctx->fde_ndx = -1; @@ -2834,7 +2834,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { * -> EAGAIN */ log_error_write(srv, __FILE__, __LINE__, "ssdsd", - "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:", + "backend is overloaded; we'll disable it for 2 seconds and send the request to another backend instead:", "reconnects:", hctx->reconnects, "load:", host->load); @@ -2864,7 +2864,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { } log_error_write(srv, __FILE__, __LINE__, "ssdsd", - "backend died, we disable it for a 5 seconds and send the request to another backend instead:", + "backend died; we'll disable it for 5 seconds and send the request to another backend instead:", "reconnects:", hctx->reconnects, "load:", host->load); @@ -2950,7 +2950,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { if (hctx->wb->bytes_out == 0 && hctx->reconnects < 5) { usleep(10000); /* take away the load of the webserver - * to let the php a chance to restart + * to give the php a chance to restart */ fcgi_reconnect(srv, hctx); @@ -2964,7 +2964,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { * */ - log_error_write(srv, __FILE__, __LINE__, "ssdsd", + log_error_write(srv, __FILE__, __LINE__, "ssosd", "[REPORT ME] connection was dropped after accept(). reconnect() denied:", "write-offset:", hctx->wb->bytes_out, "reconnect attempts:", hctx->reconnects); @@ -3152,9 +3152,9 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { (con->http_status == 200 || con->http_status == 0)) { /* - * If we are here in AUTHORIZER mode then a request for autorizer - * was proceeded already, and status 200 has been returned. We need - * now to handle autorized request. + * If we are here in AUTHORIZER mode then a request for authorizer + * was processed already, and status 200 has been returned. We need + * now to handle authorized request. */ buffer_copy_string_buffer(con->physical.doc_root, host->docroot); @@ -3220,7 +3220,7 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { } if (con->file_started == 0) { - /* nothing has been send out yet, try to use another child */ + /* nothing has been sent out yet, try to use another child */ if (hctx->wb->bytes_out == 0 && hctx->reconnects < 5) { @@ -3270,8 +3270,8 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { hctx->state == FCGI_STATE_WRITE) { /* we are allowed to send something out * - * 1. in a unfinished connect() call - * 2. in a unfinished write() call (long POST request) + * 1. in an unfinished connect() call + * 2. in an unfinished write() call (long POST request) */ return mod_fastcgi_handle_subrequest(srv, con, p); } else { @@ -3286,8 +3286,8 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { if (hctx->state == FCGI_STATE_CONNECT_DELAYED) { /* getoptsock will catch this one (right ?) * - * if we are in connect we might get a EINPROGRESS - * in the first call and a FDEVENT_HUP in the + * if we are in connect we might get an EINPROGRESS + * in the first call and an FDEVENT_HUP in the * second round * * FIXME: as it is a bit ugly. @@ -3485,7 +3485,7 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i return HANDLER_FINISHED; } - /* a note about no handler is not sent yey */ + /* a note about no handler is not sent yet */ extension->note_is_sent = 0; /* @@ -3520,7 +3520,7 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i } /* the prefix is the SCRIPT_NAME, - * everthing from start to the next slash + * everything from start to the next slash * this is important for check-local = "disable" * * if prefix = /admin.fcgi @@ -3630,13 +3630,13 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) { /* perhaps we should kill a connect attempt after 10-15 seconds * - * currently we wait for the TCP timeout which is on Linux 180 seconds + * currently we wait for the TCP timeout which is 180 seconds on Linux * * * */ - /* check all childs if they are still up */ + /* check all children if they are still up */ for (i = 0; i < srv->config_context->used; i++) { plugin_config *conf; @@ -3718,11 +3718,11 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) { if (srv->cur_ts - proc->last_used > host->idle_timeout) { /* a proc is idling for a long time now, - * terminated it */ + * terminate it */ if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssbsd", - "idle-timeout reached, terminating child:", + "idle-timeout reached; terminating child:", "socket:", proc->connection_name, "pid", proc->pid); } diff --git a/src/mod_scgi.c b/src/mod_scgi.c index 1948260..5680091 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -803,7 +803,7 @@ static int scgi_spawn_connection(server *srv, buffer_append_string_buffer(b, host->bin_path); /* exec the cgi */ - execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr); + execle("/bin/sh", "sh", "-c", b->ptr, (char *)NULL, env.ptr); log_error_write(srv, __FILE__, __LINE__, "sbs", "execl failed for:", host->bin_path, strerror(errno)); @@ -2286,7 +2286,7 @@ static handler_t scgi_write_request(server *srv, handler_ctx *hctx) { * */ - log_error_write(srv, __FILE__, __LINE__, "ssdsd", + log_error_write(srv, __FILE__, __LINE__, "ssosd", "[REPORT ME] connection was dropped after accept(). reconnect() denied:", "write-offset:", hctx->wb->bytes_out, "reconnect attempts:", hctx->reconnects); @@ -2536,7 +2536,7 @@ static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents) { return HANDLER_WAIT_FOR_FD; } - log_error_write(srv, __FILE__, __LINE__, "sdsdsd", + log_error_write(srv, __FILE__, __LINE__, "sosdsd", "response not sent, request sent:", hctx->wb->bytes_out, "connection-fd:", con->fd, "fcgi-fd:", hctx->fd); diff --git a/src/mod_ssi.c b/src/mod_ssi.c index e66a6fc..6621f9d 100644 --- a/src/mod_ssi.c +++ b/src/mod_ssi.c @@ -702,7 +702,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, /* close stdin */ close(STDIN_FILENO); - execl("/bin/sh", "sh", "-c", cmd, NULL); + execl("/bin/sh", "sh", "-c", cmd, (char *)NULL); log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd); diff --git a/src/mod_staticfile.c b/src/mod_staticfile.c index 61ff373..e371410 100644 --- a/src/mod_staticfile.c +++ b/src/mod_staticfile.c @@ -25,6 +25,7 @@ typedef struct { array *exclude_ext; + unsigned short etags_used; } plugin_config; typedef struct { @@ -82,6 +83,7 @@ SETDEFAULTS_FUNC(mod_staticfile_set_defaults) { config_values_t cv[] = { { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ + { "static-file.etags", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -94,8 +96,10 @@ SETDEFAULTS_FUNC(mod_staticfile_set_defaults) { s = calloc(1, sizeof(plugin_config)); s->exclude_ext = array_init(); + s->etags_used = 1; cv[0].destination = s->exclude_ext; + cv[1].destination = &(s->etags_used); p->config_storage[i] = s; @@ -114,6 +118,7 @@ static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_ plugin_config *s = p->config_storage[0]; PATCH(exclude_ext); + PATCH(etags_used); /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { @@ -129,7 +134,9 @@ static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_ if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) { PATCH(exclude_ext); - } + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.etags"))) { + PATCH(etags_used); + } } } @@ -446,11 +453,13 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes")); if (allow_caching) { - if (NULL == array_get_element(con->response.headers, "ETag")) { - /* generate e-tag */ - etag_mutate(con->physical.etag, sce->etag); + if (p->conf.etags_used && con->etag_flags != 0 && !buffer_is_empty(sce->etag)) { + if (NULL == array_get_element(con->response.headers, "ETag")) { + /* generate e-tag */ + etag_mutate(con->physical.etag, sce->etag); - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); + } } /* prepare header */ diff --git a/src/mod_status.c b/src/mod_status.c index 2a4003a..e64cb29 100644 --- a/src/mod_status.c +++ b/src/mod_status.c @@ -220,6 +220,7 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c BUFFER_APPEND_STRING_CONST(b, " <style type=\"text/css\">\n" " table.status { border: black solid thin; }\n" + " td { white-space: nowrap; }\n" " td.int { background-color: #f0f0f0; text-align: right }\n" " td.string { background-color: #f0f0f0; text-align: left }\n" " th.status { background-color: black; color: white; font-weight: bold; }\n" @@ -520,6 +521,16 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML); } + if (!buffer_is_empty(c->uri.query)) { + BUFFER_APPEND_STRING_CONST(b, "?"); + buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.query), ENCODING_HTML); + } + + if (!buffer_is_empty(c->request.orig_uri)) { + BUFFER_APPEND_STRING_CONST(b, " ("); + buffer_append_string_encoded(b, CONST_BUF_LEN(c->request.orig_uri), ENCODING_HTML); + BUFFER_APPEND_STRING_CONST(b, ")"); + } BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">"); buffer_append_string_buffer(b, c->physical.path); diff --git a/src/mod_webdav.c b/src/mod_webdav.c index d7bab2f..1432618 100644 --- a/src/mod_webdav.c +++ b/src/mod_webdav.c @@ -1035,7 +1035,7 @@ static int webdav_parse_chunkqueue(server *srv, connection *con, plugin_data *p, } if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) { - log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err); + log_error_write(srv, __FILE__, __LINE__, "sodd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err); } c->offset += weHave; @@ -1053,7 +1053,7 @@ static int webdav_parse_chunkqueue(server *srv, connection *con, plugin_data *p, } if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) { - log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err); + log_error_write(srv, __FILE__, __LINE__, "sodd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err); } c->offset += weHave; diff --git a/src/proc_open.c b/src/proc_open.c index ad2650d..1f55b61 100644 --- a/src/proc_open.c +++ b/src/proc_open.c @@ -255,7 +255,7 @@ int proc_open(proc_handler_t *proc, const char *command) { */ proc_close_parents(proc); - execl(shell, shell, "-c", command, NULL); + execl(shell, shell, "-c", command, (char *)NULL); _exit(127); } else if (child < 0) { diff --git a/src/request.c b/src/request.c index f76252e..92660a0 100644 --- a/src/request.c +++ b/src/request.c @@ -284,8 +284,6 @@ int http_request_parse(server *srv, connection *con) { int done = 0; - data_string *ds = NULL; - /* * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$" * Option : "^([-a-zA-Z]+): (.+)$" @@ -715,12 +713,24 @@ int http_request_parse(server *srv, connection *con) { switch(*cur) { case '\r': if (con->parse_request->ptr[i+1] == '\n') { + data_string *ds = NULL; + /* End of Headerline */ con->parse_request->ptr[i] = '\0'; con->parse_request->ptr[i+1] = '\0'; if (in_folding) { - if (!ds) { + buffer *key_b; + /** + * we use a evil hack to handle the line-folding + * + * As array_insert_unique() deletes 'ds' in the case of a duplicate + * ds points somewhere and we get a evil crash. As a solution we keep the old + * "key" and get the current value from the hash and append us + * + * */ + + if (!key || !key_len) { /* 400 */ if (srv->srvconf.log_request_header_on_error) { @@ -737,7 +747,15 @@ int http_request_parse(server *srv, connection *con) { con->response.keep_alive = 0; return 0; } - buffer_append_string(ds->value, value); + + key_b = buffer_init(); + buffer_copy_string_len(key_b, key, key_len); + + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, key_b->ptr))) { + buffer_append_string(ds->value, value); + } + + buffer_free(key_b); } else { int s_len; key = con->parse_request->ptr + first; @@ -969,7 +987,12 @@ int http_request_parse(server *srv, connection *con) { first = i+1; is_key = 1; value = 0; - key_len = 0; +#if 0 + /** + * for Bug 1230 keep the key_len a live + */ + key_len = 0; +#endif in_folding = 0; } else { if (srv->srvconf.log_request_header_on_error) { diff --git a/src/server.c b/src/server.c index 37b7cb4..7eaae3e 100644 --- a/src/server.c +++ b/src/server.c @@ -775,6 +775,22 @@ int main (int argc, char **argv) { return -1; } + /** + * we are not root can can't increase the fd-limit, but we can reduce it + */ + if (srv->srvconf.max_fds && srv->srvconf.max_fds < rlim.rlim_cur) { + /* set rlimits */ + + rlim.rlim_cur = srv->srvconf.max_fds; + + if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) { + log_error_write(srv, __FILE__, __LINE__, + "ss", "couldn't set 'max filedescriptors'", + strerror(errno)); + return -1; + } + } + if (srv->event_handler == FDEVENT_HANDLER_SELECT) { srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200; } else { diff --git a/src/spawn-fcgi.c b/src/spawn-fcgi.c index c40d8f9..0aaac14 100644 --- a/src/spawn-fcgi.c +++ b/src/spawn-fcgi.c @@ -169,7 +169,7 @@ int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const strcat(b, appPath); /* exec the cgi */ - execl("/bin/sh", "sh", "-c", b, NULL); + execl("/bin/sh", "sh", "-c", b, (char *)NULL); exit(errno); diff --git a/src/stat_cache.c b/src/stat_cache.c index 283ead9..6fbf1ba 100644 --- a/src/stat_cache.c +++ b/src/stat_cache.c @@ -608,14 +608,14 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ break; } } - etag_create(sce->etag, &(sce->st)); + etag_create(sce->etag, &(sce->st), con->etag_flags); #ifdef HAVE_XATTR - if (buffer_is_empty(sce->content_type)) { + if (con->conf.use_xattr && buffer_is_empty(sce->content_type)) { stat_cache_attr_get(sce->content_type, name->ptr); } #endif } else if (S_ISDIR(st.st_mode)) { - etag_create(sce->etag, &(sce->st)); + etag_create(sce->etag, &(sce->st), con->etag_flags); } #ifdef HAVE_FAM_H |