commit acaa131ffbc78c4355e49b7476941a1ad2c9da51
Author: Mike Perry <mikeperry-git(a)fscked.org>
Date: Wed May 2 17:57:33 2012 -0700
Add patch for #5741.
---
.../firefox/0018-Prevent-WebSocket-DNS-leak.patch | 132 ++++++++++++++++++++
1 files changed, 132 insertions(+), 0 deletions(-)
diff --git a/src/current-patches/firefox/0018-Prevent-WebSocket-DNS-leak.patch b/src/current-patches/firefox/0018-Prevent-WebSocket-DNS-leak.patch
new file mode 100644
index 0000000..9b30987
--- /dev/null
+++ b/src/current-patches/firefox/0018-Prevent-WebSocket-DNS-leak.patch
@@ -0,0 +1,132 @@
+From 93199734c06485660fb922c61f740191648a6dc6 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)torproject.org>
+Date: Wed, 2 May 2012 17:44:39 -0700
+Subject: [PATCH 18/18] Prevent WebSocket DNS leak.
+
+This is due to an improper implementation of the WebSocket spec by Mozilla.
+
+"There MUST be no more than one connection in a CONNECTING state. If multiple
+connections to the same IP address are attempted simultaneously, the client
+MUST serialize them so that there is no more than one connection at a time
+running through the following steps.
+
+If the client cannot determine the IP address of the remote host (for
+example, because all communication is being done through a proxy server that
+performs DNS queries itself), then the client MUST assume for the purposes of
+this step that each host name refers to a distinct remote host,"
+
+https://tools.ietf.org/html/rfc6455#page-15
+
+They implmented the first paragraph, but not the second...
+
+While we're at it, we also prevent the DNS service from being used to look up
+anything other than IP addresses if socks_remote_dns is set to true, so this
+bug can't turn up in other components or due to 3rd party addons.
+---
+ netwerk/dns/nsDNSService2.cpp | 24 ++++++++++++++++++++++-
+ netwerk/dns/nsDNSService2.h | 1 +
+ netwerk/protocol/websocket/WebSocketChannel.cpp | 8 +++++-
+ 3 files changed, 30 insertions(+), 3 deletions(-)
+
+diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp
+index 1bd5f38..eda0e48 100644
+--- a/netwerk/dns/nsDNSService2.cpp
++++ b/netwerk/dns/nsDNSService2.cpp
+@@ -404,6 +404,7 @@ nsDNSService::Init()
+ bool enableIDN = true;
+ bool disableIPv6 = false;
+ bool disablePrefetch = false;
++ bool disableDNS = false;
+ int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT;
+
+ nsAdoptingCString ipv4OnlyDomains;
+@@ -427,6 +428,10 @@ nsDNSService::Init()
+
+ // If a manual proxy is in use, disable prefetch implicitly
+ prefs->GetIntPref("network.proxy.type", &proxyType);
++
++ // If the user wants remote DNS, we should fail any lookups that still
++ // make it here.
++ prefs->GetBoolPref("network.proxy.socks_remote_dns", &disableDNS);
+ }
+
+ if (mFirstTime) {
+@@ -444,7 +449,7 @@ nsDNSService::Init()
+
+ // Monitor these to see if there is a change in proxy configuration
+ // If a manual proxy is in use, disable prefetch implicitly
+- prefs->AddObserver("network.proxy.type", this, false);
++ prefs->AddObserver("network.proxy.", this, false);
+ }
+ }
+
+@@ -473,6 +478,7 @@ nsDNSService::Init()
+ mIDN = idn;
+ mIPv4OnlyDomains = ipv4OnlyDomains; // exchanges buffer ownership
+ mDisableIPv6 = disableIPv6;
++ mDisableDNS = disableDNS;
+
+ // Disable prefetching either by explicit preference or if a manual proxy is configured
+ mDisablePrefetch = disablePrefetch || (proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL);
+@@ -584,6 +590,14 @@ nsDNSService::AsyncResolve(const nsACString &hostname,
+ if (mDisablePrefetch && (flags & RESOLVE_SPECULATE))
+ return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
+
++ PRNetAddr tempAddr;
++ if (mDisableDNS) {
++ // Allow IP lookups through, but nothing else.
++ if (PR_StringToNetAddr(hostname.BeginReading(), &tempAddr) != PR_SUCCESS) {
++ return NS_ERROR_UNKNOWN_PROXY_HOST; // XXX: NS_ERROR_NOT_IMPLEMENTED?
++ }
++ }
++
+ res = mResolver;
+ idn = mIDN;
+ }
+@@ -670,6 +684,14 @@ nsDNSService::Resolve(const nsACString &hostname,
+ MutexAutoLock lock(mLock);
+ res = mResolver;
+ idn = mIDN;
++
++ PRNetAddr tempAddr;
++ if (mDisableDNS) {
++ // Allow IP lookups through, but nothing else.
++ if (PR_StringToNetAddr(hostname.BeginReading(), &tempAddr) != PR_SUCCESS) {
++ return NS_ERROR_UNKNOWN_PROXY_HOST; // XXX: NS_ERROR_NOT_IMPLEMENTED?
++ }
++ }
+ }
+ NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE);
+
+diff --git a/netwerk/dns/nsDNSService2.h b/netwerk/dns/nsDNSService2.h
+index 1749b41..3ec8eba 100644
+--- a/netwerk/dns/nsDNSService2.h
++++ b/netwerk/dns/nsDNSService2.h
+@@ -70,4 +70,5 @@ private:
+ bool mDisableIPv6;
+ bool mDisablePrefetch;
+ bool mFirstTime;
++ bool mDisableDNS;
+ };
+diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp
+index 22873d3..0875c12 100644
+--- a/netwerk/protocol/websocket/WebSocketChannel.cpp
++++ b/netwerk/protocol/websocket/WebSocketChannel.cpp
+@@ -1875,8 +1875,12 @@ WebSocketChannel::ApplyForAdmission()
+ LOG(("WebSocketChannel::ApplyForAdmission: checking for concurrent open\n"));
+ nsCOMPtr<nsIThread> mainThread;
+ NS_GetMainThread(getter_AddRefs(mainThread));
+- dns->AsyncResolve(hostName, 0, this, mainThread, getter_AddRefs(mDNSRequest));
+- NS_ENSURE_SUCCESS(rv, rv);
++ rv = dns->AsyncResolve(hostName, 0, this, mainThread, getter_AddRefs(mDNSRequest));
++ if (NS_FAILED(rv)) {
++ // Fall back to hostname on dispatch failure
++ mDNSRequest = nsnull;
++ OnLookupComplete(nsnull, nsnull, rv);
++ }
+
+ return NS_OK;
+ }
+--
+1.7.5.4
+