mirror of
https://github.com/curl/curl.git
synced 2026-08-24 20:13:35 +03:00
http2: fix EOF handling on uploads with auth negotiation
- doing a POST with `--digest` does an override on the initial request with `Content-Length: 0`, but the http2 filter was unaware of that and expected the originally request body. It did therefore not send a final DATA frame with EOF flag to the server. - The fix overrides any initial notion of post size when the `done_send` event is triggered by the transfer loop, leading to the EOF that is necessary. - refs #11194. The fault did not happen in testing, as Apache httpd never tries to read the request body of the initial request, sends the 401 reply and closes the stream. The server used in the reported issue however tried to read the EOF and timed out on the request. Reported-by: Aleksander Mazur Fixes #11194 Cloes #11200
This commit is contained in:
parent
1fe8de85d3
commit
5c58cb0212
4 changed files with 138 additions and 18 deletions
|
|
@ -70,9 +70,11 @@ class Httpd:
|
|||
self._logs_dir = os.path.join(self._apache_dir, 'logs')
|
||||
self._error_log = os.path.join(self._logs_dir, 'error_log')
|
||||
self._tmp_dir = os.path.join(self._apache_dir, 'tmp')
|
||||
self._passwords = os.path.join(self._conf_dir, 'passwords')
|
||||
self._basic_passwords = os.path.join(self._conf_dir, 'basic.passwords')
|
||||
self._digest_passwords = os.path.join(self._conf_dir, 'digest.passwords')
|
||||
self._mods_dir = None
|
||||
self._proxy_auth = proxy_auth
|
||||
self._auth_digest = True
|
||||
self._proxy_auth_basic = proxy_auth
|
||||
self._extra_configs = {}
|
||||
assert env.apxs
|
||||
p = subprocess.run(args=[env.apxs, '-q', 'libexecdir'],
|
||||
|
|
@ -108,7 +110,7 @@ class Httpd:
|
|||
self._extra_configs = {}
|
||||
|
||||
def set_proxy_auth(self, active: bool):
|
||||
self._proxy_auth = active
|
||||
self._proxy_auth_basic = active
|
||||
|
||||
def _run(self, args, intext=''):
|
||||
env = {}
|
||||
|
|
@ -219,9 +221,15 @@ class Httpd:
|
|||
'server': f'{domain2}',
|
||||
}
|
||||
fd.write(JSONEncoder().encode(data))
|
||||
if self._proxy_auth:
|
||||
with open(self._passwords, 'w') as fd:
|
||||
if self._proxy_auth_basic:
|
||||
with open(self._basic_passwords, 'w') as fd:
|
||||
fd.write('proxy:$apr1$FQfeInbs$WQZbODJlVg60j0ogEIlTW/\n')
|
||||
if self._auth_digest:
|
||||
with open(self._digest_passwords, 'w') as fd:
|
||||
fd.write('test:restricted area:57123e269fd73d71ae0656594e938e2f\n')
|
||||
self._mkpath(os.path.join(self.docs_dir, 'restricted/digest'))
|
||||
with open(os.path.join(self.docs_dir, 'restricted/digest/data.json'), 'w') as fd:
|
||||
fd.write('{"area":"digest"}\n')
|
||||
with open(self._conf_file, 'w') as fd:
|
||||
for m in self.MODULES:
|
||||
if os.path.exists(os.path.join(self._mods_dir, f'mod_{m}.so')):
|
||||
|
|
@ -252,7 +260,7 @@ class Httpd:
|
|||
f' DocumentRoot "{self._docs_dir}"',
|
||||
f' Protocols h2c http/1.1',
|
||||
])
|
||||
conf.extend(self._curltest_conf())
|
||||
conf.extend(self._curltest_conf(domain1))
|
||||
conf.extend([
|
||||
f'</VirtualHost>',
|
||||
f'',
|
||||
|
|
@ -267,7 +275,7 @@ class Httpd:
|
|||
f' SSLCertificateKeyFile {creds1.pkey_file}',
|
||||
f' DocumentRoot "{self._docs_dir}"',
|
||||
])
|
||||
conf.extend(self._curltest_conf())
|
||||
conf.extend(self._curltest_conf(domain1))
|
||||
if domain1 in self._extra_configs:
|
||||
conf.extend(self._extra_configs[domain1])
|
||||
conf.extend([
|
||||
|
|
@ -283,7 +291,7 @@ class Httpd:
|
|||
f' SSLCertificateKeyFile {creds2.pkey_file}',
|
||||
f' DocumentRoot "{self._docs_dir}/two"',
|
||||
])
|
||||
conf.extend(self._curltest_conf())
|
||||
conf.extend(self._curltest_conf(domain2))
|
||||
if domain2 in self._extra_configs:
|
||||
conf.extend(self._extra_configs[domain2])
|
||||
conf.extend([
|
||||
|
|
@ -329,13 +337,13 @@ class Httpd:
|
|||
]))
|
||||
|
||||
def _get_proxy_conf(self):
|
||||
if self._proxy_auth:
|
||||
if self._proxy_auth_basic:
|
||||
return [
|
||||
f' <Proxy "*">',
|
||||
f' AuthType Basic',
|
||||
f' AuthName "Restricted Proxy"',
|
||||
f' AuthBasicProvider file',
|
||||
f' AuthUserFile "{self._passwords}"',
|
||||
f' AuthUserFile "{self._basic_passwords}"',
|
||||
f' Require user proxy',
|
||||
f' </Proxy>',
|
||||
]
|
||||
|
|
@ -355,9 +363,10 @@ class Httpd:
|
|||
return 'debug'
|
||||
return 'info'
|
||||
|
||||
def _curltest_conf(self) -> List[str]:
|
||||
def _curltest_conf(self, servername) -> List[str]:
|
||||
lines = []
|
||||
if Httpd.MOD_CURLTEST is not None:
|
||||
return [
|
||||
lines.extend([
|
||||
f' <Location /curltest/echo>',
|
||||
f' SetHandler curltest-echo',
|
||||
f' </Location>',
|
||||
|
|
@ -367,8 +376,20 @@ class Httpd:
|
|||
f' <Location /curltest/tweak>',
|
||||
f' SetHandler curltest-tweak',
|
||||
f' </Location>',
|
||||
]
|
||||
return []
|
||||
])
|
||||
if self._auth_digest:
|
||||
lines.extend([
|
||||
f' <Directory {self.docs_dir}/restricted/digest>',
|
||||
f' AuthType Digest',
|
||||
f' AuthName "restricted area"',
|
||||
f' AuthDigestDomain "https://{servername}"',
|
||||
f' AuthBasicProvider file',
|
||||
f' AuthUserFile "{self._digest_passwords}"',
|
||||
f' Require valid-user',
|
||||
f' </Directory>',
|
||||
|
||||
])
|
||||
return lines
|
||||
|
||||
def _init_curltest(self):
|
||||
if Httpd.MOD_CURLTEST is not None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue