Bug 1264562 - Part 1: Add firstPartyDomain to socket transport (adapted from Tor Browser patch 13670) r=mayhemer draft
authorJonathan Hao <jhao@mozilla.com>
Wed, 12 Oct 2016 15:32:22 +0800
changeset 427460 6f0196209abf900789284341cfa7e449921d2abc
parent 424520 22be4ae74653b25186665f22e52a50e7027fd36b
child 427461 fffddcdb5b3bf10272cf3e8c379596e0d75cf0fa
push id33016
push userbmo:jhao@mozilla.com
push dateThu, 20 Oct 2016 10:18:14 +0000
reviewersmayhemer
bugs1264562, 13670
milestone52.0a1
Bug 1264562 - Part 1: Add firstPartyDomain to socket transport (adapted from Tor Browser patch 13670) r=mayhemer
netwerk/base/nsISocketTransport.idl
netwerk/base/nsSocketTransport2.cpp
netwerk/base/nsSocketTransport2.h
netwerk/protocol/http/TunnelUtils.cpp
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/socket/nsISocketProvider.idl
netwerk/socket/nsSOCKSSocketProvider.cpp
netwerk/socket/nsUDPSocketProvider.cpp
security/manager/ssl/nsSSLSocketProvider.cpp
security/manager/ssl/nsTLSSocketProvider.cpp
--- a/netwerk/base/nsISocketTransport.idl
+++ b/netwerk/base/nsISocketTransport.idl
@@ -40,16 +40,24 @@ interface nsISocketTransport : nsITransp
 
     /**
      * Get the port for the underlying socket connection.
      * For Unix domain sockets, this is zero.
      */
     readonly attribute long port;
 
     /**
+     * This is only non-empty when "privacy.firstparty.isolate" is enabled.
+     * It is used to create sockets, and will eventually be used to isolate
+     * OCSP cache. It's the only way to carry it down to NSPR layers which are
+     * final consumers.  It must be set before the socket transport is built.
+     */
+    attribute AUTF8String firstPartyDomain;
+
+    /**
      * The platform-specific network interface id that this socket
      * associated with. Note that this attribute can be only accessed
      * in the socket thread.
      */
     attribute ACString networkInterfaceId;
 
     /**
      * Returns the IP address of the socket connection peer. This
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -1164,34 +1164,35 @@ nsSocketTransport::BuildSocket(PRFileDes
                 // service to allocate a new socket
 
                 // when https proxying we want to just connect to the proxy as if
                 // it were the end host (i.e. expect the proxy's cert)
 
                 rv = provider->NewSocket(mNetAddr.raw.family,
                                          mHttpsProxy ? mProxyHost.get() : host,
                                          mHttpsProxy ? mProxyPort : port,
-                                         proxyInfo,
+                                         proxyInfo, mFirstPartyDomain,
                                          controlFlags, &fd,
                                          getter_AddRefs(secinfo));
 
                 if (NS_SUCCEEDED(rv) && !fd) {
                     NS_NOTREACHED("NewSocket succeeded but failed to create a PRFileDesc");
                     rv = NS_ERROR_UNEXPECTED;
                 }
             }
             else {
                 // the socket has already been allocated, 
                 // so we just want the service to add itself
                 // to the stack (such as pushing an io layer)
                 rv = provider->AddToSocket(mNetAddr.raw.family,
                                            host, port, proxyInfo,
-                                           controlFlags, fd,
+                                           mFirstPartyDomain, controlFlags, fd,
                                            getter_AddRefs(secinfo));
             }
+
             // controlFlags = 0; not used below this point...
             if (NS_FAILED(rv))
                 break;
 
             // if the service was ssl or starttls, we want to hold onto the socket info
             bool isSSL = (strcmp(mTypes[i], "ssl") == 0);
             if (isSSL || (strcmp(mTypes[i], "starttls") == 0)) {
                 // remember security info and give notification callbacks to PSM...
@@ -2385,16 +2386,33 @@ NS_IMETHODIMP
 nsSocketTransport::SetNetworkInterfaceId(const nsACString_internal &aNetworkInterfaceId)
 {
     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "wrong thread");
     mNetworkInterfaceId = aNetworkInterfaceId;
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsSocketTransport::GetFirstPartyDomain(nsACString &value)
+{
+    value = mFirstPartyDomain;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSocketTransport::SetFirstPartyDomain(const nsACString &value)
+{
+    MutexAutoLock lock(mLock);
+    NS_ENSURE_FALSE(mFD.IsInitialized(), NS_ERROR_FAILURE);
+
+    mFirstPartyDomain = value;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsSocketTransport::GetPeerAddr(NetAddr *addr)
 {
     // once we are in the connected state, mNetAddr will not change.
     // so if we can verify that we are in the connected state, then
     // we can freely access mNetAddr from any thread without being
     // inside a critical section.
 
     if (!mNetAddrIsSet) {
--- a/netwerk/base/nsSocketTransport2.h
+++ b/netwerk/base/nsSocketTransport2.h
@@ -297,16 +297,22 @@ private:
     uint16_t     mPort;
     nsCOMPtr<nsIProxyInfo> mProxyInfo;
     uint16_t     mProxyPort;
     uint16_t     mOriginPort;
     bool mProxyTransparent;
     bool mProxyTransparentResolvesHost;
     bool mHttpsProxy;
     uint32_t     mConnectionFlags;
+
+    // This is only non-empty when "privacy.firstparty.isolate" is enabled.
+    // It is used to create sockets. It's the only way to carry it down to NSPR
+    // layers which are final consumers.  It must be set before the socket
+    // transport is built.
+    nsCString    mFirstPartyDomain;
     
     uint16_t         SocketPort() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyPort : mPort; }
     const nsCString &SocketHost() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyHost : mHost; }
 
     //-------------------------------------------------------------------------
     // members accessible only on the socket transport thread:
     //  (the exception being initialization/shutdown time)
     //-------------------------------------------------------------------------
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -72,17 +72,17 @@ TLSFilterTransaction::TLSFilterTransacti
     sLayerMethods.close = FilterClose;
     sLayerMethodsPtr = &sLayerMethods;
   }
 
   mFD = PR_CreateIOLayerStub(sLayerIdentity, &sLayerMethods);
 
   if (provider && mFD) {
     mFD->secret = reinterpret_cast<PRFilePrivate *>(this);
-    provider->AddToSocket(PR_AF_INET, aTLSHost, aTLSPort, nullptr,
+    provider->AddToSocket(PR_AF_INET, aTLSHost, aTLSPort, nullptr, EmptyCString(),
                           0, mFD, getter_AddRefs(mSecInfo));
   }
 
   if (mTransaction) {
     nsCOMPtr<nsIInterfaceRequestor> callbacks;
     mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks));
     nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(mSecInfo));
     if (secCtrl) {
@@ -1588,16 +1588,18 @@ FWD_TS_ADDREF(GetScriptablePeerAddr, nsI
 FWD_TS_ADDREF(GetScriptableSelfAddr, nsINetAddr);
 FWD_TS_ADDREF(GetSecurityInfo, nsISupports);
 FWD_TS_ADDREF(GetSecurityCallbacks, nsIInterfaceRequestor);
 FWD_TS_PTR(IsAlive, bool);
 FWD_TS_PTR(GetConnectionFlags, uint32_t);
 FWD_TS(SetConnectionFlags, uint32_t);
 FWD_TS_PTR(GetRecvBufferSize, uint32_t);
 FWD_TS(SetRecvBufferSize, uint32_t);
+FWD_TS(SetFirstPartyDomain, const nsACString&);
+FWD_TS(GetFirstPartyDomain, nsACString&);
 
 NS_IMETHODIMP
 SocketTransportShim::GetHost(nsACString & aHost)
 {
   return mWrapped->GetHost(aHost);
 }
 
 NS_IMETHODIMP
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -3076,16 +3076,22 @@ nsHalfOpenSocket::SetupStreams(nsISocket
     }
 
     if (!Allow1918()) {
         tmpFlags |= nsISocketTransport::DISABLE_RFC1918;
     }
 
     socketTransport->SetConnectionFlags(tmpFlags);
 
+    nsAutoCString firstPartyDomain =
+      NS_ConvertUTF16toUTF8(mEnt->mConnInfo->GetOriginAttributes().mFirstPartyDomain);
+    if (!firstPartyDomain.IsEmpty()) {
+        socketTransport->SetFirstPartyDomain(firstPartyDomain);
+    }
+
     socketTransport->SetQoSBits(gHttpHandler->GetQoSBits());
 
     if (!ci->GetNetworkInterfaceId().IsEmpty()) {
         socketTransport->SetNetworkInterfaceId(ci->GetNetworkInterfaceId());
     }
 
     rv = socketTransport->SetEventSink(this, nullptr);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/netwerk/socket/nsISocketProvider.idl
+++ b/netwerk/socket/nsISocketProvider.idl
@@ -35,16 +35,17 @@ interface nsISocketProvider : nsISupport
      *        Any security info that should be associated with aFileDesc.  This
      *        object typically implements nsITransportSecurityInfo.
      */
     [noscript]
     void newSocket(in long            aFamily,
                    in string          aHost, 
                    in long            aPort,
                    in nsIProxyInfo    aProxy,
+                   in ACString        aFirstPartyDomain,
                    in unsigned long   aFlags,
                    out PRFileDescStar aFileDesc, 
                    out nsISupports    aSecurityInfo);
 
     /**
      * addToSocket
      *
      * This function is called to allow the socket provider to layer a
@@ -54,16 +55,17 @@ interface nsISocketProvider : nsISupport
      * Parameters are the same as newSocket with the exception of aFileDesc,
      * which is an in-param instead.
      */
     [noscript]
     void addToSocket(in long           aFamily,
                      in string         aHost, 
                      in long           aPort,
                      in nsIProxyInfo   aProxy,
+                     in ACString       aFirstPartyDomain,
                      in unsigned long  aFlags,
                      in PRFileDescStar aFileDesc, 
                      out nsISupports   aSecurityInfo);
 
     /**
      * PROXY_RESOLVES_HOST
      *
      * This flag is set if the proxy is to perform hostname resolution instead
--- a/netwerk/socket/nsSOCKSSocketProvider.cpp
+++ b/netwerk/socket/nsSOCKSSocketProvider.cpp
@@ -40,16 +40,17 @@ nsSOCKSSocketProvider::CreateV5(nsISuppo
     return rv;
 }
 
 NS_IMETHODIMP
 nsSOCKSSocketProvider::NewSocket(int32_t family,
                                  const char *host, 
                                  int32_t port,
                                  nsIProxyInfo *proxy,
+                                 const nsACString &firstPartyDomain,
                                  uint32_t flags,
                                  PRFileDesc **result,
                                  nsISupports **socksInfo)
 {
     PRFileDesc *sock;
     
     sock = PR_OpenTCPSocket(family);
     if (!sock)
@@ -71,16 +72,17 @@ nsSOCKSSocketProvider::NewSocket(int32_t
     return NS_ERROR_SOCKET_CREATE_FAILED;
 }
 
 NS_IMETHODIMP
 nsSOCKSSocketProvider::AddToSocket(int32_t family,
                                    const char *host,
                                    int32_t port,
                                    nsIProxyInfo *proxy,
+                                   const nsACString &firstPartyDomain,
                                    uint32_t flags,
                                    PRFileDesc *sock,
                                    nsISupports **socksInfo)
 {
     nsresult rv = nsSOCKSIOLayerAddToSocket(family,
                                             host, 
                                             port,
                                             proxy,
--- a/netwerk/socket/nsUDPSocketProvider.cpp
+++ b/netwerk/socket/nsUDPSocketProvider.cpp
@@ -12,16 +12,17 @@ nsUDPSocketProvider::~nsUDPSocketProvide
 {
 }
 
 NS_IMETHODIMP 
 nsUDPSocketProvider::NewSocket(int32_t aFamily,
                                const char *aHost, 
                                int32_t aPort, 
                                nsIProxyInfo *aProxy,
+                               const nsACString &firstPartyDomain,
                                uint32_t aFlags,
                                PRFileDesc * *aFileDesc, 
                                nsISupports **aSecurityInfo)
 {
     NS_ENSURE_ARG_POINTER(aFileDesc);
   
     PRFileDesc* udpFD = PR_OpenUDPSocket(aFamily);
     if (!udpFD)
@@ -31,16 +32,17 @@ nsUDPSocketProvider::NewSocket(int32_t a
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsUDPSocketProvider::AddToSocket(int32_t aFamily,
                                  const char *aHost,
                                  int32_t aPort,
                                  nsIProxyInfo *aProxy,
+                                 const nsACString &firstPartyDomain,
                                  uint32_t aFlags,
                                  struct PRFileDesc * aFileDesc,
                                  nsISupports **aSecurityInfo)
 {
     // does not make sense to strap a UDP socket onto an existing socket
     NS_NOTREACHED("Cannot layer UDP socket on an existing socket");
     return NS_ERROR_UNEXPECTED;
 }
--- a/security/manager/ssl/nsSSLSocketProvider.cpp
+++ b/security/manager/ssl/nsSSLSocketProvider.cpp
@@ -18,16 +18,17 @@ nsSSLSocketProvider::~nsSSLSocketProvide
 
 NS_IMPL_ISUPPORTS(nsSSLSocketProvider, nsISocketProvider)
 
 NS_IMETHODIMP
 nsSSLSocketProvider::NewSocket(int32_t family,
                                const char *host,
                                int32_t port,
                                nsIProxyInfo *proxy,
+                               const nsACString &firstPartyDomain,
                                uint32_t flags,
                                PRFileDesc **_result,
                                nsISupports **securityInfo)
 {
   nsresult rv = nsSSLIOLayerNewSocket(family,
                                       host,
                                       port,
                                       proxy,
@@ -39,16 +40,17 @@ nsSSLSocketProvider::NewSocket(int32_t f
 }
 
 // Add the SSL IO layer to an existing socket
 NS_IMETHODIMP
 nsSSLSocketProvider::AddToSocket(int32_t family,
                                  const char *host,
                                  int32_t port,
                                  nsIProxyInfo *proxy,
+                                 const nsACString &firstPartyDomain,
                                  uint32_t flags,
                                  PRFileDesc *aSocket,
                                  nsISupports **securityInfo)
 {
   nsresult rv = nsSSLIOLayerAddToSocket(family,
                                         host,
                                         port,
                                         proxy,
--- a/security/manager/ssl/nsTLSSocketProvider.cpp
+++ b/security/manager/ssl/nsTLSSocketProvider.cpp
@@ -18,16 +18,17 @@ nsTLSSocketProvider::~nsTLSSocketProvide
 
 NS_IMPL_ISUPPORTS(nsTLSSocketProvider, nsISocketProvider)
 
 NS_IMETHODIMP
 nsTLSSocketProvider::NewSocket(int32_t family,
                                const char *host,
                                int32_t port,
                                nsIProxyInfo *proxy,
+                               const nsACString &firstPartyDomain,
                                uint32_t flags,
                                PRFileDesc **_result,
                                nsISupports **securityInfo)
 {
   nsresult rv = nsSSLIOLayerNewSocket(family,
                                       host,
                                       port,
                                       proxy,
@@ -40,16 +41,17 @@ nsTLSSocketProvider::NewSocket(int32_t f
 }
 
 // Add the SSL IO layer to an existing socket
 NS_IMETHODIMP
 nsTLSSocketProvider::AddToSocket(int32_t family,
                                  const char *host,
                                  int32_t port,
                                  nsIProxyInfo *proxy,
+                                 const nsACString &firstPartyDomain,
                                  uint32_t flags,
                                  PRFileDesc *aSocket,
                                  nsISupports **securityInfo)
 {
   nsresult rv = nsSSLIOLayerAddToSocket(family,
                                         host,
                                         port,
                                         proxy,