I’m not talking about why the client does want the upgrade… Perhaps it doesn’t know if port 443 uses TLS or hosts the same content. In general it is just a lucky guess that it does have the same content. The Alt-Svc spec might help here, but currently this still requires the admin to configure things… and I don’t see that change anytime soon. (And if it would be automatic, it would still assume no firewalls, certificate availability, etc., etc.)
What I’m trying to say is: we should not just deny connections an upgrade for no reason. If we can upgrade the connection with a body… why explicitly deny it *after* we already received the body? If we want to reuse the connection we have to read the body anyway. We can’t make the connection more secure by asking the client to retry the request… We can only make things less secure that way. Returning a 4XX error just makes the client retry the request (perhaps after asking the user). The 4XX will be more work for the server, more work for the client and perhaps even for the end user. We don’t make the web more secure by denying upgrades after the request is already sent. And as http/1.1 doesn’t have a way to stop a request before it is sent without resetting the connection I would say that we upgrade to TLS and/or H2c whenever possible. The server can’t decide if the client should send the request unencrypted or not *after* it is already on the wire unencrypted. By not upgrading we *as server* decide that the next request on the same connection will be unencrypted as well… By returning a 4XX (or other error) we ask the client to retry again; most likely on the same connection and just as unencrypted as the previous request. On disconnecting we do the same thing…. The only way to ensure encryption or more advanced protocol support is honoring the upgrade request as soon as possible. The deadlock scenarios on bodies that can’t be sent while the request is read are no reason to just block upgrades… These same deadlocks can occur for dozens of different reasons and in case of h2 even after upgrade. (Don’t send window updates and everything stalls… by design). At that point we can handle the error, just like how we handle timeouts on http/1.1 With h2 we can even force stream 1 (the response for the upgraded request) to close with an appropriate stream error in that case… so we can still reuse the connection. With h2 you can in theory start the response in h2 while you are still reading the http/1.1 body, while with TLS you can’t as you need a two way handshake. There will be cases where the upgrade path definitely breaks (e.g. huge/infinite chunked request echoed as response), but I think in most cases it can succeed without a problem. Just returning an error in easy cases for consistency with the cases where it can’t work doesn’t really help. The problem with errors like 413 is that in clients like Subversion we can only handle them by showing them as fatal error to the user. The printer scenario for upgrades to TLS probably does the same thing. Printing works or doesn’t work… It doesn’t allow retrying with a different request. Not upgrading is an option… But upgrading under less favorable conditions is what makes things work. Bert Sent from Mail for Windows 10 From: Yann Ylavic Sent: zaterdag 12 december 2015 01:46 To: Bert Huijben Subject: Re: Upgrade Summary On Sat, Dec 12, 2015 at 12:48 AM, Bert Huijben <b...@qqmail.nl> wrote: > If you request an upgrade to TLS on your initial request, upgrading with a > body might still make sense. Especially if the server would respond with a > 401. But also if the request can be public, but the response needs to be > secured. Why using Upgrade at the first place if you are confident enough (to play auth) with the server being TLS ready? Wouldn't a direct https connection be better? Is there such an authentication protocol? If so, I guess we can do the TLS Upgrade+handshake in the output filter (as proposed) like any other Protocols Upgrade, letting httpd handle that first clear text request body... That's possible without setting aside the body anyway, still I doubt there is a real need for it (if a TLS Upgrade is asked, the client shouldn't mind the first (half) round trip and play it's auth on the second (TLSed) request. > > If we blindly ignore the upgrade as ‘doesn’t make sense’, the next request > wouldn’t use encryption… but if we upgraded to TLS after the request, the > next request… with the authentication headers could be sent encrypted. My preference would be to return an error (413), so that the client notices what's "better" for a TLS Upgrade (no body), but if there really exist such a cleartext body use case I'm fine with honoring the body too. > > If upgrading the first request doesn’t make sense the client should use a > different request (Like options *, or HEAD /). That are, AFAICT, the only use cases so far. > > If the server denies the request at least some parts have already travelled > the network unencrypted. Returning an error or not upgrading will only make > sure more requests will travel unencrypted. The client would not send encrypted vs unencrypted (Upgrade) request depending on the response status, it must send plaintext request anyway, it ought to know that. IOW the error response is not a security issue at all, on the contrary if a client relies on current httpd behaviour to do the handshake before reading the body, and hence sends private things in the body of the Upgrade request, it would notice with a response error. Anyway if the RFC is respected, the TLS handshake doesn't happen before any body is (fully) received on the server, hence such client would wait for the handshake before sending anything, and that would timeout. Again, an error response is better here... > > The response is not the only thing encrypted when upgrading… all future > requests are. Upgrade is a connection level request, sent via a request. Agreed. Regards, Yann.