Bug 698730 - Add username to connection cache hash so NTLM gets correct connection, r=mcmanus
authorR Kent James <kent@caspia.com>
Sat, 26 Apr 2014 12:01:39 -0700
changeset 180778 a632ecfff394352044444b1f4a0b06e07946e654
parent 180777 9e4afd48a72760a073cfce935f4f3cfb88b0d3df
child 180779 85e868943b6110a790aaf9141f066ff880251a81
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersmcmanus
bugs698730
milestone31.0a1
Bug 698730 - Add username to connection cache hash so NTLM gets correct connection, r=mcmanus
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpConnectionInfo.cpp
netwerk/protocol/http/nsHttpConnectionInfo.h
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpHandler.cpp
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -4528,39 +4528,42 @@ nsresult
 nsHttpChannel::BeginConnect()
 {
     LOG(("nsHttpChannel::BeginConnect [this=%p]\n", this));
     nsresult rv;
 
     // Construct connection info object
     nsAutoCString host;
     int32_t port = -1;
+    nsAutoCString username;
     bool usingSSL = false;
 
     rv = mURI->SchemeIs("https", &usingSSL);
     if (NS_SUCCEEDED(rv))
         rv = mURI->GetAsciiHost(host);
     if (NS_SUCCEEDED(rv))
         rv = mURI->GetPort(&port);
     if (NS_SUCCEEDED(rv))
+        mURI->GetUsername(username);
+    if (NS_SUCCEEDED(rv))
         rv = mURI->GetAsciiSpec(mSpec);
     if (NS_FAILED(rv))
         return rv;
 
     // Reject the URL if it doesn't specify a host
     if (host.IsEmpty())
         return NS_ERROR_MALFORMED_URI;
     LOG(("host=%s port=%d\n", host.get(), port));
     LOG(("uri=%s\n", mSpec.get()));
 
     nsCOMPtr<nsProxyInfo> proxyInfo;
     if (mProxyInfo)
         proxyInfo = do_QueryInterface(mProxyInfo);
 
-    mConnectionInfo = new nsHttpConnectionInfo(host, port, proxyInfo, usingSSL);
+    mConnectionInfo = new nsHttpConnectionInfo(host, port, username, proxyInfo, usingSSL);
 
     mAuthProvider =
         do_CreateInstance("@mozilla.org/network/http-channel-auth-provider;1",
                           &rv);
     if (NS_SUCCEEDED(rv))
         rv = mAuthProvider->Init(this);
     if (NS_FAILED(rv))
         return rv;
--- a/netwerk/protocol/http/nsHttpConnectionInfo.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionInfo.cpp
@@ -16,19 +16,21 @@
 #include "nsHttpConnectionInfo.h"
 #include "mozilla/net/DNS.h"
 #include "prnetdb.h"
 
 namespace mozilla {
 namespace net {
 
 nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &host, int32_t port,
+                                           const nsACString &username,
                                            nsProxyInfo* proxyInfo,
                                            bool usingSSL)
-    : mProxyInfo(proxyInfo)
+    : mUsername(username)
+    , mProxyInfo(proxyInfo)
     , mUsingSSL(usingSSL)
     , mUsingConnect(false)
 {
     LOG(("Creating nsHttpConnectionInfo @%x\n", this));
 
     mUsingHttpProxy = (proxyInfo && proxyInfo->IsHTTP());
 
     if (mUsingHttpProxy) {
@@ -70,16 +72,21 @@ nsHttpConnectionInfo::SetOriginServer(co
         keyHost = Host();
         keyPort = Port();
     }
 
     mHashKey.AssignLiteral("....");
     mHashKey.Append(keyHost);
     mHashKey.Append(':');
     mHashKey.AppendInt(keyPort);
+    if (!mUsername.IsEmpty()) {
+        mHashKey.Append('[');
+        mHashKey.Append(mUsername);
+        mHashKey.Append(']');
+    }
 
     if (mUsingHttpProxy)
         mHashKey.SetCharAt('P', 0);
     if (mUsingSSL)
         mHashKey.SetCharAt('S', 1);
 
     // NOTE: for transparent proxies (e.g., SOCKS) we need to encode the proxy
     // info in the hash key (this ensures that we will continue to speak the
@@ -101,17 +108,17 @@ nsHttpConnectionInfo::SetOriginServer(co
         mHashKey.AppendInt(ProxyPort());
         mHashKey.Append(')');
     }
 }
 
 nsHttpConnectionInfo*
 nsHttpConnectionInfo::Clone() const
 {
-    nsHttpConnectionInfo* clone = new nsHttpConnectionInfo(mHost, mPort, mProxyInfo, mUsingSSL);
+    nsHttpConnectionInfo* clone = new nsHttpConnectionInfo(mHost, mPort, mUsername, mProxyInfo, mUsingSSL);
 
     // Make sure the anonymous and private flags are transferred!
     clone->SetAnonymous(GetAnonymous());
     clone->SetPrivate(GetPrivate());
 
     return clone;
 }
 
--- a/netwerk/protocol/http/nsHttpConnectionInfo.h
+++ b/netwerk/protocol/http/nsHttpConnectionInfo.h
@@ -19,16 +19,17 @@ extern PRLogModuleInfo *gHttpLog;
 //-----------------------------------------------------------------------------
 
 namespace mozilla { namespace net {
 
 class nsHttpConnectionInfo
 {
 public:
     nsHttpConnectionInfo(const nsACString &host, int32_t port,
+                         const nsACString &username,
                          nsProxyInfo* proxyInfo,
                          bool usingSSL=false);
 
     virtual ~nsHttpConnectionInfo()
     {
         PR_LOG(gHttpLog, 4, ("Destroying nsHttpConnectionInfo @%x\n", this));
     }
 
@@ -57,16 +58,17 @@ public:
     // a request will end up at the same host.
     bool Equals(const nsHttpConnectionInfo *info)
     {
         return mHashKey.Equals(info->HashKey());
     }
 
     const char   *Host() const           { return mHost.get(); }
     int32_t       Port() const           { return mPort; }
+    const char   *Username() const       { return mUsername.get(); }
     nsProxyInfo  *ProxyInfo()            { return mProxyInfo; }
     bool          UsingHttpProxy() const { return mUsingHttpProxy; }
     bool          UsingSSL() const       { return mUsingSSL; }
     bool          UsingConnect() const   { return mUsingConnect; }
     int32_t       DefaultPort() const    { return mUsingSSL ? NS_HTTPS_DEFAULT_PORT : NS_HTTP_DEFAULT_PORT; }
     void          SetAnonymous(bool anon)
                                          { mHashKey.SetCharAt(anon ? 'A' : '.', 2); }
     bool          GetAnonymous() const   { return mHashKey.CharAt(2) == 'A'; }
@@ -80,16 +82,17 @@ public:
 
     // Returns true when mHost is an RFC1918 literal.
     bool HostIsLocalIPLiteral() const;
 
 private:
     nsCString              mHashKey;
     nsCString              mHost;
     int32_t                mPort;
+    nsCString              mUsername;
     nsCOMPtr<nsProxyInfo>  mProxyInfo;
     bool                   mUsingHttpProxy;
     bool                   mUsingSSL;
     bool                   mUsingConnect;  // if will use CONNECT with http proxy
 
 // for nsRefPtr
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHttpConnectionInfo)
 };
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -1173,35 +1173,38 @@ nsHttpConnectionMgr::PipelineFeedbackInf
 
 void
 nsHttpConnectionMgr::ReportFailedToProcess(nsIURI *uri)
 {
     MOZ_ASSERT(uri);
 
     nsAutoCString host;
     int32_t port = -1;
+    nsAutoCString username;
     bool usingSSL = false;
     bool isHttp = false;
 
     nsresult rv = uri->SchemeIs("https", &usingSSL);
     if (NS_SUCCEEDED(rv) && usingSSL)
         isHttp = true;
     if (NS_SUCCEEDED(rv) && !isHttp)
         rv = uri->SchemeIs("http", &isHttp);
     if (NS_SUCCEEDED(rv))
         rv = uri->GetAsciiHost(host);
     if (NS_SUCCEEDED(rv))
         rv = uri->GetPort(&port);
+    if (NS_SUCCEEDED(rv))
+        uri->GetUsername(username);
     if (NS_FAILED(rv) || !isHttp || host.IsEmpty())
         return;
 
     // report the event for all the permutations of anonymous and
     // private versions of this host
     nsRefPtr<nsHttpConnectionInfo> ci =
-        new nsHttpConnectionInfo(host, port, nullptr, usingSSL);
+        new nsHttpConnectionInfo(host, port, username, nullptr, usingSSL);
     ci->SetAnonymous(false);
     ci->SetPrivate(false);
     PipelineFeedbackInfo(ci, RedCorruptedContent, nullptr, 0);
 
     ci = ci->Clone();
     ci->SetAnonymous(false);
     ci->SetPrivate(true);
     PipelineFeedbackInfo(ci, RedCorruptedContent, nullptr, 0);
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -1909,18 +1909,21 @@ nsHttpHandler::SpeculativeConnect(nsIURI
     if (NS_FAILED(rv))
         return rv;
 
     int32_t port = -1;
     rv = aURI->GetPort(&port);
     if (NS_FAILED(rv))
         return rv;
 
+    nsAutoCString username;
+    aURI->GetUsername(username);
+
     nsHttpConnectionInfo *ci =
-        new nsHttpConnectionInfo(host, port, nullptr, usingSSL);
+        new nsHttpConnectionInfo(host, port, username, nullptr, usingSSL);
 
     return SpeculativeConnect(ci, aCallbacks);
 }
 
 void
 nsHttpHandler::TickleWifi(nsIInterfaceRequestor *cb)
 {
     if (!cb || !mWifiTickler)