From 5bf5e1adccd87846e9884a1a013f4d308c4c3d91 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Mon, 28 Nov 2016 12:39:37 -0500 Subject: [PATCH] fix race in dynamic handler configs (reentrancy) (fixes #2774) (thx tobbe303) x-ref: "CGI request not handled" https://redmine.lighttpd.net/issues/2774 --- src/mod_cgi.c | 8 ++-- src/mod_fastcgi.c | 5 --- src/mod_proxy.c | 19 ++++---- src/mod_scgi.c | 9 ++-- src/mod_webdav.c | 110 +++++++++++++++++++++++++++------------------- 5 files changed, 84 insertions(+), 67 deletions(-) diff --git a/src/mod_cgi.c b/src/mod_cgi.c index 9f920884..0b23dc71 100644 --- a/src/mod_cgi.c +++ b/src/mod_cgi.c @@ -95,6 +95,7 @@ typedef struct { buffer *response; buffer *response_header; + plugin_config conf; } handler_ctx; static handler_ctx * cgi_handler_ctx_init(void) { @@ -562,10 +563,10 @@ static int cgi_demux_response(server *srv, handler_ctx *hctx) { } } - if (p->conf.xsendfile_allow) { + if (hctx->conf.xsendfile_allow) { data_string *ds; if (NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-Sendfile"))) { - http_response_xsendfile(srv, con, ds->value, p->conf.xsendfile_docroot); + http_response_xsendfile(srv, con, ds->value, hctx->conf.xsendfile_docroot); return FDEVENT_HANDLED_FINISHED; } } @@ -1335,6 +1336,7 @@ URIHANDLER_FUNC(cgi_is_handled) { handler_ctx *hctx = cgi_handler_ctx_init(); hctx->remote_conn = con; hctx->plugin_data = p; + memcpy(&hctx->conf, &p->conf, sizeof(plugin_config)); con->plugin_ctx[p->id] = hctx; con->mode = p->id; } @@ -1442,7 +1444,7 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { } if (-1 == hctx->fd) { - buffer *handler = cgi_get_handler(p->conf.cgi, con->physical.path); + buffer *handler = cgi_get_handler(hctx->conf.cgi, con->physical.path); if (!handler) return HANDLER_GO_ON; /*(should not happen; checked in cgi_is_handled())*/ if (cgi_create_env(srv, con, p, hctx, handler)) { con->http_status = 500; diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index db74c5f8..ce47cdae 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -305,8 +305,6 @@ typedef struct { buffer *fcgi_env; - buffer *path; - buffer *statuskey; plugin_config **config_storage; @@ -701,8 +699,6 @@ INIT_FUNC(mod_fastcgi_init) { p->fcgi_env = buffer_init(); - p->path = buffer_init(); - p->statuskey = buffer_init(); return p; @@ -715,7 +711,6 @@ FREE_FUNC(mod_fastcgi_free) { UNUSED(srv); buffer_free(p->fcgi_env); - buffer_free(p->path); buffer_free(p->statuskey); if (p->config_storage) { diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 9b0fd21d..fa9a343e 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -348,7 +348,7 @@ static void proxy_backend_close(server *srv, handler_ctx *hctx) { } } -static data_proxy * mod_proxy_extension_host_get(server *srv, connection *con, plugin_data *p, data_array *extension) { +static data_proxy * mod_proxy_extension_host_get(server *srv, connection *con, data_array *extension, proxy_balance_t balance, int debug) { unsigned long last_max = ULONG_MAX; int max_usage = INT_MAX; int ndx = -1; @@ -360,11 +360,11 @@ static data_proxy * mod_proxy_extension_host_get(server *srv, connection *con, p } else { ndx = 0; } - } else if (extension->value->used != 0) switch(p->conf.balance) { + } else if (extension->value->used != 0) switch(balance) { case PROXY_BALANCE_HASH: /* hash balancing */ - if (p->conf.debug) { + if (debug) { log_error_write(srv, __FILE__, __LINE__, "sd", "proxy - used hash balancing, hosts:", extension->value->used); } @@ -379,7 +379,7 @@ static data_proxy * mod_proxy_extension_host_get(server *srv, connection *con, p generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */ generate_crc32c(CONST_BUF_LEN(con->uri.authority)); - if (p->conf.debug) { + if (debug) { log_error_write(srv, __FILE__, __LINE__, "sbbbd", "proxy - election:", con->uri.path, @@ -399,7 +399,7 @@ static data_proxy * mod_proxy_extension_host_get(server *srv, connection *con, p break; case PROXY_BALANCE_FAIR: /* fair balancing */ - if (p->conf.debug) { + if (debug) { log_error_write(srv, __FILE__, __LINE__, "s", "proxy - used fair balancing"); } @@ -421,7 +421,7 @@ static data_proxy * mod_proxy_extension_host_get(server *srv, connection *con, p data_proxy *host; /* round robin */ - if (p->conf.debug) { + if (debug) { log_error_write(srv, __FILE__, __LINE__, "s", "proxy - used round-robin balancing"); } @@ -464,7 +464,7 @@ static data_proxy * mod_proxy_extension_host_get(server *srv, connection *con, p if (ndx != -1) { data_proxy *host = (data_proxy *)extension->value->data[ndx]; - if (p->conf.debug) { + if (debug) { log_error_write(srv, __FILE__, __LINE__, "sbd", "proxy - found a host", host->host, host->port); @@ -505,7 +505,7 @@ static void proxy_connection_close(server *srv, handler_ctx *hctx) { static handler_t proxy_reconnect(server *srv, handler_ctx *hctx) { proxy_backend_close(srv, hctx); - hctx->host = mod_proxy_extension_host_get(srv, hctx->remote_conn, hctx->plugin_data, hctx->ext); + hctx->host = mod_proxy_extension_host_get(srv, hctx->remote_conn, hctx->ext, hctx->conf.balance, (int)hctx->conf.debug); if (NULL == hctx->host) return HANDLER_FINISHED; hctx->state = PROXY_STATE_INIT; @@ -1271,7 +1271,7 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p return HANDLER_GO_ON; } - host = mod_proxy_extension_host_get(srv, con, p, extension); + host = mod_proxy_extension_host_get(srv, con, extension, p->conf.balance, (int)p->conf.debug); if (NULL == host) { return HANDLER_FINISHED; } @@ -1293,6 +1293,7 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p hctx->host = host; hctx->ext = extension; + hctx->conf.balance = p->conf.balance; hctx->conf.debug = p->conf.debug; con->plugin_ctx[p->id] = hctx; diff --git a/src/mod_scgi.c b/src/mod_scgi.c index ffc28f73..9b827c3b 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -291,7 +291,6 @@ typedef struct { buffer *scgi_env; - buffer *path; buffer *parse_response; plugin_config **config_storage; @@ -545,7 +544,6 @@ INIT_FUNC(mod_scgi_init) { p->scgi_env = buffer_init(); - p->path = buffer_init(); p->parse_response = buffer_init(); return p; @@ -558,7 +556,6 @@ FREE_FUNC(mod_scgi_free) { UNUSED(srv); buffer_free(p->scgi_env); - buffer_free(p->path); buffer_free(p->parse_response); if (p->config_storage) { @@ -1606,7 +1603,7 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { http_cgi_opts opts = { 0, 0, host->docroot, NULL }; - http_cgi_header_append_cb scgi_env_add = p->conf.proto == LI_PROTOCOL_SCGI + http_cgi_header_append_cb scgi_env_add = hctx->conf.proto == LI_PROTOCOL_SCGI ? scgi_env_add_scgi : scgi_env_add_uwsgi; @@ -1617,7 +1614,7 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { return -1; } - if (p->conf.proto == LI_PROTOCOL_SCGI) { + if (hctx->conf.proto == LI_PROTOCOL_SCGI) { scgi_env_add(p->scgi_env, CONST_STR_LEN("SCGI"), CONST_STR_LEN("1")); b = buffer_init(); buffer_append_int(b, buffer_string_length(p->scgi_env)); @@ -2759,6 +2756,7 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i hctx->ext = extension; /*hctx->conf.exts = p->conf.exts;*/ + hctx->conf.proto = p->conf.proto; hctx->conf.debug = p->conf.debug; con->plugin_ctx[p->id] = hctx; @@ -2816,6 +2814,7 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i hctx->ext = extension; /*hctx->conf.exts = p->conf.exts;*/ + hctx->conf.proto = p->conf.proto; hctx->conf.debug = p->conf.debug; con->plugin_ctx[p->id] = hctx; diff --git a/src/mod_webdav.c b/src/mod_webdav.c index afb4b32d..d98f35c4 100644 --- a/src/mod_webdav.c +++ b/src/mod_webdav.c @@ -89,6 +89,10 @@ typedef struct { plugin_config conf; } plugin_data; +typedef struct { + plugin_config conf; +} handler_ctx; + /* init the plugin data */ INIT_FUNC(mod_webdav_init) { plugin_data *p; @@ -533,7 +537,7 @@ static int webdav_gen_response_status_tag(server *srv, connection *con, physical return 0; } -static int webdav_delete_file(server *srv, connection *con, plugin_data *p, physical *dst, buffer *b) { +static int webdav_delete_file(server *srv, connection *con, handler_ctx *hctx, physical *dst, buffer *b) { int status = 0; /* try to unlink it */ @@ -551,7 +555,7 @@ static int webdav_delete_file(server *srv, connection *con, plugin_data *p, phys webdav_gen_response_status_tag(srv, con, dst, status, b); } else { #ifdef USE_PROPPATCH - sqlite3_stmt *stmt = p->conf.stmt_delete_uri; + sqlite3_stmt *stmt = hctx->conf.stmt_delete_uri; if (!stmt) { status = 403; @@ -577,7 +581,7 @@ static int webdav_delete_file(server *srv, connection *con, plugin_data *p, phys return (status != 0); } -static int webdav_delete_dir(server *srv, connection *con, plugin_data *p, physical *dst, buffer *b) { +static int webdav_delete_dir(server *srv, connection *con, handler_ctx *hctx, physical *dst, buffer *b) { DIR *dir; int have_multi_status = 0; physical d; @@ -609,7 +613,7 @@ static int webdav_delete_dir(server *srv, connection *con, plugin_data *p, physi if (-1 == stat(d.path->ptr, &st)) { /* don't about it yet, rmdir will fail too */ } else if (S_ISDIR(st.st_mode)) { - have_multi_status = webdav_delete_dir(srv, con, p, &d, b); + have_multi_status = webdav_delete_dir(srv, con, hctx, &d, b); /* try to unlink it */ if (-1 == rmdir(d.path->ptr)) { @@ -629,7 +633,7 @@ static int webdav_delete_dir(server *srv, connection *con, plugin_data *p, physi webdav_gen_response_status_tag(srv, con, &d, status, b); } else { #ifdef USE_PROPPATCH - sqlite3_stmt *stmt = p->conf.stmt_delete_uri; + sqlite3_stmt *stmt = hctx->conf.stmt_delete_uri; if (stmt) { sqlite3_reset(stmt); @@ -647,7 +651,7 @@ static int webdav_delete_dir(server *srv, connection *con, plugin_data *p, physi #endif } } else { - have_multi_status = webdav_delete_file(srv, con, p, &d, b); + have_multi_status = webdav_delete_file(srv, con, hctx, &d, b); } } closedir(dir); @@ -670,7 +674,7 @@ static int webdav_delete_dir(server *srv, connection *con, plugin_data *p, physi #define O_BINARY 0 #endif -static int webdav_copy_file(server *srv, connection *con, plugin_data *p, physical *src, physical *dst, int overwrite) { +static int webdav_copy_file(server *srv, connection *con, handler_ctx *hctx, physical *src, physical *dst, int overwrite) { char *data; ssize_t rd, wr, offset; int status = 0, ifd, ofd; @@ -729,7 +733,7 @@ static int webdav_copy_file(server *srv, connection *con, plugin_data *p, physic #ifdef USE_PROPPATCH if (0 == status) { /* copy worked fine, copy connected properties */ - sqlite3_stmt *stmt = p->conf.stmt_copy_uri; + sqlite3_stmt *stmt = hctx->conf.stmt_copy_uri; if (stmt) { sqlite3_reset(stmt); @@ -754,7 +758,7 @@ static int webdav_copy_file(server *srv, connection *con, plugin_data *p, physic return status; } -static int webdav_copy_dir(server *srv, connection *con, plugin_data *p, physical *src, physical *dst, int overwrite) { +static int webdav_copy_dir(server *srv, connection *con, handler_ctx *hctx, physical *src, physical *dst, int overwrite) { DIR *srcdir; int status = 0; @@ -801,9 +805,9 @@ static int webdav_copy_dir(server *srv, connection *con, plugin_data *p, physica /* WTH ? */ } else { #ifdef USE_PROPPATCH - sqlite3_stmt *stmt = p->conf.stmt_copy_uri; + sqlite3_stmt *stmt = hctx->conf.stmt_copy_uri; - if (0 != (status = webdav_copy_dir(srv, con, p, &s, &d, overwrite))) { + if (0 != (status = webdav_copy_dir(srv, con, hctx, &s, &d, overwrite))) { break; } /* directory is copied, copy the properties too */ @@ -828,7 +832,7 @@ static int webdav_copy_dir(server *srv, connection *con, plugin_data *p, physica } } else if (S_ISREG(st.st_mode)) { /* a plain file */ - if (0 != (status = webdav_copy_file(srv, con, p, &s, &d, overwrite))) { + if (0 != (status = webdav_copy_file(srv, con, hctx, &s, &d, overwrite))) { break; } } @@ -883,9 +887,9 @@ static void webdav_activelock(buffer *b, buffer_append_string_len(b, CONST_STR_LEN("\n")); } -static void webdav_get_live_property_lockdiscovery(server *srv, connection *con, plugin_data *p, physical *dst, buffer *b) { +static void webdav_get_live_property_lockdiscovery(server *srv, connection *con, handler_ctx *hctx, physical *dst, buffer *b) { - sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri; + sqlite3_stmt *stmt = hctx->conf.stmt_read_lock_by_uri; if (!stmt) { /*(should not happen)*/ buffer_append_string_len(b, CONST_STR_LEN("\n\n")); return; @@ -923,11 +927,11 @@ static void webdav_get_live_property_lockdiscovery(server *srv, connection *con, } #endif -static int webdav_get_live_property(server *srv, connection *con, plugin_data *p, physical *dst, char *prop_name, buffer *b) { +static int webdav_get_live_property(server *srv, connection *con, handler_ctx *hctx, physical *dst, char *prop_name, buffer *b) { stat_cache_entry *sce = NULL; int found = 0; - UNUSED(p); + UNUSED(hctx); if (HANDLER_ERROR != (stat_cache_get_entry(srv, con, dst->path, &sce))) { char ctime_buf[] = "2005-08-18T07:27:16Z"; @@ -992,7 +996,7 @@ static int webdav_get_live_property(server *srv, connection *con, plugin_data *p found = 1; #ifdef USE_LOCKS } else if (0 == strcmp(prop_name, "lockdiscovery")) { - webdav_get_live_property_lockdiscovery(srv, con, p, dst, b); + webdav_get_live_property_lockdiscovery(srv, con, hctx, dst, b); found = 1; } else if (0 == strcmp(prop_name, "supportedlock")) { buffer_append_string_len(b,CONST_STR_LEN("")); @@ -1009,14 +1013,14 @@ static int webdav_get_live_property(server *srv, connection *con, plugin_data *p return found ? 0 : -1; } -static int webdav_get_property(server *srv, connection *con, plugin_data *p, physical *dst, char *prop_name, char *prop_ns, buffer *b) { +static int webdav_get_property(server *srv, connection *con, handler_ctx *hctx, physical *dst, char *prop_name, char *prop_ns, buffer *b) { if (0 == strcmp(prop_ns, "DAV:")) { /* a local 'live' property */ - return webdav_get_live_property(srv, con, p, dst, prop_name, b); + return webdav_get_live_property(srv, con, hctx, dst, prop_name, b); } else { int found = 0; #ifdef USE_PROPPATCH - sqlite3_stmt *stmt = p->conf.stmt_select_prop; + sqlite3_stmt *stmt = hctx->conf.stmt_select_prop; if (stmt) { /* perhaps it is in sqlite3 */ @@ -1081,7 +1085,7 @@ typedef struct { size_t size; } webdav_properties; -static int webdav_get_props(server *srv, connection *con, plugin_data *p, physical *dst, webdav_properties *props, buffer *b_200, buffer *b_404) { +static int webdav_get_props(server *srv, connection *con, handler_ctx *hctx, physical *dst, webdav_properties *props, buffer *b_200, buffer *b_404) { size_t i; if (props && props->used) { @@ -1090,7 +1094,7 @@ static int webdav_get_props(server *srv, connection *con, plugin_data *p, physic prop = props->ptr[i]; - if (0 != webdav_get_property(srv, con, p, + if (0 != webdav_get_property(srv, con, hctx, dst, prop->prop, prop->ns, b_200)) { webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404); } @@ -1098,7 +1102,7 @@ static int webdav_get_props(server *srv, connection *con, plugin_data *p, physic } else { for (i = 0; live_properties[i].prop; i++) { /* a local 'live' property */ - webdav_get_live_property(srv, con, p, dst, live_properties[i].prop, b_200); + webdav_get_live_property(srv, con, hctx, dst, live_properties[i].prop, b_200); } } @@ -1106,7 +1110,7 @@ static int webdav_get_props(server *srv, connection *con, plugin_data *p, physic } #ifdef USE_PROPPATCH -static int webdav_parse_chunkqueue(server *srv, connection *con, plugin_data *p, chunkqueue *cq, xmlDoc **ret_xml) { +static int webdav_parse_chunkqueue(server *srv, connection *con, handler_ctx *hctx, chunkqueue *cq, xmlDoc **ret_xml) { xmlParserCtxtPtr ctxt; xmlDoc *xml; int res; @@ -1178,7 +1182,7 @@ static int webdav_parse_chunkqueue(server *srv, connection *con, plugin_data *p, if (weHave > weWant) weHave = weWant; - if (p->conf.log_xml) { + if (hctx->conf.log_xml) { log_error_write(srv, __FILE__, __LINE__, "ss", "XML-request-body:", c->mem->ptr + c->offset); } @@ -1248,7 +1252,7 @@ static int webdav_lockdiscovery(server *srv, connection *con, * * */ -static int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) { +static int webdav_has_lock(server *srv, connection *con, handler_ctx *hctx, buffer *uri) { int has_lock = 1; #ifdef USE_LOCKS @@ -1279,7 +1283,7 @@ static int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer /* we didn't provided a lock-token -> */ /* if the resource is locked -> 423 */ - sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri; + sqlite3_stmt *stmt = hctx->conf.stmt_read_lock_by_uri; sqlite3_reset(stmt); @@ -1294,7 +1298,7 @@ static int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer #else UNUSED(srv); UNUSED(con); - UNUSED(p); + UNUSED(pconf); UNUSED(uri); #endif @@ -1304,6 +1308,7 @@ static int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { plugin_data *p = p_d; + handler_ctx *hctx = con->plugin_ctx[p->id]; buffer *b; DIR *dir; data_string *ds; @@ -1316,7 +1321,8 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { UNUSED(srv); - if (!p->conf.enabled) return HANDLER_GO_ON; + if (NULL == hctx) return HANDLER_GO_ON; + if (!hctx->conf.enabled) return HANDLER_GO_ON; /* physical path is setup */ if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON; @@ -1362,7 +1368,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { if (r != HANDLER_GO_ON) return r; } - if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) { + if (1 == webdav_parse_chunkqueue(srv, con, hctx, con->request_content_queue, &xml)) { xmlNode *rootnode = xmlDocGetRootElement(xml); force_assert(rootnode); @@ -1462,7 +1468,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { { /* Depth: 0 or Depth: 1 */ - webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404); + webdav_get_props(srv, con, hctx, &(con->physical), req_props, prop_200, prop_404); buffer_append_string_len(b,CONST_STR_LEN("\n")); buffer_append_string_len(b,CONST_STR_LEN("")); @@ -1528,7 +1534,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { buffer_reset(prop_200); buffer_reset(prop_404); - webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404); + webdav_get_props(srv, con, hctx, &d, req_props, prop_200, prop_404); buffer_append_string_len(b,CONST_STR_LEN("\n")); buffer_append_string_len(b,CONST_STR_LEN("")); @@ -1644,7 +1650,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { } /* does the client have a lock for this connection ? */ - if (!webdav_has_lock(srv, con, p, con->uri.path)) { + if (!webdav_has_lock(srv, con, hctx, con->uri.path)) { con->http_status = 423; return HANDLER_FINISHED; } @@ -1670,7 +1676,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { multi_status_resp = buffer_init(); - if (webdav_delete_dir(srv, con, p, &(con->physical), multi_status_resp)) { + if (webdav_delete_dir(srv, con, hctx, &(con->physical), multi_status_resp)) { /* we got an error somewhere in between, build a 207 */ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\"")); @@ -1743,7 +1749,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { /* is a exclusive lock set on the source */ /* (check for lock once before potentially reading large input) */ - if (0 == cq->bytes_in && !webdav_has_lock(srv, con, p, con->uri.path)) { + if (0 == cq->bytes_in && !webdav_has_lock(srv, con, hctx, con->uri.path)) { con->http_status = 423; return HANDLER_FINISHED; } @@ -1933,7 +1939,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { /* is a exclusive lock set on the source */ if (con->request.http_method == HTTP_METHOD_MOVE) { - if (!webdav_has_lock(srv, con, p, con->uri.path)) { + if (!webdav_has_lock(srv, con, hctx, con->uri.path)) { con->http_status = 423; return HANDLER_FINISHED; } @@ -2118,13 +2124,13 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { } /* copy the content of src to dest */ - if (0 != (r = webdav_copy_dir(srv, con, p, &(con->physical), &(p->physical), overwrite))) { + if (0 != (r = webdav_copy_dir(srv, con, hctx, &(con->physical), &(p->physical), overwrite))) { con->http_status = r; return HANDLER_FINISHED; } if (con->request.http_method == HTTP_METHOD_MOVE) { b = buffer_init(); - webdav_delete_dir(srv, con, p, &(con->physical), b); /* content */ + webdav_delete_dir(srv, con, hctx, &(con->physical), b); /* content */ buffer_free(b); rmdir(con->physical.path->ptr); @@ -2137,7 +2143,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { int destdir = 0; /* does the client have a lock for this connection ? */ - if (!webdav_has_lock(srv, con, p, p->uri.path)) { + if (!webdav_has_lock(srv, con, hctx, p->uri.path)) { con->http_status = 423; return HANDLER_FINISHED; } @@ -2205,7 +2211,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { /* rename failed, fall back to COPY + DELETE */ } - if (0 != (r = webdav_copy_file(srv, con, p, &(con->physical), &(p->physical), overwrite))) { + if (0 != (r = webdav_copy_file(srv, con, hctx, &(con->physical), &(p->physical), overwrite))) { con->http_status = r; return HANDLER_FINISHED; @@ -2213,7 +2219,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { if (con->request.http_method == HTTP_METHOD_MOVE) { b = buffer_init(); - webdav_delete_file(srv, con, p, &(con->physical), b); + webdav_delete_file(srv, con, hctx, &(con->physical), b); buffer_free(b); } } @@ -2226,7 +2232,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { return HANDLER_FINISHED; } - if (!webdav_has_lock(srv, con, p, con->uri.path)) { + if (!webdav_has_lock(srv, con, hctx, con->uri.path)) { con->http_status = 423; return HANDLER_FINISHED; } @@ -2254,7 +2260,7 @@ SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { if (r != HANDLER_GO_ON) return r; } - if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) { + if (1 == webdav_parse_chunkqueue(srv, con, hctx, con->request_content_queue, &xml)) { xmlNode *rootnode = xmlDocGetRootElement(xml); if (0 == xmlStrcmp(rootnode->name, BAD_CAST "propertyupdate")) { @@ -2451,7 +2457,7 @@ propmatch_cleanup: } } - if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) { + if (1 == webdav_parse_chunkqueue(srv, con, hctx, con->request_content_queue, &xml)) { xmlNode *rootnode = xmlDocGetRootElement(xml); force_assert(rootnode); @@ -2735,10 +2741,14 @@ PHYSICALPATH_FUNC(mod_webdav_physical_handler) { case HTTP_METHOD_MKCOL: case HTTP_METHOD_DELETE: case HTTP_METHOD_LOCK: - case HTTP_METHOD_UNLOCK: + case HTTP_METHOD_UNLOCK: { + handler_ctx *hctx = calloc(1, sizeof(*hctx)); + memcpy(&hctx->conf, &p->conf, sizeof(plugin_config)); + con->plugin_ctx[p->id] = hctx; con->conf.stream_request_body = 0; con->mode = p->id; break; + } default: break; } @@ -2746,6 +2756,15 @@ PHYSICALPATH_FUNC(mod_webdav_physical_handler) { return HANDLER_GO_ON; } +static handler_t mod_webdav_connection_reset(server *srv, connection *con, void *p_d) { + plugin_data *p = p_d; + handler_ctx *hctx = con->plugin_ctx[p->id]; + if (hctx) free(hctx); + + UNUSED(srv); + return HANDLER_GO_ON; +} + /* this function is called at dlopen() time and inits the callbacks */ @@ -2758,6 +2777,7 @@ int mod_webdav_plugin_init(plugin *p) { p->handle_uri_clean = mod_webdav_uri_handler; p->handle_physical = mod_webdav_physical_handler; p->handle_subrequest = mod_webdav_subrequest_handler; + p->connection_reset = mod_webdav_connection_reset; p->set_defaults = mod_webdav_set_defaults; p->cleanup = mod_webdav_free;