1
0
mirror of https://github.com/apache/httpd.git synced 2026-10-23 22:49:01 +03:00

mod_dav: Do not advertise disabled TRACE

dav_method_options() builds its own Allow field and unconditionally
advertised TRACE for existing DAV resources, even when TraceEnable was
off.

Respect TraceEnable when constructing the DAV Allow field.

PR: 70264
GitHub: closes #827


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1939146 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Arturo Bernal
2026-10-16 09:01:44 +00:00
parent ba3fa29664
commit 261058fa22
3 changed files with 82 additions and 1 deletions

View File

@@ -0,0 +1,2 @@
*) mod_dav: Do not list TRACE in the Allow field of an OPTIONS response when
TraceEnable is off. PR 70264

View File

@@ -1844,6 +1844,8 @@ static int dav_method_search(request_rec *r)
/* handle the OPTIONS method */
static int dav_method_options(request_rec *r)
{
core_server_config *conf =
ap_get_core_module_config(r->server->module_config);
const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
const dav_hooks_binding *binding_hooks = DAV_GET_HOOKS_BINDING(r);
@@ -1975,7 +1977,9 @@ static int dav_method_options(request_rec *r)
apr_table_addn(methods, "HEAD", "");
apr_table_addn(methods, "POST", "");
apr_table_addn(methods, "DELETE", "");
apr_table_addn(methods, "TRACE", "");
if (conf->trace_enable != AP_TRACE_DISABLE) {
apr_table_addn(methods, "TRACE", "");
}
apr_table_addn(methods, "PROPFIND", "");
apr_table_addn(methods, "PROPPATCH", "");
apr_table_addn(methods, "COPY", "");

View File

@@ -0,0 +1,75 @@
import os
import pytest
from pyhttpd.conf import HttpdConf
DAV_METHODS = {"OPTIONS", "GET", "HEAD", "POST", "DELETE", "PROPFIND",
"PROPPATCH", "COPY", "MOVE", "LOCK", "UNLOCK"}
def _setup(env, trace):
dav_dir = os.path.join(env.gen_dir, 'dav')
os.makedirs(os.path.join(dav_dir, 'col'), exist_ok=True)
with open(os.path.join(dav_dir, 'file.txt'), 'w') as fd:
fd.write('hello\n')
conf = HttpdConf(env, extras={
'base': f"""
DavLockDB "{env.gen_dir}/davlock"
TraceEnable {trace}
""",
f"test1.{env.http_tld}": f"""
Alias /dav "{dav_dir}"
<Directory "{dav_dir}">
Dav On
Require all granted
</Directory>
""",
})
conf.add_vhost_test1()
conf.install()
assert env.apache_restart() == 0
def _request(env, method, path):
r = env.curl_raw(env.mkurl("https", "test1", path),
options=['-X', method])
assert r.response, f"no response: {r.stderr}"
allow = r.response["header"].get("allow", "")
return r.response["status"], {m.strip() for m in allow.split(',') if m.strip()}
class TestOptionsTraceDisabled:
@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
_setup(env, "off")
# TRACE is not offered while the server refuses it
@pytest.mark.parametrize("path", ["/dav/file.txt", "/dav/col/"])
def test_dav_002_001(self, env, path):
status, allow = _request(env, "OPTIONS", path)
assert status == 200
assert "TRACE" not in allow, f"Allow: {allow}"
assert DAV_METHODS <= allow, f"Allow: {allow}"
def test_dav_002_002(self, env):
assert _request(env, "TRACE", "/dav/file.txt")[0] == 405
class TestOptionsTraceEnabled:
@pytest.fixture(autouse=True, scope='class',
params=["on", "extended"])
def _class_scope(self, env, request):
_setup(env, request.param)
# unchanged: TRACE is offered and works
@pytest.mark.parametrize("path", ["/dav/file.txt", "/dav/col/"])
def test_dav_002_101(self, env, path):
status, allow = _request(env, "OPTIONS", path)
assert status == 200
assert (DAV_METHODS | {"TRACE"}) <= allow, f"Allow: {allow}"
def test_dav_002_102(self, env):
assert _request(env, "TRACE", "/dav/file.txt")[0] == 200