bug 766817 - websocket handshake closes conn on 407/401 defeating session auth schemes r=jduell
authorPatrick McManus <mcmanus@ducksong.com>
Tue, 16 Oct 2012 15:13:52 -0400
changeset 110579 b8b86cd19f38a16518b678a37f9bb15cc0cff63b
parent 110578 073b904aed0cd056c425125a14323e263cc58e4c
child 110580 e7497bc33b3c2b25b2aa40e29f2973aeff012084
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersjduell
bugs766817
milestone19.0a1
bug 766817 - websocket handshake closes conn on 407/401 defeating session auth schemes r=jduell
netwerk/protocol/http/nsHttpConnection.cpp
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -707,17 +707,18 @@ nsHttpConnection::OnHeadersAvailable(nsA
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
     NS_ENSURE_ARG_POINTER(trans);
     NS_ASSERTION(responseHead, "No response head?");
 
     // If the server issued an explicit timeout, then we need to close down the
     // socket transport.  We pass an error code of NS_ERROR_NET_RESET to
     // trigger the transactions 'restart' mechanism.  We tell it to reset its
     // response headers so that it will be ready to receive the new response.
-    if (responseHead->Status() == 408) {
+    uint16_t responseStatus = responseHead->Status();
+    if (responseStatus == 408) {
         Close(NS_ERROR_NET_RESET);
         *reset = true;
         return NS_OK;
     }
 
     // we won't change our keep-alive policy unless the server has explicitly
     // told us to do so.
 
@@ -784,17 +785,17 @@ nsHttpConnection::OnHeadersAvailable(nsA
             gHttpHandler->ConnMgr()->SupportsPipelining(mConnInfo);
     }
 
     // If this connection is reserved for revalidations and we are
     // receiving a document that failed revalidation then switch the
     // classification to general to avoid pipelining more revalidations behind
     // it.
     if (mClassification == nsAHttpTransaction::CLASS_REVALIDATION &&
-        responseHead->Status() != 304) {
+        responseStatus != 304) {
         mClassification = nsAHttpTransaction::CLASS_GENERAL;
     }
     
     // if this connection is persistent, then the server may send a "Keep-Alive"
     // header specifying the maximum number of times the connection can be
     // reused as well as the maximum amount of time the connection can be idle
     // before the server will close it.  we ignore the max reuse count, because
     // a "keep-alive" connection is by definition capable of being reused, and
@@ -837,17 +838,17 @@ nsHttpConnection::OnHeadersAvailable(nsA
     // If we're doing a proxy connect, we need to check whether or not
     // it was successful.  If so, we have to reset the transaction and step-up
     // the socket connection if using SSL. Finally, we have to wake up the
     // socket write request.
     if (mProxyConnectStream) {
         NS_ABORT_IF_FALSE(!mUsingSpdyVersion,
                           "SPDY NPN Complete while using proxy connect stream");
         mProxyConnectStream = 0;
-        if (responseHead->Status() == 200) {
+        if (responseStatus == 200) {
             LOG(("proxy CONNECT succeeded! ssl=%s\n",
                  mConnInfo->UsingSSL() ? "true" :"false"));
             *reset = true;
             nsresult rv;
             if (mConnInfo->UsingSSL()) {
                 rv = ProxyStartSSL();
                 if (NS_FAILED(rv)) // XXX need to handle this for real
                     LOG(("ProxyStartSSL failed [rv=%x]\n", rv));
@@ -861,22 +862,24 @@ nsHttpConnection::OnHeadersAvailable(nsA
         else {
             LOG(("proxy CONNECT failed! ssl=%s\n",
                  mConnInfo->UsingSSL() ? "true" :"false"));
             mTransaction->SetProxyConnectFailed();
         }
     }
     
     const char *upgradeReq = requestHead->PeekHeader(nsHttp::Upgrade);
-    if (upgradeReq) {
+    // Don't use persistent connection for Upgrade unless there's an auth failure:
+    // some proxies expect to see auth response on persistent connection.
+    if (upgradeReq && responseStatus != 401 && responseStatus != 407) {
         LOG(("HTTP Upgrade in play - disable keepalive\n"));
         DontReuse();
     }
     
-    if (responseHead->Status() == 101) {
+    if (responseStatus == 101) {
         const char *upgradeResp = responseHead->PeekHeader(nsHttp::Upgrade);
         if (!upgradeReq || !upgradeResp ||
             !nsHttp::FindToken(upgradeResp, upgradeReq,
                                HTTP_HEADER_VALUE_SEPS)) {
             LOG(("HTTP 101 Upgrade header mismatch req = %s, resp = %s\n",
                  upgradeReq, upgradeResp));
             Close(NS_ERROR_ABORT);
         }