1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Proxy: discard buffered input data on reconnection.

When talking to a web proxy which requires a password, our HTTP proxy
code sends an initial attempt to connect without authentication,
receives the 407 status indicating that authentication was required
(and which kind), and then closes and reopens the connection (if given
"Connection: close"). Then, on the next attempt, we try again with
authentication, and expect the first thing in the input bufchain to be
the HTTP status response to the revised request.

But what happened about the error document that followed those HTTP
headers? It - or at least some of it - would already have been in the
input bufchain.

With an HTTP/1.1 proxy, we already read it and discarded it (either
via a Content-length header or chunked transfer encoding), before we
set the 'reconnect' flag. So, assuming the proxy HTTP server is
behaving sensibly, our input bufchain ought to be empty at the point
when we start the fresh connection.

But if the proxy only speaks HTTP/1.0 (which does still happen -
'tinyproxy' is a still-current example), then we didn't get a
Content-length header either, so we didn't run any of the code that
skips over the error document. (And HTTP/1.0 implicitly has
"Connection: close" semantics, which is why that doesn't matter.) As a
result, some of it would still be in the input bufchain, and never got
cleared out, and we'd try to parse _that_ as if it was the HTTP
response from the second network connection.

The simple solution is that when we close and reopen the proxy network
connection, we also clear the input bufchain, so that the fresh
connection starts from a clean slate.
This commit is contained in:
Simon Tatham 2022-05-18 12:41:44 +01:00
parent 0a877e9df5
commit 81dcbd6267

View File

@ -232,6 +232,13 @@ static void proxy_negotiate(ProxySocket *ps)
ps->proxy_nodelay, ps->proxy_keepalive,
&ps->plugimpl);
ps->pn->reconnect = false;
/* If the negotiator has asked us to reconnect, they are
* expecting that on the next call their input queue will
* consist entirely of data from the _new_ connection, without
* any remaining data buffered from the old one. (If they'd
* wanted the latter, they could have read it out of the input
* queue before asking us to close the connection.) */
bufchain_clear(&ps->pending_input_data);
}
while (bufchain_size(&ps->output_from_negotiator)) {