fix race in dynamic handler configs (reentrancy) (fixes #2774)

(thx tobbe303)

x-ref:
  "CGI request not handled"
  https://redmine.lighttpd.net/issues/2774
personal/stbuehler/mod-csrf
Glenn Strauss 2016-11-28 12:39:37 -05:00
parent df61f19daf
commit 5bf5e1adcc
5 changed files with 84 additions and 67 deletions

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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("</D:activelock>\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("<D:lockdiscovery>\n</D:lockdiscovery>\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("<D:supportedlock>"));
@ -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("<D:response>\n"));
buffer_append_string_len(b,CONST_STR_LEN("<D:href>"));
@ -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("<D:response>\n"));
buffer_append_string_len(b,CONST_STR_LEN("<D:href>"));
@ -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;