[
https://issues.apache.org/jira/browse/HTTPCLIENT-2433?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18116767#comment-18116767
]
ASF subversion and git services commented on HTTPCLIENT-2433:
-------------------------------------------------------------
Commit 7ed9d66d0fe108123ebf43d0392f1de0b90ad1c1 in httpcomponents-client's
branch refs/heads/5.6.x from Matthias Kurz
[ https://gitbox.apache.org/repos/asf?p=httpcomponents-client.git;h=7ed9d66d0 ]
HTTPCLIENT-2433: Prevent concurrent HTTP/2 request body replay
Wait for both sides of an HTTP/2 exchange to terminate before completing it,
including graceful request termination after RST_STREAM(NO_ERROR).
Cover authentication replay with a large file and with a body-less 401 followed
by a graceful stream reset.
> Async HTTP/2 authentication challenge replay corrupts repeatable
> FileEntityProducer request body
> ------------------------------------------------------------------------------------------------
>
> Key: HTTPCLIENT-2433
> URL: https://issues.apache.org/jira/browse/HTTPCLIENT-2433
> Project: HttpComponents HttpClient
> Issue Type: Bug
> Components: HttpClient (async)
> Affects Versions: 5.6.1
> Environment: Apache HttpClient: 5.6.1
> Apache HttpCore: 5.4
> Java: Eclipse Temurin 17.0.20
> Maven: 3.9.16
> Operating system: Linux
> Transport: clear-text HTTP/2 over loopback using the asynchronous client
> Request entity: repeatable FileEntityProducer containing 2,000,000 bytes
> Authentication: HTTP Basic after a 401 challenge
> Reporter: Matthias
> Priority: Major
> Labels: authentication, http2
> Fix For: 5.6.5, 5.7-alpha2
>
> Time Spent: 40m
> Remaining Estimate: 0h
>
> h2. Summary
> When the asynchronous HttpClient sends a PUT containing a repeatable
> {{FileEntityProducer}} over HTTP/2 and the server immediately responds with a
> {{401 Unauthorized}} Basic-authentication challenge, the authenticated replay
> can contain a corrupted request body.
> The client receives {{200 OK}}, even though the body received for the
> authenticated request is truncated. The original unauthenticated HTTP/2
> stream can simultaneously receive more bytes than the complete entity.
> The equivalent HTTP/1.1 authentication replay works correctly. Sending the
> Authorization header preemptively over HTTP/2 also works correctly.
> h2. Minimal reproducer
> A standalone Java/Maven reproducer is available here:
> [https://github.com/mkurz/apache-httpclient5-h2-auth-replay-reproducer|https://github.com/mkurz/apache-httpclient5-h2-auth-replay-reproducer]
> It directly uses Apache HttpClient 5.6.1 and its transitive HttpCore 5.4
> dependency. It does not use sbt, Gigahorse, Sonatype, or any external server.
> {code:bash}
> git clone
> https://github.com/mkurz/apache-httpclient5-h2-auth-replay-reproducer.git
> cd apache-httpclient5-h2-auth-replay-reproducer
> mvn test
> {code}
> The test starts an in-process loopback server and sends a deterministic
> 2,000,000-byte file using {{FileEntityProducer}}.
> Three cases are tested:
> # HTTP/2 with preemptive Basic authentication: passes.
> # HTTP/1.1 with a Basic-authentication challenge: passes.
> # HTTP/2 with the same authentication challenge: fails.
> h2. Representative result
> {code}
> status=200 expected-length=2000000
> expected-sha1=b694f093d9545edaf64a849bf7e6fc2864a23a0f
> 1: auth=false protocol=HTTP/2.0 length=3229953 exact=false
> sha1=6e23e0988c6d247aa984573ea4f40ee677b0ee0a event=end
> 2: auth=true protocol=HTTP/2.0 length=999423 exact=false
> sha1=60d7a5d13f025e3a10080a71b6c36164b8520a2c event=end
> Tests run: 3, Failures: 1, Errors: 0, Skipped: 0
> {code}
> The precise corrupted lengths and checksums vary between runs, but the HTTP/2
> challenge case consistently fails while both controls pass.
> h2. Expected behavior
> The authenticated replay should contain exactly the original 2,000,000 bytes
> with SHA-1:
> {code}
> b694f093d9545edaf64a849bf7e6fc2864a23a0f
> {code}
> A repeatable entity producer must be reset or reproduced independently for
> the authentication retry, without bytes leaking between the original and
> replayed HTTP/2 streams.
> h2. Actual behavior
> The server receives an oversized body on the original unauthenticated stream
> and a truncated body on the authenticated stream. It sends {{200 OK}} after
> consuming the authenticated stream, so the client reports a successful
> request despite the corrupted upload.
> h2. Real-world occurrence
> This was originally observed while sbt, through Gigahorse's Apache HttpClient
> backend, published Twirl snapshot artifacts to Sonatype Central snapshots.
> Publishing appeared to succeed, but subsequent dependency resolution failed
> because the downloaded artifact did not match its published checksum.
> * Downstream checksum failure:
>
> [https://github.com/playframework/play-doc/actions/runs/34967229654/job/104374507676|https://github.com/playframework/play-doc/actions/runs/34967229654/job/104374507676]
> * Twirl commit whose snapshot publication reproduced the corruption:
>
> [https://github.com/playframework/twirl/commit/e8c94e68fdb69fc1e4bef9b2689596cced5ac2f3|https://github.com/playframework/twirl/commit/e8c94e68fdb69fc1e4bef9b2689596cced5ac2f3]
> * Original sbt investigation:
> [https://github.com/sbt/sbt/pull/9772|https://github.com/sbt/sbt/pull/9772]
> Gigahorse 0.9.6 works around this for known credentials by sending Basic
> authentication preemptively, and sbt adopted that release in:
> [https://github.com/sbt/sbt/pull/9775|https://github.com/sbt/sbt/pull/9775]
> That workaround avoids the challenge/replay path. It does not fix
> challenge-based HTTP/2 authentication replay inside HttpClient.
> h2. Implementation
> [apache/httpcomponents-client#884|https://github.com/apache/httpcomponents-client/pull/884]
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]