diff options
author | Graham Leggett <minfrin@apache.org> | 2020-06-29 16:21:52 +0000 |
---|---|---|
committer | Graham Leggett <minfrin@apache.org> | 2020-06-29 16:21:52 +0000 |
commit | b1b9013a4c7e846ca750e99f57dd41afbe6c168b (patch) | |
tree | 014b66ec8c22d6a0cbaec6507727762d6ee7db1a /modules/dav | |
parent | a1ffe6bfede1f31cce12527e1c7a62642beafc6e (diff) | |
download | httpd-b1b9013a4c7e846ca750e99f57dd41afbe6c168b.tar.gz |
mod_dav: Add method_precondition hook. WebDAV extensions define
conditions that must exist before a WebDAV method can be executed.
This hook allows a WebDAV extension to verify these preconditions.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1879339 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/dav')
-rw-r--r-- | modules/dav/main/mod_dav.c | 197 | ||||
-rw-r--r-- | modules/dav/main/mod_dav.h | 26 |
2 files changed, 205 insertions, 18 deletions
diff --git a/modules/dav/main/mod_dav.c b/modules/dav/main/mod_dav.c index 1abf5b9cd6..3d8393ff31 100644 --- a/modules/dav/main/mod_dav.c +++ b/modules/dav/main/mod_dav.c @@ -874,7 +874,13 @@ static int dav_method_get(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); - if (!resource->exists) { + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; } @@ -921,6 +927,12 @@ static int dav_method_post(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + /* Note: depth == 0. Implies no need for a multistatus response. */ if ((err = dav_validate_request(r, resource, 0, NULL, NULL, DAV_VALIDATE_RESOURCE, NULL)) != NULL) { @@ -955,6 +967,12 @@ static int dav_method_put(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + /* If not a file or collection resource, PUT not allowed */ if (resource->type != DAV_RESOURCE_TYPE_REGULAR && resource->type != DAV_RESOURCE_TYPE_WORKING) { @@ -1239,6 +1257,13 @@ static int dav_method_delete(request_rec *r) &resource); if (err != NULL) return dav_handle_err(r, err, NULL); + + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -1686,6 +1711,12 @@ static int dav_method_options(request_rec *r) } /* note: doc == NULL if no request body */ + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (doc && !dav_validate_root(doc, "options")) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00584) "The \"options\" element was not found."); @@ -2101,6 +2132,17 @@ static int dav_method_propfind(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + if ((result = ap_xml_parse_input(r, &doc)) != OK) { + return result; + } + /* note: doc == NULL if no request body */ + + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (dav_get_resource_state(r, resource) == DAV_RESOURCE_NULL) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -2128,11 +2170,6 @@ static int dav_method_propfind(request_rec *r) } } - if ((result = ap_xml_parse_input(r, &doc)) != OK) { - return result; - } - /* note: doc == NULL if no request body */ - if (doc && !dav_validate_root(doc, "propfind")) { /* This supplies additional information for the default message. */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00585) @@ -2378,16 +2415,23 @@ static int dav_method_proppatch(request_rec *r) &resource); if (err != NULL) return dav_handle_err(r, err, NULL); - if (!resource->exists) { - /* Apache will supply a default error for this. */ - return HTTP_NOT_FOUND; - } if ((result = ap_xml_parse_input(r, &doc)) != OK) { return result; } /* note: doc == NULL if no request body */ + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + + if (!resource->exists) { + /* Apache will supply a default error for this. */ + return HTTP_NOT_FOUND; + } + if (doc == NULL || !dav_validate_root(doc, "propertyupdate")) { /* This supplies additional information for the default message. */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00587) @@ -2594,6 +2638,12 @@ static int dav_method_mkcol(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (resource->exists) { /* oops. something was already there! */ @@ -2723,6 +2773,12 @@ static int dav_method_copymove(request_rec *r, int is_move) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -2789,6 +2845,12 @@ static int dav_method_copymove(request_rec *r, int is_move) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, resnew, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + /* are the two resources handled by the same repository? */ if (resource->hooks != resnew->hooks) { /* ### this message exposes some backend config, but screw it... */ @@ -3151,6 +3213,12 @@ static int dav_method_lock(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + /* Check if parent collection exists */ if ((err = resource->hooks->get_parent_resource(resource, &parent)) != NULL) { /* ### add a higher-level description? */ @@ -3350,6 +3418,12 @@ static int dav_method_unlock(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + resource_state = dav_get_resource_state(r, resource); /* @@ -3409,15 +3483,21 @@ static int dav_method_vsn_control(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); - /* remember the pre-creation resource state */ - resource_state = dav_get_resource_state(r, resource); - /* parse the request body (may be a version-control element) */ if ((result = ap_xml_parse_input(r, &doc)) != OK) { return result; } /* note: doc == NULL if no request body */ + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + + /* remember the pre-creation resource state */ + resource_state = dav_get_resource_state(r, resource); + if (doc != NULL) { const apr_xml_elem *child; apr_size_t tsize; @@ -3662,6 +3742,12 @@ static int dav_method_checkout(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -3738,6 +3824,12 @@ static int dav_method_uncheckout(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -3815,6 +3907,12 @@ static int dav_method_checkin(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -3936,6 +4034,12 @@ static int dav_method_update(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -4081,11 +4185,23 @@ static int dav_method_label(request_rec *r) if (vsn_hooks == NULL || vsn_hooks->add_label == NULL) return DECLINED; + /* parse the request body */ + if ((result = ap_xml_parse_input(r, &doc)) != OK) { + return result; + } + /* Ask repository module to resolve the resource */ err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */, &resource); if (err != NULL) return dav_handle_err(r, err, NULL); + + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -4097,11 +4213,6 @@ static int dav_method_label(request_rec *r) return HTTP_BAD_REQUEST; } - /* parse the request body */ - if ((result = ap_xml_parse_input(r, &doc)) != OK) { - return result; - } - if (doc == NULL || !dav_validate_root(doc, "label")) { /* This supplies additional information for the default message. */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00610) @@ -4261,6 +4372,12 @@ static int dav_method_report(request_rec *r) return dav_handle_err(r, err, NULL); } + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -4331,6 +4448,12 @@ static int dav_method_make_workspace(request_rec *r) return result; } + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (doc == NULL || !dav_validate_root(doc, "mkworkspace")) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00615) @@ -4390,6 +4513,12 @@ static int dav_method_make_activity(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + /* MKACTIVITY does not have a defined request body. */ if ((result = ap_discard_request_body(r)) != OK) { return result; @@ -4515,6 +4644,12 @@ static int dav_method_merge(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, source_resource, NULL, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + no_auto_merge = dav_find_child(doc->root, "no-auto-merge") != NULL; no_checkout = dav_find_child(doc->root, "no-checkout") != NULL; @@ -4532,6 +4667,13 @@ static int dav_method_merge(request_rec *r) &resource); if (err != NULL) return dav_handle_err(r, err, NULL); + + /* check for any method preconditions */ + if (dav_run_method_precondition(r, source_resource, resource, doc, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -4599,6 +4741,12 @@ static int dav_method_bind(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + if (!resource->exists) { /* Apache will supply a default error for this. */ return HTTP_NOT_FOUND; @@ -4649,6 +4797,12 @@ static int dav_method_bind(request_rec *r) if (err != NULL) return dav_handle_err(r, err, NULL); + /* check for any method preconditions */ + if (dav_run_method_precondition(r, resource, binding, NULL, &err) != DECLINED + && err) { + return dav_handle_err(r, err, NULL); + } + /* are the two resources handled by the same repository? */ if (resource->hooks != binding->hooks) { /* ### this message exposes some backend config, but screw it... */ @@ -5067,6 +5221,7 @@ APR_HOOK_STRUCT( APR_HOOK_LINK(insert_all_liveprops) APR_HOOK_LINK(deliver_report) APR_HOOK_LINK(gather_reports) + APR_HOOK_LINK(method_precondition) ) APR_IMPLEMENT_EXTERNAL_HOOK_VOID(dav, DAV, gather_propsets, @@ -5096,3 +5251,9 @@ APR_IMPLEMENT_EXTERNAL_HOOK_VOID(dav, DAV, gather_reports, apr_array_header_t *reports, dav_error **err), (r, resource, reports, err)) +APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(dav, DAV, int, method_precondition, + (request_rec *r, + dav_resource *src, dav_resource *dest, + const apr_xml_doc *doc, + dav_error **err), + (r, src, dest, doc, err), DECLINED) diff --git a/modules/dav/main/mod_dav.h b/modules/dav/main/mod_dav.h index 56ce428706..7b51b604f9 100644 --- a/modules/dav/main/mod_dav.h +++ b/modules/dav/main/mod_dav.h @@ -744,6 +744,32 @@ APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, gather_reports, (request_rec *r, const dav_resource *resource, apr_array_header_t *reports, dav_error **err)) +/* + ** method_precondition: check method preconditions. + ** + ** If a WebDAV extension needs to set any preconditions on a method, this + ** hook is where to do it. If the precondition fails, return an error + ** response with the tagname set to the value of the failed precondition. + ** + ** If the method requires an XML body, this will be read and provided as + ** the doc value. If not, doc is NULL. An extension that needs to verify + ** the non-XML body of a request should register an input filter to do so + ** within this hook. + ** + ** Methods like PUT will supply a single src resource, and the dest will + ** be NULL. + ** + ** Methods like COPY or MOVE will trigger this hook twice. The first + ** invocation will supply just the source resource. The second invocation + ** will supply a source and destination. This allows preconditions on the + ** source resource to be verified before making an attempt to get the + ** destination resource. + */ +APR_DECLARE_EXTERNAL_HOOK(dav, DAV, int, method_precondition, + (request_rec *r, + dav_resource *src, dav_resource *dst, + const apr_xml_doc *doc, dav_error **err)) + DAV_DECLARE(const dav_hooks_locks *) dav_get_lock_hooks(request_rec *r); DAV_DECLARE(const dav_hooks_propdb *) dav_get_propdb_hooks(request_rec *r); |