tor-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
August 2011
- 19 participants
- 635 discussions

[torbrowser/maint-2.2] bump experimental TBBs to 2.2.31, tor to 0.2.2.31-rc, Firefox to 6.0, update other versions too
by erinn@torproject.org 20 Aug '11
by erinn@torproject.org 20 Aug '11
20 Aug '11
commit cdc9067b126c9cf6e9ea5c62e16d816b83e8e8e9
Author: Erinn Clark <erinn(a)torproject.org>
Date: Sat Aug 20 21:02:03 2011 +0200
bump experimental TBBs to 2.2.31, tor to 0.2.2.31-rc, Firefox to 6.0, update other versions too
---
README.LINUX-2.2 | 9 ++++-----
README.OSX-2.2 | 9 ++++-----
README.WIN-2.2 | 9 ++++-----
build-scripts/versions.mk | 14 +++++++-------
changelog.linux-2.2 | 12 ++++++++++++
changelog.osx-2.2 | …
[View More] 14 +++++++++++++-
changelog.win-2.2 | 14 +++++++++++++-
7 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/README.LINUX-2.2 b/README.LINUX-2.2
index c871c74..47f2684 100644
--- a/README.LINUX-2.2
+++ b/README.LINUX-2.2
@@ -5,12 +5,11 @@ Included applications
---------------------
Vidalia 0.2.12 (with Qt 4.6.2)
-Tor 0.2.2.30-rc (with libevent-2.0.12-stable, zlib-1.2.5 and openssl-1.0.0d)
-Firefox (Aurora) 5.0.1
+Tor 0.2.2.31-rc (with libevent-2.0.13-stable, zlib-1.2.5 and openssl-1.0.0d)
+Firefox (Aurora) 6.0
\_ Torbutton 1.4.0
- |_ NoScript 2.1.1.2
- |_ HTTPS-Everywhere 1.0.0development.4
- |_ BetterPrivacy 1.51
+ |_ NoScript 2.1.2.6
+ |_ HTTPS-Everywhere 1.0.0development.5
Usage
-----
diff --git a/README.OSX-2.2 b/README.OSX-2.2
index 88564a6..750e540 100644
--- a/README.OSX-2.2
+++ b/README.OSX-2.2
@@ -5,12 +5,11 @@ Included applications
---------------------
Vidalia 0.2.12 (with Qt 4.6.2)
-Tor 0.2.2.30-rc (with libevent-2.0.12-stable, zlib-1.2.5 and openssl-1.0.0d)
-Firefox (Aurora) 5.0.1
+Tor 0.2.2.31-rc (with libevent-2.0.13-stable, zlib-1.2.5 and openssl-1.0.0d)
+Firefox (Aurora) 6.0
\_ Torbutton 1.4.0
- |_ NoScript 2.1.1.2
- |_ HTTPS-Everywhere 1.0.0development.4
- |_ BetterPrivacy 1.51
+ |_ NoScript 2.1.2.6
+ |_ HTTPS-Everywhere 1.0.0development.5
Usage
-----
diff --git a/README.WIN-2.2 b/README.WIN-2.2
index dbe8ffb..519c64f 100644
--- a/README.WIN-2.2
+++ b/README.WIN-2.2
@@ -5,13 +5,12 @@ Included applications
---------------------
Vidalia 0.2.12 (with Qt 4.6.2)
-Tor 0.2.2.30-rc (with libevent-2.0.12-stable, zlib-1.2.5 and openssl-1.0.0d)
+Tor 0.2.2.31-rc (with libevent-2.0.13-stable, zlib-1.2.5 and openssl-1.0.0d)
FirefoxPortable 5.0.1
- \_ Firefox (Aurora) 5.0.1
+ \_ Firefox (Aurora) 6.0
\_ Torbutton 1.4.0
- |_ NoScript 2.1.1.2
- |_ HTTPS-Everywhere 1.0.0development.4
- |_ BetterPrivacy 1.51
+ |_ NoScript 2.1.2.6
+ |_ HTTPS-Everywhere 1.0.0development.5
Usage
-----
diff --git a/build-scripts/versions.mk b/build-scripts/versions.mk
index af23c30..e116326 100644
--- a/build-scripts/versions.mk
+++ b/build-scripts/versions.mk
@@ -1,21 +1,21 @@
#!/usr/bin/make
-RELEASE_VER=2.2.30
+RELEASE_VER=2.2.31
-HTTPSEVERY_VER=1.0.0development.4
-FIREFOX_VER=5.0.1
-LIBEVENT_VER=2.0.12-stable
+HTTPSEVERY_VER=1.0.0development.5
+FIREFOX_VER=6.0
+LIBEVENT_VER=2.0.13-stable
LIBPNG_VER=1.4.3
-NOSCRIPT_VER=2.1.1.2
+NOSCRIPT_VER=2.1.2.6
OPENSSL_VER=1.0.0d
OTR_VER=3.2.0
PIDGIN_VER=2.6.4
POLIPO_VER=1.0.4.1
QT_VER=4.6.2
-TOR_VER=0.2.2.30-rc
+TOR_VER=0.2.2.31-rc
TORBUTTON_VER=1.4.0
VIDALIA_VER=0.2.12
-ZLIB_VER=1.2.5
+ZLIB_VER=1.4.0
## Extension IDs
FF_VENDOR_ID:=\{ec8030f7-c20a-464f-9b0e-13a3a9e97384\}
diff --git a/changelog.linux-2.2 b/changelog.linux-2.2
index f9119c5..20d8bc5 100644
--- a/changelog.linux-2.2
+++ b/changelog.linux-2.2
@@ -1,3 +1,15 @@
+Tor Browser Bundle (2.2.30-1) alpha; suite=osx
+
+ * Update Tor to 0.2.2.31-rc
+ * Update Firefox to 6.0
+ * Update Libevent to 2.0.13-stable
+ * Update NoScript to 2.1.2.6
+ * Update HTTPS Everywhere to 1.0.0development.5
+ * Remove BetterPrivacy until we can figure out how to make it safe in all
+ bundles (see #3597)
+
+ -- Erinn Clark <erinn(a)torproject.org> Sat Aug 20 20:40:52 CEST 2011
+
Tor Browser Bundle (2.2.30-1) alpha; suite=linux
* Update Tor to 0.2.2.30-rc
diff --git a/changelog.osx-2.2 b/changelog.osx-2.2
index 888aaf5..ff6763d 100644
--- a/changelog.osx-2.2
+++ b/changelog.osx-2.2
@@ -1,8 +1,20 @@
+Tor Browser Bundle (2.2.30-1) alpha; suite=osx
+
+ * Update Tor to 0.2.2.31-rc
+ * Update Firefox to 6.0
+ * Update Libevent to 2.0.13-stable
+ * Update NoScript to 2.1.2.6
+ * Update HTTPS Everywhere to 1.0.0development.5
+ * Remove BetterPrivacy until we can figure out how to make it safe in all
+ bundles (see #3597)
+
+ -- Erinn Clark <erinn(a)torproject.org> Sat Aug 20 20:40:52 CEST 2011
+
Tor Browser Bundle (2.2.30-2) alpha; suite=osx
* Update Firefox to 5.0.1
- - Erinn Clark <erinn(a)torproject.org> Wed Jul 13 09:07:41 ART 2011
+ -- Erinn Clark <erinn(a)torproject.org> Wed Jul 13 09:07:41 ART 2011
Tor Browser Bundle (2.2.30-1) alpha; suite=osx
diff --git a/changelog.win-2.2 b/changelog.win-2.2
index ee916bc..bde8ad4 100644
--- a/changelog.win-2.2
+++ b/changelog.win-2.2
@@ -1,8 +1,20 @@
+Tor Browser Bundle (2.2.30-1) alpha; suite=osx
+
+ * Update Tor to 0.2.2.31-rc
+ * Update Firefox to 6.0
+ * Update Libevent to 2.0.13-stable
+ * Update NoScript to 2.1.2.6
+ * Update HTTPS Everywhere to 1.0.0development.5
+ * Remove BetterPrivacy until we can figure out how to make it safe in all
+ bundles (see #3597)
+
+ -- Erinn Clark <erinn(a)torproject.org> Sat Aug 20 20:40:52 CEST 2011
+
Tor Browser Bundle (2.2.30-2) alpha; suite=windows
* Update Firefox to 5.0.1
- - Erinn Clark <erinn(a)torproject.org> Wed Jul 13 09:07:41 ART 2011
+ -- Erinn Clark <erinn(a)torproject.org> Wed Jul 13 09:07:41 ART 2011
Tor Browser Bundle (2.2.30-1) alpha; suite=windows
[View Less]
1
0

20 Aug '11
commit a0e3aa031694051815911f74d71c37e5f779e48d
Author: Erinn Clark <erinn(a)torproject.org>
Date: Sat Aug 20 21:36:03 2011 +0200
remove betterprivacy from osx bundles
---
build-scripts/osx.mk | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/build-scripts/osx.mk b/build-scripts/osx.mk
index 1ab3a77..e1f005d 100644
--- a/build-scripts/osx.mk
+++ b/build-scripts/osx.mk
@@ -351,7 +351,7 @@ bundle_%:
compressed-bundle_%:
LANGCODE=$* make -f osx.mk …
[View More]compressed-bundle-localized
bundle-localized_%.stamp:
- make -f osx.mk copy-files_$* install-extensions install-betterprivacy install-httpseverywhere install-noscript install-lang-extensions patch-vidalia-language patch-firefox-language patch-pidgin-language update-extension-pref final
+ make -f osx.mk copy-files_$* install-extensions install-httpseverywhere install-noscript install-lang-extensions patch-vidalia-language patch-firefox-language patch-pidgin-language update-extension-pref final
touch bundle-localized_$*.stamp
cp extensions/torbutton.xpi .
[View Less]
1
0

[torbrowser/maint-2.2] update lots and lots of build targets for building firefox, fixing tabs, and making it easier to download & unpack all of the tarballs
by erinn@torproject.org 20 Aug '11
by erinn@torproject.org 20 Aug '11
20 Aug '11
commit a5f7328004ffef76cb954719f0f3749dc8e3b45f
Author: Erinn Clark <erinn(a)torproject.org>
Date: Sat Aug 20 21:35:01 2011 +0200
update lots and lots of build targets for building firefox, fixing tabs, and making it easier to download & unpack all of the tarballs
---
build-scripts/config/dot_mozconfig | 3 ---
build-scripts/linux.mk | 24 ++++++++++++++++++------
build-scripts/osx.mk | 4 ++++
build-scripts/versions.mk | 35 ++++++++…
[View More]+++++++++++++++++++++++----
build-scripts/windows.mk | 2 +-
5 files changed, 54 insertions(+), 14 deletions(-)
diff --git a/build-scripts/config/dot_mozconfig b/build-scripts/config/dot_mozconfig
index 7ba5ca6..934e4f4 100755
--- a/build-scripts/config/dot_mozconfig
+++ b/build-scripts/config/dot_mozconfig
@@ -3,9 +3,6 @@
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-@CONFIG_GUESS@
mk_add_options MOZ_APP_DISPLAYNAME=TorBrowser
-ac_add_options --enable-static
-ac_add_options --disable-shared
-ac_add_options --disable-libxul
ac_add_options --enable-optimize
ac_add_options --disable-tests
ac_add_options --disable-debug
diff --git a/build-scripts/linux.mk b/build-scripts/linux.mk
index aaeb11d..1a70edb 100644
--- a/build-scripts/linux.mk
+++ b/build-scripts/linux.mk
@@ -108,8 +108,20 @@ build-polipo:
build-pidgin:
echo "We're not building pidgin yet!"
+FIREFOX_DIR=$(FETCH_DIR)/mozilla-release
build-firefox:
- # XXX: add directions ASAP
+ cp ../src/current-patches/*Firefox* $(FIREFOX_DIR)
+ cp patch-firefox-src.sh $(FIREFOX_DIR)
+ cp $(CONFIG_SRC)/mozconfig-osx-$(ARCH_TYPE) $(FIREFOX_DIR)/mozconfig
+ cd $(FIREFOX_DIR) && ./patch-firefox-src.sh
+ cd $(FIREFOX_DIR) && make -f client.mk build
+
+copy-firefox:
+ -rm -rf $(FETCH_DIR)/Firefox
+ ## This is so ugly. Update it to use cool tar --transform soon.
+ cd $(FIREFOX_DIR) && make -C obj-$(ARCH_TYPE)-pc-linux-gnu/ package
+ cp $(FIREFOX_DIR)/obj-$(ARCH_TYPE)-pc-linux-gnu/*bz2 $(FETCH_DIR)
+ cd $(FETCH_DIR) && tar -xvjf firefox-$(FIREFOX_VER).en-US.bz2 && mv firefox Firefox
# source-dance unpack-source
build-all-binaries: source-dance build-zlib build-openssl build-libpng build-qt build-vidalia build-libevent build-tor build-polipo
@@ -269,9 +281,9 @@ install-binaries:
cp -d $(ZLIB)/libz.so $(ZLIB)/libz.so.1 $(ZLIB)/libz.so.1.2.5 $(LIBSDIR)/libz
# Libevent
cp -d $(LIBEVENT)/libevent-2.0.so.5 $(LIBEVENT)/libevent-2.0.so.5.0.1 $(LIBEVENT)/libevent_core.so \
- $(LIBEVENT)/libevent_core-2.0.so.5 $(LIBEVENT)/libevent_core-2.0.so.5.0.1 \
- $(LIBEVENT)/libevent_extra-2.0.so.5 $(LIBEVENT)/libevent_extra-2.0.so.5.0.1 \
- $(LIBEVENT)/libevent_extra.so $(LIBEVENT)/libevent.so $(LIBSDIR)
+ $(LIBEVENT)/libevent_core-2.0.so.5 $(LIBEVENT)/libevent_core-2.0.so.5.0.1 \
+ $(LIBEVENT)/libevent_extra-2.0.so.5 $(LIBEVENT)/libevent_extra-2.0.so.5.0.1 \
+ $(LIBEVENT)/libevent_extra.so $(LIBEVENT)/libevent.so $(LIBSDIR)
# libpng
cp -d $(LIBPNG)/libpng14.so* $(LIBSDIR)
# OpenSSL
@@ -436,8 +448,8 @@ patch-pidgin-language:
## Patch Pidgin
ifeq ($(USE_PIDGIN),1)
./patch-pidgin-language.sh $(BUNDLE)/PidginPortable/Data/settings/PidginPortableSettings.ini $(LANGCODE) \
- $(BUNDLE)/PidginPortable/App/Pidgin/locale \
- $(BUNDLE)/PidginPortable/App/GTK/share/locale
+ $(BUNDLE)/PidginPortable/App/Pidgin/locale \
+ $(BUNDLE)/PidginPortable/App/GTK/share/locale
endif
patch-firefox-language:
diff --git a/build-scripts/osx.mk b/build-scripts/osx.mk
index 7151ddf..1ab3a77 100644
--- a/build-scripts/osx.mk
+++ b/build-scripts/osx.mk
@@ -109,6 +109,10 @@ build-firefox:
cd $(FIREFOX_DIR) && ./patch-firefox-src.sh
cd $(FIREFOX_DIR) && make -f client.mk build
+copy-firefox:
+ -rm -rf $(FETCH_DIR)/Firefox.app
+ cp -r $(FIREFOX_DIR)/obj*/dist/*.app $(FETCH_DIR)/Firefox.app
+
build-all-binaries: build-zlib build-openssl build-vidalia build-libevent build-tor
echo "If we're here, we've done something right."
diff --git a/build-scripts/versions.mk b/build-scripts/versions.mk
index e116326..e8991a2 100644
--- a/build-scripts/versions.mk
+++ b/build-scripts/versions.mk
@@ -35,28 +35,55 @@ ZLIB_URL=http://www.zlib.net/$(ZLIB_PACKAGE)
OPENSSL_URL=http://www.openssl.org/source/$(OPENSSL_PACKAGE)
QT_URL=ftp://ftp.qt.nokia.com/qt/source/$(QT_PACKAGE)
VIDALIA_URL=http://www.torproject.org/dist/vidalia/$(VIDALIA_PACKAGE)
-LIBEVENT_URL=http://www.monkey.org/~provos/$(LIBEVENT_PACKAGE)
+LIBEVENT_URL=http://archive.torproject.org/tor-package-archive/libevent/$(LIBEVENT_PACKAGE)
TOR_URL=http://www.torproject.org/dist/$(TOR_PACKAGE)
PIDGIN_URL=http://sourceforge.net/projects/pidgin/files/Pidgin/$(PIDGIN_PAC…
FIREFOX_URL=http://releases.mozilla.org/pub/mozilla.org/firefox/releases/$(…
-fetch-source:
+fetch-source: fetch-zlib fetch-openssl fetch-vidalia fetch-libevent fetch-tor fetch-firefox
-mkdir $(FETCH_DIR)
+
+fetch-zlib:
$(WGET) --no-check-certificate --directory-prefix=$(FETCH_DIR) $(ZLIB_URL)
+
+fetch-openssl:
$(WGET) --no-check-certificate --directory-prefix=$(FETCH_DIR) $(OPENSSL_URL)
+
+fetch-vidalia:
$(WGET) --no-check-certificate --directory-prefix=$(FETCH_DIR) $(VIDALIA_URL)
+
+fetch-libevent:
$(WGET) --no-check-certificate --directory-prefix=$(FETCH_DIR) $(LIBEVENT_URL)
+
+fetch-tor:
$(WGET) --no-check-certificate --directory-prefix=$(FETCH_DIR) $(TOR_URL)
fetch-firefox:
-rm -rf $(FETCH_DIR)/mozilla-release
$(WGET) --no-check-certificate --directory-prefix=$(FETCH_DIR) $(FIREFOX_URL)
-unpack-source:
+unpack-source: unpack-zlib unpack-openssl unpack-vidalia unpack-libevent unpack-tor unpack-firefox
+
+unpack-zlib:
+ -rm -rf $(FETCH_DIR)/zlib-$(ZLIB_VER)
cd $(FETCH_DIR) && tar -xvzf $(ZLIB_PACKAGE)
+
+unpack-openssl:
+ -rm -rf $(FETCH_DIR)/openssl-$(OPENSSL_VER)
cd $(FETCH_DIR) && tar -xvzf $(OPENSSL_PACKAGE)
+
+unpack-vidalia:
+ -rm -rf $(FETCH_DIR)/vidalia-$(VIDALIA_VER)
cd $(FETCH_DIR) && tar -xvzf $(VIDALIA_PACKAGE)
+
+unpack-libevent:
+ -rm -rf $(FETCH_DIR)/libevent-$(LIBEVENT_VER)
cd $(FETCH_DIR) && tar -xvzf $(LIBEVENT_PACKAGE)
- cd $(FETCH_DIR) && tar -xvzf $(TOR_PACKAGE)
+unpack-tor:
+ -rm -rf $(FETCH_DIR)/tor-$(TOR-VER)
+ cd $(FETCH_DIR) && tar -xvzf $(TOR_PACKAGE)
+unpack-firefox:
+ -rm -rf $(FETCH_DIR)/mozilla-release
+ cd $(FETCH_DIR) && tar -xvjf $(FIREFOX_PACKAGE)
diff --git a/build-scripts/windows.mk b/build-scripts/windows.mk
index 1836741..da5dda1 100644
--- a/build-scripts/windows.mk
+++ b/build-scripts/windows.mk
@@ -359,7 +359,7 @@ split-bundle_%:
LANGCODE=$* make -f windows.mk split-bundle-localized
bundle-localized_%.stamp:
- make -f windows.mk copy-files_$* install-extensions install-torbutton install-httpseverywhere install-betterprivacy install-noscript patch-vidalia-language patch-firefox-language patch-pidgin-language
+ make -f windows.mk copy-files_$* install-extensions install-torbutton install-httpseverywhere install-noscript patch-vidalia-language patch-firefox-language patch-pidgin-language
touch bundle-localized_$*.stamp
bundle-localized: bundle-localized_$(LANGCODE).stamp
[View Less]
1
0

20 Aug '11
commit 50ef43974ea4bfe95835dfedc6719710d9e52d90
Author: Erinn Clark <erinn(a)torproject.org>
Date: Sat Aug 20 21:36:21 2011 +0200
new bundles are version 1, not 2
---
build-scripts/osx.mk | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/build-scripts/osx.mk b/build-scripts/osx.mk
index e1f005d..ebd265d 100644
--- a/build-scripts/osx.mk
+++ b/build-scripts/osx.mk
@@ -153,7 +153,7 @@ NAME=TorBrowser
DISTDIR=tbbosx-alpha-dist
## Version and name of the …
[View More]compressed bundle (also used for source)
-VERSION=$(RELEASE_VER)-2-alpha
+VERSION=$(RELEASE_VER)-1-alpha
DEFAULT_COMPRESSED_BASENAME=TorBrowser-$(VERSION)-osx-$(ARCH_TYPE)-
IM_COMPRESSED_BASENAME=TorBrowser-IM-$(VERSION)-
DEFAULT_COMPRESSED_NAME=$(DEFAULT_COMPRESSED_BASENAME)
[View Less]
1
0

[torbrowser/maint-2.2] Update Firefox patches for FF6, and slim them down.
by erinn@torproject.org 20 Aug '11
by erinn@torproject.org 20 Aug '11
20 Aug '11
commit 9fc85439ccb46e6b589fbac814631b35a5284bd8
Author: Mike Perry <mikeperry-git(a)fscked.org>
Date: Fri Aug 19 18:13:23 2011 -0700
Update Firefox patches for FF6, and slim them down.
Relocate old firefox patches to archive.
---
.../0001-Firefox4-Fix-SOCKS-timeout.patch | 1500 ++++++++++++++++++++
...ock-Components.interfaces-lookupMethod-fr.patch | 50 +
...ock-Components.interfaces-lookupMethod-fr.patch | 50 +
...-Make-Intermediate-Cert-Store-memory-only.…
[View More]patch | 300 ++++
...-Make-Intermediate-Cert-Store-memory-only.patch | 283 ++++
...fox5-Make-Permissions-Manager-memory-only.patch | 94 ++
...fox4-Make-Permissions-Manager-memory-only.patch | 94 ++
.../0001-Firefox4-Fix-SOCKS-timeout.patch | 1500 --------------------
...ock-Components.interfaces-lookupMethod-fr.patch | 50 -
...ock-Components.interfaces-lookupMethod-fr.patch | 50 +
...ock-Components.interfaces-lookupMethod-fr.patch | 50 -
...-Make-Intermediate-Cert-Store-memory-only.patch | 300 ----
...fox6-Make-Permissions-Manager-memory-only.patch | 94 ++
...-Make-Intermediate-Cert-Store-memory-only.patch | 283 ----
...fox5-Make-Permissions-Manager-memory-only.patch | 94 --
...-Make-Intermediate-Cert-Store-memory-only.patch | 43 +
...fox4-Make-Permissions-Manager-memory-only.patch | 94 --
17 files changed, 2558 insertions(+), 2371 deletions(-)
diff --git a/src/archived-patches/0001-Firefox4-Fix-SOCKS-timeout.patch b/src/archived-patches/0001-Firefox4-Fix-SOCKS-timeout.patch
new file mode 100644
index 0000000..3b9343e
--- /dev/null
+++ b/src/archived-patches/0001-Firefox4-Fix-SOCKS-timeout.patch
@@ -0,0 +1,1500 @@
+From d37dce07b9eb9b40244d2fa867728e7a57a33f0f Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Mon, 20 Jun 2011 17:07:33 -0700
+Subject: [PATCH 1/4] Firefox4: Fix SOCKS timeout
+
+This patch by chrisd removes the hardcoded SOCKS timeout by rewriting the
+Firefox SOCKS code to use non-blocking IO.
+
+See also: https://bugzilla.mozilla.org/show_bug.cgi?id=280661
+https://trac.torproject.org/projects/tor/ticket/3247
+---
+ netwerk/base/src/nsSocketTransport2.cpp | 21 +-
+ netwerk/socket/nsSOCKSIOLayer.cpp | 1273 ++++++++++++++++++-------------
+ 2 files changed, 775 insertions(+), 519 deletions(-)
+
+diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp
+index 3f95dfd..fb363db 100644
+--- a/netwerk/base/src/nsSocketTransport2.cpp
++++ b/netwerk/base/src/nsSocketTransport2.cpp
+@@ -1227,6 +1227,16 @@ nsSocketTransport::InitiateSocket()
+ }
+ }
+ //
++ // A SOCKS request was rejected; get the actual error code from
++ // the OS error
++ //
++ else if (PR_UNKNOWN_ERROR == code &&
++ mProxyTransparent &&
++ !mProxyHost.IsEmpty()) {
++ code = PR_GetOSError();
++ rv = ErrorAccordingToNSPR(code);
++ }
++ //
+ // The connection was refused...
+ //
+ else {
+@@ -1549,7 +1559,16 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 outFlags)
+ mPollFlags = (PR_POLL_EXCEPT | PR_POLL_WRITE);
+ // Update poll timeout in case it was changed
+ mPollTimeout = mTimeouts[TIMEOUT_CONNECT];
+- }
++ }
++ //
++ // The SOCKS proxy rejected our request. Find out why.
++ //
++ else if (PR_UNKNOWN_ERROR == code &&
++ mProxyTransparent &&
++ !mProxyHost.IsEmpty()) {
++ code = PR_GetOSError();
++ mCondition = ErrorAccordingToNSPR(code);
++ }
+ else {
+ //
+ // else, the connection failed...
+diff --git a/netwerk/socket/nsSOCKSIOLayer.cpp b/netwerk/socket/nsSOCKSIOLayer.cpp
+index 9a15667..4d3a4e8 100644
+--- a/netwerk/socket/nsSOCKSIOLayer.cpp
++++ b/netwerk/socket/nsSOCKSIOLayer.cpp
+@@ -25,6 +25,7 @@
+ * Bradley Baetz <bbaetz(a)acm.org>
+ * Darin Fisher <darin(a)meer.net>
+ * Malcolm Smith <malsmith(a)cs.rmit.edu.au>
++ * Christopher Davis <chrisd(a)torproject.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+@@ -68,9 +69,28 @@ static PRLogModuleInfo *gSOCKSLog;
+
+ class nsSOCKSSocketInfo : public nsISOCKSSocketInfo
+ {
++ enum State {
++ SOCKS_INITIAL,
++ SOCKS_CONNECTING_TO_PROXY,
++ SOCKS4_WRITE_CONNECT_REQUEST,
++ SOCKS4_READ_CONNECT_RESPONSE,
++ SOCKS5_WRITE_AUTH_REQUEST,
++ SOCKS5_READ_AUTH_RESPONSE,
++ SOCKS5_WRITE_CONNECT_REQUEST,
++ SOCKS5_READ_CONNECT_RESPONSE_TOP,
++ SOCKS5_READ_CONNECT_RESPONSE_BOTTOM,
++ SOCKS_CONNECTED,
++ SOCKS_FAILED
++ };
++
++ // A buffer of 262 bytes should be enough for any request and response
++ // in case of SOCKS4 as well as SOCKS5
++ static const PRUint32 BUFFER_SIZE = 262;
++ static const PRUint32 MAX_HOSTNAME_LEN = 255;
++
+ public:
+ nsSOCKSSocketInfo();
+- virtual ~nsSOCKSSocketInfo() {}
++ virtual ~nsSOCKSSocketInfo() { HandshakeFinished(); }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISOCKSSOCKETINFO
+@@ -81,13 +101,50 @@ public:
+ const char *destinationHost,
+ PRUint32 flags);
+
+- const nsCString &DestinationHost() { return mDestinationHost; }
+- const nsCString &ProxyHost() { return mProxyHost; }
+- PRInt32 ProxyPort() { return mProxyPort; }
+- PRInt32 Version() { return mVersion; }
+- PRUint32 Flags() { return mFlags; }
++ void SetConnectTimeout(PRIntervalTime to);
++ PRStatus DoHandshake(PRFileDesc *fd, PRInt16 oflags = -1);
++ PRInt16 GetPollFlags() const;
++ bool IsConnected() const { return mState == SOCKS_CONNECTED; }
++
++private:
++ void HandshakeFinished(PRErrorCode err = 0);
++ PRStatus ConnectToProxy(PRFileDesc *fd);
++ PRStatus ContinueConnectingToProxy(PRFileDesc *fd, PRInt16 oflags);
++ PRStatus WriteV4ConnectRequest();
++ PRStatus ReadV4ConnectResponse();
++ PRStatus WriteV5AuthRequest();
++ PRStatus ReadV5AuthResponse();
++ PRStatus WriteV5ConnectRequest();
++ PRStatus ReadV5AddrTypeAndLength(PRUint8 *type, PRUint32 *len);
++ PRStatus ReadV5ConnectResponseTop();
++ PRStatus ReadV5ConnectResponseBottom();
++
++ void WriteUint8(PRUint8 d);
++ void WriteUint16(PRUint16 d);
++ void WriteUint32(PRUint32 d);
++ void WriteNetAddr(const PRNetAddr *addr);
++ void WriteNetPort(const PRNetAddr *addr);
++ void WriteString(const nsACString &str);
++
++ PRUint8 ReadUint8();
++ PRUint16 ReadUint16();
++ PRUint32 ReadUint32();
++ void ReadNetAddr(PRNetAddr *addr, PRUint16 fam);
++ void ReadNetPort(PRNetAddr *addr);
++
++ void WantRead(PRUint32 sz);
++ PRStatus ReadFromSocket(PRFileDesc *fd);
++ PRStatus WriteToSocket(PRFileDesc *fd);
+
+ private:
++ State mState;
++ PRUint8 * mData;
++ PRUint8 * mDataIoPtr;
++ PRUint32 mDataLength;
++ PRUint32 mReadOffset;
++ PRUint32 mAmountToRead;
++ nsCOMPtr<nsIDNSRecord> mDnsRec;
++
+ nsCString mDestinationHost;
+ nsCString mProxyHost;
+ PRInt32 mProxyPort;
+@@ -96,13 +153,21 @@ private:
+ PRNetAddr mInternalProxyAddr;
+ PRNetAddr mExternalProxyAddr;
+ PRNetAddr mDestinationAddr;
++ PRIntervalTime mTimeout;
+ };
+
+ nsSOCKSSocketInfo::nsSOCKSSocketInfo()
+- : mProxyPort(-1)
++ : mState(SOCKS_INITIAL)
++ , mDataIoPtr(nsnull)
++ , mDataLength(0)
++ , mReadOffset(0)
++ , mAmountToRead(0)
++ , mProxyPort(-1)
+ , mVersion(-1)
+ , mFlags(0)
++ , mTimeout(PR_INTERVAL_NO_TIMEOUT)
+ {
++ mData = new PRUint8[BUFFER_SIZE];
+ PR_InitializeNetAddr(PR_IpAddrAny, 0, &mInternalProxyAddr);
+ PR_InitializeNetAddr(PR_IpAddrAny, 0, &mExternalProxyAddr);
+ PR_InitializeNetAddr(PR_IpAddrAny, 0, &mDestinationAddr);
+@@ -162,637 +227,807 @@ nsSOCKSSocketInfo::SetInternalProxyAddr(PRNetAddr *aInternalProxyAddr)
+ return NS_OK;
+ }
+
+-static PRInt32
+-pr_RecvAll(PRFileDesc *fd, unsigned char *buf, PRInt32 amount, PRIntn flags,
+- PRIntervalTime *timeout)
++// There needs to be a means of distinguishing between connection errors
++// that the SOCKS server reports when it rejects a connection request, and
++// connection errors that happen while attempting to connect to the SOCKS
++// server. Otherwise, Firefox will report incorrectly that the proxy server
++// is refusing connections when a SOCKS request is rejected by the proxy.
++// When a SOCKS handshake failure occurs, the PR error is set to
++// PR_UNKNOWN_ERROR, and the real error code is returned via the OS error.
++void
++nsSOCKSSocketInfo::HandshakeFinished(PRErrorCode err)
+ {
+- PRInt32 bytesRead = 0;
+- PRInt32 offset = 0;
++ if (err == 0) {
++ mState = SOCKS_CONNECTED;
++ } else {
++ mState = SOCKS_FAILED;
++ PR_SetError(PR_UNKNOWN_ERROR, err);
++ }
+
+- while (offset < amount) {
+- PRIntervalTime start_time = PR_IntervalNow();
+- bytesRead = PR_Recv(fd, buf + offset, amount - offset, flags, *timeout);
+- PRIntervalTime elapsed = PR_IntervalNow() - start_time;
++ // We don't need the buffer any longer, so free it.
++ delete [] mData;
++ mData = nsnull;
++ mDataIoPtr = nsnull;
++ mDataLength = 0;
++ mReadOffset = 0;
++ mAmountToRead = 0;
++}
+
+- if (elapsed > *timeout) {
+- *timeout = 0;
+- } else {
+- *timeout -= elapsed;
+- }
++PRStatus
++nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc *fd)
++{
++ PRStatus status;
++ nsresult rv;
+
+- if (bytesRead > 0) {
+- offset += bytesRead;
+- } else if (bytesRead == 0 || offset != 0) {
+- return offset;
+- } else {
+- return bytesRead;
+- }
++ NS_ABORT_IF_FALSE(mState == SOCKS_INITIAL,
++ "Must be in initial state to make connection!");
+
+- if (*timeout == 0) {
+- LOGERROR(("PR_Recv() timed out. amount = %d. offset = %d.",
+- amount, offset));
+- return offset;
++ // If we haven't performed the DNS lookup, do that now.
++ if (!mDnsRec) {
++ nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
++ if (!dns)
++ return PR_FAILURE;
++
++ rv = dns->Resolve(mProxyHost, 0, getter_AddRefs(mDnsRec));
++ if (NS_FAILED(rv)) {
++ LOGERROR(("socks: DNS lookup for SOCKS proxy %s failed",
++ mProxyHost.get()));
++ return PR_FAILURE;
+ }
+ }
+- return offset;
+-}
+
+-static PRInt32
+-pr_Send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+- PRIntervalTime *timeout)
+-{
+- PRIntervalTime start_time = PR_IntervalNow();
+- PRInt32 retval = PR_Send(fd, buf, amount, flags, *timeout);
+- PRIntervalTime elapsed = PR_IntervalNow() - start_time;
+-
+- if (elapsed > *timeout) {
+- *timeout = 0;
+- LOGERROR(("PR_Send() timed out. amount = %d. retval = %d.",
+- amount, retval));
+- return retval;
+- } else {
+- *timeout -= elapsed;
+- }
++ do {
++ rv = mDnsRec->GetNextAddr(mProxyPort, &mInternalProxyAddr);
++ // No more addresses to try? If so, we'll need to bail
++ if (NS_FAILED(rv)) {
++ LOGERROR(("socks: unable to connect to SOCKS proxy, %s",
++ mProxyHost.get()));
++ return PR_FAILURE;
++ }
+
+- if (retval <= 0) {
+- LOGERROR(("PR_Send() failed. amount = %d. retval = %d.",
+- amount, retval));
+- }
++#if defined(PR_LOGGING)
++ char buf[64];
++ PR_NetAddrToString(&mInternalProxyAddr, buf, sizeof(buf));
++ LOGDEBUG(("socks: trying proxy server, %s:%hu",
++ buf, PR_ntohs(PR_NetAddrInetPort(&mInternalProxyAddr))));
++#endif
++ status = fd->lower->methods->connect(fd->lower,
++ &mInternalProxyAddr, mTimeout);
++ if (status != PR_SUCCESS) {
++ PRErrorCode c = PR_GetError();
++ // If EINPROGRESS, return now and check back later after polling
++ if (c == PR_WOULD_BLOCK_ERROR || c == PR_IN_PROGRESS_ERROR) {
++ mState = SOCKS_CONNECTING_TO_PROXY;
++ return status;
++ }
++ }
++ } while (status != PR_SUCCESS);
+
+- return retval;
++ // Connected now, start SOCKS
++ if (mVersion == 4)
++ return WriteV4ConnectRequest();
++ return WriteV5AuthRequest();
+ }
+
+-// Negotiate a SOCKS 5 connection. Assumes the TCP connection to the socks
+-// server port has been established.
+-static nsresult
+-ConnectSOCKS5(PRFileDesc *fd, const PRNetAddr *addr, PRNetAddr *extAddr, PRIntervalTime timeout)
++PRStatus
++nsSOCKSSocketInfo::ContinueConnectingToProxy(PRFileDesc *fd, PRInt16 oflags)
+ {
+- int request_len = 0;
+- int response_len = 0;
+- int desired_len = 0;
+- unsigned char request[22];
+- unsigned char response[262];
+-
+- NS_ENSURE_TRUE(fd, NS_ERROR_NOT_INITIALIZED);
+- NS_ENSURE_TRUE(addr, NS_ERROR_NOT_INITIALIZED);
+- NS_ENSURE_TRUE(extAddr, NS_ERROR_NOT_INITIALIZED);
+-
+- request[0] = 0x05; // SOCKS version 5
+- request[1] = 0x01; // number of auth procotols we recognize
+- // auth protocols
+- request[2] = 0x00; // no authentication required
+- // compliant implementations MUST implement GSSAPI
+- // and SHOULD implement username/password and MAY
+- // implement CHAP
+- // TODO: we don't implement these
+- //request[3] = 0x01; // GSSAPI
+- //request[4] = 0x02; // username/password
+- //request[5] = 0x03; // CHAP
++ PRStatus status;
+
+- request_len = 2 + request[1];
+- int write_len = pr_Send(fd, request, request_len, 0, &timeout);
+- if (write_len != request_len) {
+- return NS_ERROR_FAILURE;
+- }
++ NS_ABORT_IF_FALSE(mState == SOCKS_CONNECTING_TO_PROXY,
++ "Continuing connection in wrong state!");
+
+- // get the server's response.
+- desired_len = 2;
+- response_len = pr_RecvAll(fd, response, desired_len, 0, &timeout);
++ LOGDEBUG(("socks: continuing connection to proxy"));
+
+- if (response_len < desired_len) {
+- LOGERROR(("pr_RecvAll() failed. response_len = %d.", response_len));
+- return NS_ERROR_FAILURE;
+- }
++ status = fd->lower->methods->connectcontinue(fd->lower, oflags);
++ if (status != PR_SUCCESS) {
++ PRErrorCode c = PR_GetError();
++ if (c != PR_WOULD_BLOCK_ERROR && c != PR_IN_PROGRESS_ERROR) {
++ // A connection failure occured, try another address
++ mState = SOCKS_INITIAL;
++ return ConnectToProxy(fd);
++ }
+
+- if (response[0] != 0x05) {
+- // it's a either not SOCKS or not our version
+- LOGERROR(("Not a SOCKS 5 reply. Expected: 5; received: %x", response[0]));
+- return NS_ERROR_FAILURE;
+- }
+- switch (response[1]) {
+- case 0x00:
+- // no auth
+- break;
+- case 0x01:
+- // GSSAPI
+- // TODO: implement
+- LOGERROR(("Server want to use GSSAPI to authenticate, but we don't support it."));
+- return NS_ERROR_FAILURE;
+- case 0x02:
+- // username/password
+- // TODO: implement
+- LOGERROR(("Server want to use username/password to authenticate, but we don't support it."));
+- return NS_ERROR_FAILURE;
+- case 0x03:
+- // CHAP
+- // TODO: implement?
+- LOGERROR(("Server want to use CHAP to authenticate, but we don't support it."));
+- return NS_ERROR_FAILURE;
+- default:
+- // unrecognized auth method
+- LOGERROR(("Uncrecognized authentication method received: %x", response[1]));
+- return NS_ERROR_FAILURE;
++ // We're still connecting
++ return PR_FAILURE;
+ }
+
+- // we are now authenticated, so lets tell
+- // the server where to connect to
++ // Connected now, start SOCKS
++ if (mVersion == 4)
++ return WriteV4ConnectRequest();
++ return WriteV5AuthRequest();
++}
+
+- request_len = 0;
++PRStatus
++nsSOCKSSocketInfo::WriteV4ConnectRequest()
++{
++ PRNetAddr *addr = &mDestinationAddr;
++ PRInt32 proxy_resolve;
+
+- request[0] = 0x05; // SOCKS version 5
+- request[1] = 0x01; // CONNECT command
+- request[2] = 0x00; // obligatory reserved field (perfect for MS tampering!)
++ NS_ABORT_IF_FALSE(mState == SOCKS_CONNECTING_TO_PROXY,
++ "Invalid state!");
++
++ proxy_resolve = mFlags & nsISocketProvider::PROXY_RESOLVES_HOST;
++
++ mDataLength = 0;
++ mState = SOCKS4_WRITE_CONNECT_REQUEST;
++
++ LOGDEBUG(("socks4: sending connection request (socks4a resolve? %s)",
++ proxy_resolve? "yes" : "no"));
++
++ // Send a SOCKS 4 connect request.
++ WriteUint8(0x04); // version -- 4
++ WriteUint8(0x01); // command -- connect
++ WriteNetPort(addr);
++ if (proxy_resolve) {
++ // Add the full name, null-terminated, to the request
++ // according to SOCKS 4a. A fake IP address, with the first
++ // four bytes set to 0 and the last byte set to something other
++ // than 0, is used to notify the proxy that this is a SOCKS 4a
++ // request. This request type works for Tor and perhaps others.
++ WriteUint32(PR_htonl(0x00000001)); // Fake IP
++ WriteUint8(0x00); // Send an emtpy username
++ if (mDestinationHost.Length() > MAX_HOSTNAME_LEN) {
++ LOGERROR(("socks4: destination host name is too long!"));
++ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
++ return PR_FAILURE;
++ }
++ WriteString(mDestinationHost); // Hostname
++ WriteUint8(0x00);
++ } else if (PR_NetAddrFamily(addr) == PR_AF_INET) {
++ WriteNetAddr(addr); // Add the IPv4 address
++ WriteUint8(0x00); // Send an emtpy username
++ } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
++ LOGERROR(("socks: SOCKS 4 can't handle IPv6 addresses!"));
++ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
++ return PR_FAILURE;
++ }
+
+- // get destination port
+- PRInt32 destPort = PR_ntohs(PR_NetAddrInetPort(addr));
+- nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
++ return PR_SUCCESS;
++}
+
+- if (info->Flags() & nsISocketProvider::PROXY_RESOLVES_HOST) {
++PRStatus
++nsSOCKSSocketInfo::ReadV4ConnectResponse()
++{
++ NS_ABORT_IF_FALSE(mState == SOCKS4_READ_CONNECT_RESPONSE,
++ "Handling SOCKS 4 connection reply in wrong state!");
++ NS_ABORT_IF_FALSE(mDataLength == 8,
++ "SOCKS 4 connection reply must be 8 bytes!");
+
+- LOGDEBUG(("using server to resolve hostnames rather than resolving it first\n"));
++ LOGDEBUG(("socks4: checking connection reply"));
+
+- // if the PROXY_RESOLVES_HOST flag is set, we assume
+- // that the transport wants us to pass the SOCKS server the
+- // hostname and port and let it do the name resolution.
++ if (ReadUint8() != 0x00) {
++ LOGERROR(("socks4: wrong connection reply"));
++ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
++ return PR_FAILURE;
++ }
+
+- // the real destination hostname and port was stored
+- // in our info object earlier when this layer was created.
++ // See if our connection request was granted
++ if (ReadUint8() == 90) {
++ LOGDEBUG(("socks4: connection successful!"));
++ HandshakeFinished();
++ return PR_SUCCESS;
++ }
+
+- const nsCString& destHost = info->DestinationHost();
++ LOGERROR(("socks4: unable to connect"));
++ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
++ return PR_FAILURE;
++}
+
+- LOGDEBUG(("host:port -> %s:%li", destHost.get(), destPort));
++PRStatus
++nsSOCKSSocketInfo::WriteV5AuthRequest()
++{
++ NS_ABORT_IF_FALSE(mVersion == 5, "SOCKS version must be 5!");
+
+- request[3] = 0x03; // encoding of destination address (3 == hostname)
++ mState = SOCKS5_WRITE_AUTH_REQUEST;
+
+- int host_len = destHost.Length();
+- if (host_len > 255) {
+- // SOCKS5 transmits the length of the hostname in a single char.
+- // This gives us an absolute limit of 255 chars in a hostname, and
+- // there's nothing we can do to extend it. I don't think many
+- // hostnames will ever be bigger than this, so hopefully it's an
+- // uneventful abort condition.
+- LOGERROR (("Hostname too big for SOCKS5."));
+- return NS_ERROR_INVALID_ARG;
+- }
+- request[4] = (char) host_len;
+- request_len = 5;
+-
+- // Send the initial header first...
+- write_len = pr_Send(fd, request, request_len, 0, &timeout);
+- if (write_len != request_len) {
+- // bad write
+- return NS_ERROR_FAILURE;
+- }
++ // Send an initial SOCKS 5 greeting
++ LOGDEBUG(("socks5: sending auth methods"));
++ WriteUint8(0x05); // version -- 5
++ WriteUint8(0x01); // # auth methods -- 1
++ WriteUint8(0x00); // we don't support authentication
+
+- // Now send the hostname...
+- write_len = pr_Send(fd, destHost.get(), host_len, 0, &timeout);
+- if (write_len != host_len) {
+- // bad write
+- return NS_ERROR_FAILURE;
+- }
++ return PR_SUCCESS;
++}
+
+- // There's no data left because we just sent it.
+- request_len = 0;
++PRStatus
++nsSOCKSSocketInfo::ReadV5AuthResponse()
++{
++ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_AUTH_RESPONSE,
++ "Handling SOCKS 5 auth method reply in wrong state!");
++ NS_ABORT_IF_FALSE(mDataLength == 2,
++ "SOCKS 5 auth method reply must be 2 bytes!");
+
+- } else if (PR_NetAddrFamily(addr) == PR_AF_INET) {
++ LOGDEBUG(("socks5: checking auth method reply"));
+
+- request[3] = 0x01; // encoding of destination address (1 == IPv4)
+- request_len = 8; // 4 for address, 4 SOCKS headers
++ // Check version number
++ if (ReadUint8() != 0x05) {
++ LOGERROR(("socks5: unexpected version in the reply"));
++ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
++ return PR_FAILURE;
++ }
+
+- char * ip = (char*)(&addr->inet.ip);
+- request[4] = *ip++;
+- request[5] = *ip++;
+- request[6] = *ip++;
+- request[7] = *ip++;
++ // Make sure our authentication choice was accepted
++ if (ReadUint8() != 0x00) {
++ LOGERROR(("socks5: server did not accept our authentication method"));
++ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
++ return PR_FAILURE;
++ }
+
+- } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
++ return WriteV5ConnectRequest();
++}
+
+- request[3] = 0x04; // encoding of destination address (4 == IPv6)
+- request_len = 20; // 16 for address, 4 SOCKS headers
+-
+- char * ip = (char*)(&addr->ipv6.ip.pr_s6_addr);
+- request[4] = *ip++; request[5] = *ip++;
+- request[6] = *ip++; request[7] = *ip++;
+- request[8] = *ip++; request[9] = *ip++;
+- request[10] = *ip++; request[11] = *ip++;
+- request[12] = *ip++; request[13] = *ip++;
+- request[14] = *ip++; request[15] = *ip++;
+- request[16] = *ip++; request[17] = *ip++;
+- request[18] = *ip++; request[19] = *ip++;
+-
+- // we're going to test to see if this address can
+- // be mapped back into IPv4 without loss. if so,
+- // we'll use IPv4 instead, as reliable SOCKS server
+- // support for IPv6 is probably questionable.
+-
+- if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
+- request[3] = 0x01; // ipv4 encoding
+- request[4] = request[16];
+- request[5] = request[17];
+- request[6] = request[18];
+- request[7] = request[19];
+- request_len -= 12;
++PRStatus
++nsSOCKSSocketInfo::WriteV5ConnectRequest()
++{
++ // Send SOCKS 5 connect request
++ PRNetAddr *addr = &mDestinationAddr;
++ PRInt32 proxy_resolve;
++ proxy_resolve = mFlags & nsISocketProvider::PROXY_RESOLVES_HOST;
++
++ LOGDEBUG(("socks5: sending connection request (socks5 resolve? %s)",
++ proxy_resolve? "yes" : "no"));
++
++ mDataLength = 0;
++ mState = SOCKS5_WRITE_CONNECT_REQUEST;
++
++ WriteUint8(0x05); // version -- 5
++ WriteUint8(0x01); // command -- connect
++ WriteUint8(0x00); // reserved
++
++ // Add the address to the SOCKS 5 request. SOCKS 5 supports several
++ // address types, so we pick the one that works best for us.
++ if (proxy_resolve) {
++ // Add the host name. Only a single byte is used to store the length,
++ // so we must prevent long names from being used.
++ if (mDestinationHost.Length() > MAX_HOSTNAME_LEN) {
++ LOGERROR(("socks5: destination host name is too long!"));
++ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
++ return PR_FAILURE;
+ }
++ WriteUint8(0x03); // addr type -- domainname
++ WriteUint8(mDestinationHost.Length()); // name length
++ WriteString(mDestinationHost);
++ } else if (PR_NetAddrFamily(addr) == PR_AF_INET) {
++ WriteUint8(0x01); // addr type -- IPv4
++ WriteNetAddr(addr);
++ } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
++ WriteUint8(0x04); // addr type -- IPv6
++ WriteNetAddr(addr);
+ } else {
+- // Unknown address type
+- LOGERROR(("Don't know what kind of IP address this is."));
+- return NS_ERROR_FAILURE;
+- }
+-
+- // add the destination port to the request
+- request[request_len] = (unsigned char)(destPort >> 8);
+- request[request_len+1] = (unsigned char)destPort;
+- request_len += 2;
+-
+- write_len = pr_Send(fd, request, request_len, 0, &timeout);
+- if (write_len != request_len) {
+- // bad write
+- return NS_ERROR_FAILURE;
++ LOGERROR(("socks5: destination address of unknown type!"));
++ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
++ return PR_FAILURE;
+ }
+
+- desired_len = 5;
+- response_len = pr_RecvAll(fd, response, desired_len, 0, &timeout);
+- if (response_len < desired_len) { // bad read
+- LOGERROR(("pr_RecvAll() failed getting connect command reply. response_len = %d.", response_len));
+- return NS_ERROR_FAILURE;
+- }
++ WriteNetPort(addr); // port
+
+- if (response[0] != 0x05) {
+- // bad response
+- LOGERROR(("Not a SOCKS 5 reply. Expected: 5; received: %x", response[0]));
+- return NS_ERROR_FAILURE;
+- }
++ return PR_SUCCESS;
++}
+
+- switch(response[1]) {
+- case 0x00: break; // success
+- case 0x01: LOGERROR(("SOCKS 5 server rejected connect request: 01, General SOCKS server failure."));
+- return NS_ERROR_FAILURE;
+- case 0x02: LOGERROR(("SOCKS 5 server rejected connect request: 02, Connection not allowed by ruleset."));
+- return NS_ERROR_FAILURE;
+- case 0x03: LOGERROR(("SOCKS 5 server rejected connect request: 03, Network unreachable."));
+- return NS_ERROR_FAILURE;
+- case 0x04: LOGERROR(("SOCKS 5 server rejected connect request: 04, Host unreachable."));
+- return NS_ERROR_FAILURE;
+- case 0x05: LOGERROR(("SOCKS 5 server rejected connect request: 05, Connection refused."));
+- return NS_ERROR_FAILURE;
+- case 0x06: LOGERROR(("SOCKS 5 server rejected connect request: 06, TTL expired."));
+- return NS_ERROR_FAILURE;
+- case 0x07: LOGERROR(("SOCKS 5 server rejected connect request: 07, Command not supported."));
+- return NS_ERROR_FAILURE;
+- case 0x08: LOGERROR(("SOCKS 5 server rejected connect request: 08, Address type not supported."));
+- return NS_ERROR_FAILURE;
+- default: LOGERROR(("SOCKS 5 server rejected connect request: %x.", response[1]));
+- return NS_ERROR_FAILURE;
+-
+-
+- }
+-
+- switch (response[3]) {
+- case 0x01: // IPv4
+- desired_len = 4 + 2 - 1;
+- break;
+- case 0x03: // FQDN
+- desired_len = response[4] + 2;
++PRStatus
++nsSOCKSSocketInfo::ReadV5AddrTypeAndLength(PRUint8 *type, PRUint32 *len)
++{
++ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_CONNECT_RESPONSE_TOP ||
++ mState == SOCKS5_READ_CONNECT_RESPONSE_BOTTOM,
++ "Invalid state!");
++ NS_ABORT_IF_FALSE(mDataLength >= 5,
++ "SOCKS 5 connection reply must be at least 5 bytes!");
++
++ // Seek to the address location
++ mReadOffset = 3;
++
++ *type = ReadUint8();
++
++ switch (*type) {
++ case 0x01: // ipv4
++ *len = 4 - 1;
+ break;
+- case 0x04: // IPv6
+- desired_len = 16 + 2 - 1;
++ case 0x04: // ipv6
++ *len = 16 - 1;
+ break;
+- default: // unknown format
+- return NS_ERROR_FAILURE;
++ case 0x03: // fqdn
++ *len = ReadUint8();
+ break;
++ default: // wrong address type
++ LOGERROR(("socks5: wrong address type in connection reply!"));
++ return PR_FAILURE;
+ }
+- response_len = pr_RecvAll(fd, response + 5, desired_len, 0, &timeout);
+- if (response_len < desired_len) { // bad read
+- LOGERROR(("pr_RecvAll() failed getting connect command reply. response_len = %d.", response_len));
+- return NS_ERROR_FAILURE;
+- }
+- response_len += 5;
+
+- // get external bound address (this is what
+- // the outside world sees as "us")
+- char *ip = nsnull;
+- PRUint16 extPort = 0;
++ return PR_SUCCESS;
++}
+
+- switch (response[3]) {
+- case 0x01: // IPv4
++PRStatus
++nsSOCKSSocketInfo::ReadV5ConnectResponseTop()
++{
++ PRUint8 res;
++ PRUint32 len;
+
+- extPort = (response[8] << 8) | response[9];
++ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_CONNECT_RESPONSE_TOP,
++ "Invalid state!");
++ NS_ABORT_IF_FALSE(mDataLength == 5,
++ "SOCKS 5 connection reply must be exactly 5 bytes!");
+
+- PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET, extPort, extAddr);
++ LOGDEBUG(("socks5: checking connection reply"));
+
+- ip = (char*)(&extAddr->inet.ip);
+- *ip++ = response[4];
+- *ip++ = response[5];
+- *ip++ = response[6];
+- *ip++ = response[7];
++ // Check version number
++ if (ReadUint8() != 0x05) {
++ LOGERROR(("socks5: unexpected version in the reply"));
++ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
++ return PR_FAILURE;
++ }
+
+- break;
+- case 0x04: // IPv6
++ // Check response
++ res = ReadUint8();
++ if (res != 0x00) {
++ PRErrorCode c = PR_CONNECT_REFUSED_ERROR;
++
++ switch (res) {
++ case 0x01:
++ LOGERROR(("socks5: connect failed: "
++ "01, General SOCKS server failure."));
++ break;
++ case 0x02:
++ LOGERROR(("socks5: connect failed: "
++ "02, Connection not allowed by ruleset."));
++ break;
++ case 0x03:
++ LOGERROR(("socks5: connect failed: 03, Network unreachable."));
++ c = PR_NETWORK_UNREACHABLE_ERROR;
++ break;
++ case 0x04:
++ LOGERROR(("socks5: connect failed: 04, Host unreachable."));
++ break;
++ case 0x05:
++ LOGERROR(("socks5: connect failed: 05, Connection refused."));
++ break;
++ case 0x06:
++ LOGERROR(("socks5: connect failed: 06, TTL expired."));
++ c = PR_CONNECT_TIMEOUT_ERROR;
++ break;
++ case 0x07:
++ LOGERROR(("socks5: connect failed: "
++ "07, Command not supported."));
++ break;
++ case 0x08:
++ LOGERROR(("socks5: connect failed: "
++ "08, Address type not supported."));
++ c = PR_BAD_ADDRESS_ERROR;
++ break;
++ default:
++ LOGERROR(("socks5: connect failed."));
++ break;
++ }
+
+- extPort = (response[20] << 8) | response[21];
++ HandshakeFinished(c);
++ return PR_FAILURE;
++ }
+
+- PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, extPort, extAddr);
++ if (ReadV5AddrTypeAndLength(&res, &len) != PR_SUCCESS) {
++ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
++ return PR_FAILURE;
++ }
+
+- ip = (char*)(&extAddr->ipv6.ip.pr_s6_addr);
+- *ip++ = response[4]; *ip++ = response[5];
+- *ip++ = response[6]; *ip++ = response[7];
+- *ip++ = response[8]; *ip++ = response[9];
+- *ip++ = response[10]; *ip++ = response[11];
+- *ip++ = response[12]; *ip++ = response[13];
+- *ip++ = response[14]; *ip++ = response[15];
+- *ip++ = response[16]; *ip++ = response[17];
+- *ip++ = response[18]; *ip++ = response[19];
++ mState = SOCKS5_READ_CONNECT_RESPONSE_BOTTOM;
++ WantRead(len + 2);
+
+- break;
+- case 0x03: // FQDN
+- // if we get here, we don't know our external address.
+- // however, as that's possibly not critical to the user,
+- // we let it slide.
+- extPort = (response[response_len - 2] << 8) |
+- response[response_len - 1];
+- PR_InitializeNetAddr(PR_IpAddrNull, extPort, extAddr);
+- break;
+- }
+- return NS_OK;
++ return PR_SUCCESS;
+ }
+
+-// Negotiate a SOCKS 4 connection. Assumes the TCP connection to the socks
+-// server port has been established.
+-static nsresult
+-ConnectSOCKS4(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
++PRStatus
++nsSOCKSSocketInfo::ReadV5ConnectResponseBottom()
+ {
+- int request_len = 0;
+- int write_len;
+- int response_len = 0;
+- int desired_len = 0;
+- char *ip = nsnull;
+- unsigned char request[12];
+- unsigned char response[10];
++ PRUint8 type;
++ PRUint32 len;
+
+- NS_ENSURE_TRUE(fd, NS_ERROR_NOT_INITIALIZED);
+- NS_ENSURE_TRUE(addr, NS_ERROR_NOT_INITIALIZED);
++ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_CONNECT_RESPONSE_BOTTOM,
++ "Invalid state!");
+
+- request[0] = 0x04; // SOCKS version 4
+- request[1] = 0x01; // CD command code -- 1 for connect
+-
+- // destination port
+- PRInt32 destPort = PR_ntohs(PR_NetAddrInetPort(addr));
+-
+- // store the port
+- request[2] = (unsigned char)(destPort >> 8);
+- request[3] = (unsigned char)destPort;
+-
+- // username
+- request[8] = 'M';
+- request[9] = 'O';
+- request[10] = 'Z';
+-
+- request[11] = 0x00;
+-
+- request_len = 12;
+-
+- nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
++ if (ReadV5AddrTypeAndLength(&type, &len) != PR_SUCCESS) {
++ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
++ return PR_FAILURE;
++ }
+
+- if (info->Flags() & nsISocketProvider::PROXY_RESOLVES_HOST) {
++ NS_ABORT_IF_FALSE(mDataLength == 7+len,
++ "SOCKS 5 unexpected length of connection reply!");
+
+- LOGDEBUG(("using server to resolve hostnames rather than resolving it first\n"));
++ LOGDEBUG(("socks5: loading source addr and port"));
++ // Read what the proxy says is our source address
++ switch (type) {
++ case 0x01: // ipv4
++ ReadNetAddr(&mExternalProxyAddr, PR_AF_INET);
++ break;
++ case 0x04: // ipv6
++ ReadNetAddr(&mExternalProxyAddr, PR_AF_INET6);
++ break;
++ case 0x03: // fqdn (skip)
++ mReadOffset += len;
++ mExternalProxyAddr.raw.family = PR_AF_INET;
++ break;
++ }
+
+- // if the PROXY_RESOLVES_HOST flag is set, we assume that the
+- // transport wants us to pass the SOCKS server the hostname
+- // and port and let it do the name resolution.
++ ReadNetPort(&mExternalProxyAddr);
+
+- // an extension to SOCKS 4, called 4a, specifies a way
+- // to do this, so we'll try that and hope the
+- // server supports it.
++ LOGDEBUG(("socks5: connected!"));
++ HandshakeFinished();
+
+- // the real destination hostname and port was stored
+- // in our info object earlier when this layer was created.
++ return PR_SUCCESS;
++}
+
+- const nsCString& destHost = info->DestinationHost();
++void
++nsSOCKSSocketInfo::SetConnectTimeout(PRIntervalTime to)
++{
++ mTimeout = to;
++}
+
+- LOGDEBUG(("host:port -> %s:%li\n", destHost.get(), destPort));
++PRStatus
++nsSOCKSSocketInfo::DoHandshake(PRFileDesc *fd, PRInt16 oflags)
++{
++ LOGDEBUG(("socks: DoHandshake(), state = %d", mState));
++
++ switch (mState) {
++ case SOCKS_INITIAL:
++ return ConnectToProxy(fd);
++ case SOCKS_CONNECTING_TO_PROXY:
++ return ContinueConnectingToProxy(fd, oflags);
++ case SOCKS4_WRITE_CONNECT_REQUEST:
++ if (WriteToSocket(fd) != PR_SUCCESS)
++ return PR_FAILURE;
++ WantRead(8);
++ mState = SOCKS4_READ_CONNECT_RESPONSE;
++ return PR_SUCCESS;
++ case SOCKS4_READ_CONNECT_RESPONSE:
++ if (ReadFromSocket(fd) != PR_SUCCESS)
++ return PR_FAILURE;
++ return ReadV4ConnectResponse();
++
++ case SOCKS5_WRITE_AUTH_REQUEST:
++ if (WriteToSocket(fd) != PR_SUCCESS)
++ return PR_FAILURE;
++ WantRead(2);
++ mState = SOCKS5_READ_AUTH_RESPONSE;
++ return PR_SUCCESS;
++ case SOCKS5_READ_AUTH_RESPONSE:
++ if (ReadFromSocket(fd) != PR_SUCCESS)
++ return PR_FAILURE;
++ return ReadV5AuthResponse();
++ case SOCKS5_WRITE_CONNECT_REQUEST:
++ if (WriteToSocket(fd) != PR_SUCCESS)
++ return PR_FAILURE;
++
++ // The SOCKS 5 response to the connection request is variable
++ // length. First, we'll read enough to tell how long the response
++ // is, and will read the rest later.
++ WantRead(5);
++ mState = SOCKS5_READ_CONNECT_RESPONSE_TOP;
++ return PR_SUCCESS;
++ case SOCKS5_READ_CONNECT_RESPONSE_TOP:
++ if (ReadFromSocket(fd) != PR_SUCCESS)
++ return PR_FAILURE;
++ return ReadV5ConnectResponseTop();
++ case SOCKS5_READ_CONNECT_RESPONSE_BOTTOM:
++ if (ReadFromSocket(fd) != PR_SUCCESS)
++ return PR_FAILURE;
++ return ReadV5ConnectResponseBottom();
++
++ case SOCKS_CONNECTED:
++ LOGERROR(("socks: already connected"));
++ HandshakeFinished(PR_IS_CONNECTED_ERROR);
++ return PR_FAILURE;
++ case SOCKS_FAILED:
++ LOGERROR(("socks: already failed"));
++ return PR_FAILURE;
++ }
+
+- // the IP portion of the query is set to this special address.
+- request[4] = 0;
+- request[5] = 0;
+- request[6] = 0;
+- request[7] = 1;
++ LOGERROR(("socks: executing handshake in invalid state, %d", mState));
++ HandshakeFinished(PR_INVALID_STATE_ERROR);
+
+- write_len = pr_Send(fd, request, request_len, 0, &timeout);
+- if (write_len != request_len) {
+- return NS_ERROR_FAILURE;
+- }
++ return PR_FAILURE;
++}
+
+- // Remember the NULL.
+- int host_len = destHost.Length() + 1;
++PRInt16
++nsSOCKSSocketInfo::GetPollFlags() const
++{
++ switch (mState) {
++ case SOCKS_CONNECTING_TO_PROXY:
++ return PR_POLL_EXCEPT | PR_POLL_WRITE;
++ case SOCKS4_WRITE_CONNECT_REQUEST:
++ case SOCKS5_WRITE_AUTH_REQUEST:
++ case SOCKS5_WRITE_CONNECT_REQUEST:
++ return PR_POLL_WRITE;
++ case SOCKS4_READ_CONNECT_RESPONSE:
++ case SOCKS5_READ_AUTH_RESPONSE:
++ case SOCKS5_READ_CONNECT_RESPONSE_TOP:
++ case SOCKS5_READ_CONNECT_RESPONSE_BOTTOM:
++ return PR_POLL_READ;
++ default:
++ break;
++ }
+
+- write_len = pr_Send(fd, destHost.get(), host_len, 0, &timeout);
+- if (write_len != host_len) {
+- return NS_ERROR_FAILURE;
+- }
++ return 0;
++}
+
+- // No data to send, just sent it.
+- request_len = 0;
+-
+- } else if (PR_NetAddrFamily(addr) == PR_AF_INET) { // IPv4
+-
+- // store the ip
+- ip = (char*)(&addr->inet.ip);
+- request[4] = *ip++;
+- request[5] = *ip++;
+- request[6] = *ip++;
+- request[7] = *ip++;
+-
+- } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) { // IPv6
+-
+- // IPv4 address encoded in an IPv6 address
+- if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
+- // store the ip
+- ip = (char*)(&addr->ipv6.ip.pr_s6_addr[12]);
+- request[4] = *ip++;
+- request[5] = *ip++;
+- request[6] = *ip++;
+- request[7] = *ip++;
+- } else {
+- LOGERROR(("IPv6 is not supported in SOCKS 4."));
+- return NS_ERROR_FAILURE; // SOCKS 4 can't do IPv6
+- }
++inline void
++nsSOCKSSocketInfo::WriteUint8(PRUint8 v)
++{
++ NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
++ "Can't write that much data!");
++ mData[mDataLength] = v;
++ mDataLength += sizeof(v);
++}
+
+- } else {
+- LOGERROR(("Don't know what kind of IP address this is."));
+- return NS_ERROR_FAILURE; // don't recognize this type
+- }
++inline void
++nsSOCKSSocketInfo::WriteUint16(PRUint16 v)
++{
++ NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
++ "Can't write that much data!");
++ memcpy(mData + mDataLength, &v, sizeof(v));
++ mDataLength += sizeof(v);
++}
+
+- if (request_len > 0) {
+- write_len = pr_Send(fd, request, request_len, 0, &timeout);
+- if (write_len != request_len) {
+- return NS_ERROR_FAILURE;
+- }
+- }
++inline void
++nsSOCKSSocketInfo::WriteUint32(PRUint32 v)
++{
++ NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
++ "Can't write that much data!");
++ memcpy(mData + mDataLength, &v, sizeof(v));
++ mDataLength += sizeof(v);
++}
+
+- // get the server's response
+- desired_len = 8; // size of the response
+- response_len = pr_RecvAll(fd, response, desired_len, 0, &timeout);
+- if (response_len < desired_len) {
+- LOGERROR(("pr_RecvAll() failed. response_len = %d.", response_len));
+- return NS_ERROR_FAILURE;
+- }
++void
++nsSOCKSSocketInfo::WriteNetAddr(const PRNetAddr *addr)
++{
++ const char *ip = NULL;
++ PRUint32 len = 0;
+
+- if ((response[0] != 0x00) && (response[0] != 0x04)) {
+- // Novell BorderManager sends a response of type 4, should be zero
+- // According to the spec. Cope with this brokenness.
+- // it's not a SOCKS 4 reply or version 0 of the reply code
+- LOGERROR(("Not a SOCKS 4 reply. Expected: 0; received: %x.", response[0]));
+- return NS_ERROR_FAILURE;
++ if (PR_NetAddrFamily(addr) == PR_AF_INET) {
++ ip = (const char*)&addr->inet.ip;
++ len = sizeof(addr->inet.ip);
++ } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
++ ip = (const char*)addr->ipv6.ip.pr_s6_addr;
++ len = sizeof(addr->ipv6.ip.pr_s6_addr);
+ }
+
+- if (response[1] != 0x5A) { // = 90: request granted
+- // connect request not granted
+- LOGERROR(("Connection request refused. Expected: 90; received: %d.", response[1]));
+- return NS_ERROR_FAILURE;
+- }
++ NS_ABORT_IF_FALSE(ip != NULL, "Unknown address");
++ NS_ABORT_IF_FALSE(mDataLength + len <= BUFFER_SIZE,
++ "Can't write that much data!");
+
+- return NS_OK;
++ memcpy(mData + mDataLength, ip, len);
++ mDataLength += len;
++}
+
++void
++nsSOCKSSocketInfo::WriteNetPort(const PRNetAddr *addr)
++{
++ WriteUint16(PR_NetAddrInetPort(addr));
+ }
+
++void
++nsSOCKSSocketInfo::WriteString(const nsACString &str)
++{
++ NS_ABORT_IF_FALSE(mDataLength + str.Length() <= BUFFER_SIZE,
++ "Can't write that much data!");
++ memcpy(mData + mDataLength, str.Data(), str.Length());
++ mDataLength += str.Length();
++}
+
+-static PRStatus
+-nsSOCKSIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime /*timeout*/)
++inline PRUint8
++nsSOCKSSocketInfo::ReadUint8()
+ {
++ PRUint8 rv;
++ NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
++ "Not enough space to pop a uint8!");
++ rv = mData[mReadOffset];
++ mReadOffset += sizeof(rv);
++ return rv;
++}
+
+- PRStatus status;
++inline PRUint16
++nsSOCKSSocketInfo::ReadUint16()
++{
++ PRUint16 rv;
++ NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
++ "Not enough space to pop a uint16!");
++ memcpy(&rv, mData + mReadOffset, sizeof(rv));
++ mReadOffset += sizeof(rv);
++ return rv;
++}
+
+- nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
+- if (info == NULL) return PR_FAILURE;
++inline PRUint32
++nsSOCKSSocketInfo::ReadUint32()
++{
++ PRUint32 rv;
++ NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
++ "Not enough space to pop a uint32!");
++ memcpy(&rv, mData + mReadOffset, sizeof(rv));
++ mReadOffset += sizeof(rv);
++ return rv;
++}
+
+- // First, we need to look up our proxy...
+- const nsCString &proxyHost = info->ProxyHost();
++void
++nsSOCKSSocketInfo::ReadNetAddr(PRNetAddr *addr, PRUint16 fam)
++{
++ PRUint32 amt;
++ const PRUint8 *ip = mData + mReadOffset;
++
++ addr->raw.family = fam;
++ if (fam == PR_AF_INET) {
++ amt = sizeof(addr->inet.ip);
++ NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
++ "Not enough space to pop an ipv4 addr!");
++ memcpy(&addr->inet.ip, ip, amt);
++ } else if (fam == PR_AF_INET6) {
++ amt = sizeof(addr->ipv6.ip.pr_s6_addr);
++ NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
++ "Not enough space to pop an ipv6 addr!");
++ memcpy(addr->ipv6.ip.pr_s6_addr, ip, amt);
++ }
+
+- if (proxyHost.IsEmpty())
+- return PR_FAILURE;
++ mReadOffset += amt;
++}
+
+- PRInt32 socksVersion = info->Version();
++void
++nsSOCKSSocketInfo::ReadNetPort(PRNetAddr *addr)
++{
++ addr->inet.port = ReadUint16();
++}
+
+- LOGDEBUG(("nsSOCKSIOLayerConnect SOCKS %u; proxyHost: %s.", socksVersion, proxyHost.get()));
++void
++nsSOCKSSocketInfo::WantRead(PRUint32 sz)
++{
++ NS_ABORT_IF_FALSE(mDataIoPtr == NULL,
++ "WantRead() called while I/O already in progress!");
++ NS_ABORT_IF_FALSE(mDataLength + sz <= BUFFER_SIZE,
++ "Can't read that much data!");
++ mAmountToRead = sz;
++}
+
+- // Sync resolve the proxy hostname.
+- PRNetAddr proxyAddr;
+- nsCOMPtr<nsIDNSRecord> rec;
+- nsresult rv;
+- {
+- nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
+- if (!dns)
+- return PR_FAILURE;
++PRStatus
++nsSOCKSSocketInfo::ReadFromSocket(PRFileDesc *fd)
++{
++ PRInt32 rc;
++ const PRUint8 *end;
+
+- rv = dns->Resolve(proxyHost, 0, getter_AddRefs(rec));
+- if (NS_FAILED(rv))
+- return PR_FAILURE;
++ if (!mAmountToRead) {
++ LOGDEBUG(("socks: ReadFromSocket(), nothing to do"));
++ return PR_SUCCESS;
+ }
+
+- info->SetInternalProxyAddr(&proxyAddr);
++ if (!mDataIoPtr) {
++ mDataIoPtr = mData + mDataLength;
++ mDataLength += mAmountToRead;
++ }
+
+- // For now, we'll do this as a blocking connect,
+- // but with nspr 4.1, the necessary functions to
+- // do a non-blocking connect will be available
++ end = mData + mDataLength;
++
++ while (mDataIoPtr < end) {
++ rc = PR_Read(fd, mDataIoPtr, end - mDataIoPtr);
++ if (rc <= 0) {
++ if (rc == 0) {
++ LOGERROR(("socks: proxy server closed connection"));
++ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
++ return PR_FAILURE;
++ } else if (PR_GetError() == PR_WOULD_BLOCK_ERROR) {
++ LOGDEBUG(("socks: ReadFromSocket(), want read"));
++ }
++ break;
++ }
+
+- // Preserve the non-blocking state of the socket
+- PRBool nonblocking;
+- PRSocketOptionData sockopt;
+- sockopt.option = PR_SockOpt_Nonblocking;
+- status = PR_GetSocketOption(fd, &sockopt);
++ mDataIoPtr += rc;
++ }
+
+- if (PR_SUCCESS != status) {
+- LOGERROR(("PR_GetSocketOption() failed. status = %x.", status));
+- return status;
++ LOGDEBUG(("socks: ReadFromSocket(), have %u bytes total",
++ unsigned(mDataIoPtr - mData)));
++ if (mDataIoPtr == end) {
++ mDataIoPtr = nsnull;
++ mAmountToRead = 0;
++ mReadOffset = 0;
++ return PR_SUCCESS;
+ }
+
+- // Store blocking option
+- nonblocking = sockopt.value.non_blocking;
++ return PR_FAILURE;
++}
+
+- sockopt.option = PR_SockOpt_Nonblocking;
+- sockopt.value.non_blocking = PR_FALSE;
+- status = PR_SetSocketOption(fd, &sockopt);
++PRStatus
++nsSOCKSSocketInfo::WriteToSocket(PRFileDesc *fd)
++{
++ PRInt32 rc;
++ const PRUint8 *end;
+
+- if (PR_SUCCESS != status) {
+- LOGERROR(("PR_SetSocketOption() failed. status = %x.", status));
+- return status;
++ if (!mDataLength) {
++ LOGDEBUG(("socks: WriteToSocket(), nothing to do"));
++ return PR_SUCCESS;
+ }
+
+- // Now setup sockopts, so we can restore the value later.
+- sockopt.option = PR_SockOpt_Nonblocking;
+- sockopt.value.non_blocking = nonblocking;
++ if (!mDataIoPtr)
++ mDataIoPtr = mData;
+
+- // This connectWait should be long enough to connect to local proxy
+- // servers, but not much longer. Since this protocol negotiation
+- // uses blocking network calls, the app can appear to hang for a maximum
+- // of this time if the user presses the STOP button during the SOCKS
+- // connection negotiation. Note that this value only applies to the
+- // connecting to the SOCKS server: once the SOCKS connection has been
+- // established, the value is not used anywhere else.
+- PRIntervalTime connectWait = PR_SecondsToInterval(10);
++ end = mData + mDataLength;
+
+- // Connect to the proxy server.
+- PRInt32 addresses = 0;
+- do {
+- rv = rec->GetNextAddr(info->ProxyPort(), &proxyAddr);
+- if (NS_FAILED(rv)) {
+- status = PR_FAILURE;
++ while (mDataIoPtr < end) {
++ rc = PR_Write(fd, mDataIoPtr, end - mDataIoPtr);
++ if (rc < 0) {
++ if (PR_GetError() == PR_WOULD_BLOCK_ERROR) {
++ LOGDEBUG(("socks: WriteToSocket(), want write"));
++ }
+ break;
+ }
+- ++addresses;
+- status = fd->lower->methods->connect(fd->lower, &proxyAddr, connectWait);
+- } while (PR_SUCCESS != status);
++
++ mDataIoPtr += rc;
++ }
+
+- if (PR_SUCCESS != status) {
+- LOGERROR(("Failed to TCP connect to the proxy server (%s): timeout = %d, status = %x, tried %d addresses.", proxyHost.get(), connectWait, status, addresses));
+- PR_SetSocketOption(fd, &sockopt);
+- return status;
++ if (mDataIoPtr == end) {
++ mDataIoPtr = nsnull;
++ mDataLength = 0;
++ mReadOffset = 0;
++ return PR_SUCCESS;
+ }
++
++ return PR_FAILURE;
++}
+
++static PRStatus
++nsSOCKSIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime to)
++{
++ PRStatus status;
++ PRNetAddr dst;
+
+- // We are now connected to the SOCKS proxy server.
+- // Now we will negotiate a connection to the desired server.
++ nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
++ if (info == NULL) return PR_FAILURE;
+
+- // External IP address returned from ConnectSOCKS5(). Not supported in SOCKS4.
+- PRNetAddr extAddr;
+- PR_InitializeNetAddr(PR_IpAddrNull, 0, &extAddr);
++ if (PR_NetAddrFamily(addr) == PR_AF_INET6 &&
++ PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
++ const PRUint8 *srcp;
+
+- NS_ASSERTION((socksVersion == 4) || (socksVersion == 5), "SOCKS Version must be selected");
++ LOGDEBUG(("socks: converting ipv4-mapped ipv6 address to ipv4"));
+
+- // Try to connect via SOCKS 5.
+- if (socksVersion == 5) {
+- rv = ConnectSOCKS5(fd, addr, &extAddr, connectWait);
++ // copied from _PR_ConvertToIpv4NetAddr()
++ PR_InitializeNetAddr(PR_IpAddrAny, 0, &dst);
++ srcp = addr->ipv6.ip.pr_s6_addr;
++ memcpy(&dst.inet.ip, srcp + 12, 4);
++ dst.inet.family = PR_AF_INET;
++ dst.inet.port = addr->ipv6.port;
++ } else {
++ memcpy(&dst, addr, sizeof(dst));
++ }
+
+- if (NS_FAILED(rv)) {
+- PR_SetSocketOption(fd, &sockopt);
+- return PR_FAILURE;
+- }
++ info->SetDestinationAddr(&dst);
++ info->SetConnectTimeout(to);
+
+- }
++ do {
++ status = info->DoHandshake(fd, -1);
++ } while (status == PR_SUCCESS && !info->IsConnected());
+
+- // Try to connect via SOCKS 4.
+- else {
+- rv = ConnectSOCKS4(fd, addr, connectWait);
++ return status;
++}
+
+- if (NS_FAILED(rv)) {
+- PR_SetSocketOption(fd, &sockopt);
+- return PR_FAILURE;
+- }
++static PRStatus
++nsSOCKSIOLayerConnectContinue(PRFileDesc *fd, PRInt16 oflags)
++{
++ PRStatus status;
+
+- }
++ nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
++ if (info == NULL) return PR_FAILURE;
+
++ do {
++ status = info->DoHandshake(fd, oflags);
++ } while (status == PR_SUCCESS && !info->IsConnected());
+
+- info->SetDestinationAddr((PRNetAddr*)addr);
+- info->SetExternalProxyAddr(&extAddr);
++ return status;
++}
+
+- // restore non-blocking option
+- PR_SetSocketOption(fd, &sockopt);
++static PRInt16
++nsSOCKSIOLayerPoll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
++{
++ nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
++ if (info == NULL) return PR_FAILURE;
+
+- // we're set-up and connected.
+- // this socket can be used as normal now.
++ if (!info->IsConnected()) {
++ *out_flags = 0;
++ return info->GetPollFlags();
++ }
+
+- return PR_SUCCESS;
++ return fd->lower->methods->poll(fd->lower, in_flags, out_flags);
+ }
+
+ static PRStatus
+@@ -885,6 +1120,8 @@ nsSOCKSIOLayerAddToSocket(PRInt32 family,
+ nsSOCKSIOLayerMethods = *PR_GetDefaultIOMethods();
+
+ nsSOCKSIOLayerMethods.connect = nsSOCKSIOLayerConnect;
++ nsSOCKSIOLayerMethods.connectcontinue = nsSOCKSIOLayerConnectContinue;
++ nsSOCKSIOLayerMethods.poll = nsSOCKSIOLayerPoll;
+ nsSOCKSIOLayerMethods.bind = nsSOCKSIOLayerBind;
+ nsSOCKSIOLayerMethods.acceptread = nsSOCKSIOLayerAcceptRead;
+ nsSOCKSIOLayerMethods.getsockname = nsSOCKSIOLayerGetName;
+--
+1.7.3.4
+
diff --git a/src/archived-patches/0001-Firefox5-Block-Components.interfaces-lookupMethod-fr.patch b/src/archived-patches/0001-Firefox5-Block-Components.interfaces-lookupMethod-fr.patch
new file mode 100644
index 0000000..816e2d2
--- /dev/null
+++ b/src/archived-patches/0001-Firefox5-Block-Components.interfaces-lookupMethod-fr.patch
@@ -0,0 +1,50 @@
+From cb6df58b95028693007936e423d43223609e17cc Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Mon, 20 Jun 2011 17:07:41 -0700
+Subject: [PATCH 1/3] Firefox5: Block Components.interfaces,lookupMethod from content
+
+This patch removes the ability of content script to access
+Components.interfaces.* as well as call or access Components.lookupMethod.
+
+These two interfaces seem to be exposed to content script only to make our
+lives difficult. Components.lookupMethod can undo our JS hooks, and
+Components.interfaces is useful for fingerprinting the platform, OS, and
+Firebox version.
+
+They appear to have no other legitimate use. See also:
+https://bugzilla.mozilla.org/show_bug.cgi?id=429070
+https://trac.torproject.org/projects/tor/ticket/2873
+https://trac.torproject.org/projects/tor/ticket/2874
+---
+ js/src/xpconnect/src/xpccomponents.cpp | 8 ++++++--
+ 1 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp
+index 5e789e7..5c76981 100644
+--- a/js/src/xpconnect/src/xpccomponents.cpp
++++ b/js/src/xpconnect/src/xpccomponents.cpp
+@@ -4287,7 +4287,9 @@ nsXPCComponents::CanCreateWrapper(const nsIID * iid, char **_retval)
+ NS_IMETHODIMP
+ nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
+ {
+- static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
++ // XXX: Pref observer? Also, is this what we want? Seems like a plan
++ //static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
++ static const char* allowed[] = { "isSuccessCode", nsnull };
+ *_retval = xpc_CheckAccessList(methodName, allowed);
+ return NS_OK;
+ }
+@@ -4296,7 +4298,9 @@ nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, c
+ NS_IMETHODIMP
+ nsXPCComponents::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
+ {
+- static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
++ // XXX: Pref observer? Also, is this what we want? Seems like a plan
++ // static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
++ static const char* allowed[] = { "results", nsnull};
+ *_retval = xpc_CheckAccessList(propertyName, allowed);
+ return NS_OK;
+ }
+--
+1.7.3.4
+
diff --git a/src/archived-patches/0002-Firefox4-Block-Components.interfaces-lookupMethod-fr.patch b/src/archived-patches/0002-Firefox4-Block-Components.interfaces-lookupMethod-fr.patch
new file mode 100644
index 0000000..8e34500
--- /dev/null
+++ b/src/archived-patches/0002-Firefox4-Block-Components.interfaces-lookupMethod-fr.patch
@@ -0,0 +1,50 @@
+From ebaf58a014f98942886ae829da83fadd662df948 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Mon, 20 Jun 2011 17:07:41 -0700
+Subject: [PATCH 2/4] Firefox4: Block Components.interfaces,lookupMethod from content
+
+This patch removes the ability of content script to access
+Components.interfaces.* as well as call or access Components.lookupMethod.
+
+These two interfaces seem to be exposed to content script only to make our
+lives difficult. Components.lookupMethod can undo our JS hooks, and
+Components.interfaces is useful for fingerprinting the platform, OS, and
+Firebox version.
+
+They appear to have no other legitimate use. See also:
+https://bugzilla.mozilla.org/show_bug.cgi?id=429070
+https://trac.torproject.org/projects/tor/ticket/2873
+https://trac.torproject.org/projects/tor/ticket/2874
+---
+ js/src/xpconnect/src/xpccomponents.cpp | 8 ++++++--
+ 1 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp
+index 1c141f9..85a2b4e 100644
+--- a/js/src/xpconnect/src/xpccomponents.cpp
++++ b/js/src/xpconnect/src/xpccomponents.cpp
+@@ -4294,7 +4294,9 @@ nsXPCComponents::CanCreateWrapper(const nsIID * iid, char **_retval)
+ NS_IMETHODIMP
+ nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
+ {
+- static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
++ // XXX: Pref observer? Also, is this what we want? Seems like a plan
++ //static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
++ static const char* allowed[] = { "isSuccessCode", nsnull };
+ *_retval = xpc_CheckAccessList(methodName, allowed);
+ return NS_OK;
+ }
+@@ -4303,7 +4305,9 @@ nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, c
+ NS_IMETHODIMP
+ nsXPCComponents::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
+ {
+- static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
++ // XXX: Pref observer? Also, is this what we want? Seems like a plan
++ // static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
++ static const char* allowed[] = { "results", nsnull};
+ *_retval = xpc_CheckAccessList(propertyName, allowed);
+ return NS_OK;
+ }
+--
+1.7.3.4
+
diff --git a/src/archived-patches/0002-Firefox5-Make-Intermediate-Cert-Store-memory-only.patch b/src/archived-patches/0002-Firefox5-Make-Intermediate-Cert-Store-memory-only.patch
new file mode 100644
index 0000000..2bd11e8
--- /dev/null
+++ b/src/archived-patches/0002-Firefox5-Make-Intermediate-Cert-Store-memory-only.patch
@@ -0,0 +1,300 @@
+From 16b89c54032d1ad0acf2d6fa005b292a6f434791 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Mon, 20 Jun 2011 17:07:49 -0700
+Subject: [PATCH 2/3] Firefox5: Make Intermediate Cert Store memory-only.
+
+This patch makes the intermediate SSL cert store exist in memory only. It
+exposes a pref ('security.nocertdb') to toggle to clear the store, but this
+seems buggy.
+
+The pref must be set before startup in prefs.js.
+https://trac.torproject.org/projects/tor/ticket/2949
+---
+ security/manager/ssl/src/nsNSSComponent.cpp | 180 ++++++++++++++++++---------
+ 1 files changed, 120 insertions(+), 60 deletions(-)
+
+diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp
+index d3ae772..fa37ace 100644
+--- a/security/manager/ssl/src/nsNSSComponent.cpp
++++ b/security/manager/ssl/src/nsNSSComponent.cpp
+@@ -1658,8 +1658,21 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox)
+ // Ubuntu 8.04, which loads any nonexistent "<configdir>/libnssckbi.so" as
+ // "/usr/lib/nss/libnssckbi.so".
+ PRUint32 init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
+- SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "",
++ PRBool nocertdb = false;
++ mPrefBranch->GetBoolPref("security.nocertdb", &nocertdb);
++
++ // XXX: We can also do the the following to only disable the certdb.
++ // Leaving this codepath in as a fallback in case InitNODB fails
++ if (nocertdb)
++ init_flags |= NSS_INIT_NOCERTDB;
++
++ SECStatus init_rv;
++ if (nocertdb) {
++ init_rv = ::NSS_NoDB_Init(NULL);
++ } else {
++ init_rv = ::NSS_Initialize(profileStr.get(), "", "",
+ SECMOD_DB, init_flags);
++ }
+
+ if (init_rv != SECSuccess) {
+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can not init NSS r/w in %s\n", profileStr.get()));
+@@ -2215,70 +2228,106 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
+ }
+ }
+ }
+- else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
+- nsNSSShutDownPreventionLock locker;
+- PRBool clearSessionCache = PR_FALSE;
+- PRBool enabled;
++ else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
+ NS_ConvertUTF16toUTF8 prefName(someData);
++ // XXX: This should be an observer notification, so we can properly cancel it
++ if (prefName.Equals("security.nocertdb")) {
++ // XXX: If these functions tell us to cancel, the browser seems to get left in an
++ // indeterminate state that prevents SSL from being used.
++ //
++ // We apparently need to wait for all SSL sockets to shut down on their
++ // own (this can take up to a minute!) and then attempt to alter the pref
++ // again before doing anything.
++ //
++ // So any implementation of New Identity based on this code will need to keep
++ // attempting to send the notification until it is not canceled. Ugh...
++ if (!DoProfileApproveChange(aSubject)) {
++ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled\n"));
++ return NS_OK;
++ }
+
+- if (prefName.Equals("security.enable_ssl2")) {
+- mPrefBranch->GetBoolPref("security.enable_ssl2", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_SSL2, enabled);
+- SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, enabled);
+- clearSessionCache = PR_TRUE;
+- } else if (prefName.Equals("security.enable_ssl3")) {
+- mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
+- clearSessionCache = PR_TRUE;
+- } else if (prefName.Equals("security.enable_tls")) {
+- mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
+- clearSessionCache = PR_TRUE;
+- } else if (prefName.Equals("security.enable_tls_session_tickets")) {
+- mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
+- } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
+- mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
+- SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
+- } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
+- mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
+- enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
+- } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
+- char *unrestricted_hosts=nsnull;
+- mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
+- if (unrestricted_hosts) {
+- nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
+- nsMemory::Free(unrestricted_hosts);
++ DoProfileChangeNetTeardown();
++ if (!DoProfileChangeTeardown(aSubject)) {
++ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled\n"));
++ return NS_OK;
++ }
++
++ if (!DoProfileBeforeChange(aSubject)) {
++ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled by NSS shutdown\n"));
++ // Need to re-add observer because ShutdownNSS removed it.
++ nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(mPrefBranch);
++ pbi->AddObserver("security.", this, PR_FALSE);
++ return NS_OK;
+ }
+- } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
+- mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
+- nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
+- } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
+- PRInt32 warnLevel = 1;
+- mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
+- nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
++
++ DoProfileChangeNetRestore();
++ InitializeNSS(PR_FALSE);
++ InitializeCRLUpdateTimer();
++ return NS_OK;
++ } else {
++ nsNSSShutDownPreventionLock locker;
++ PRBool clearSessionCache = PR_FALSE;
++ PRBool enabled;
++
++ if (prefName.Equals("security.enable_ssl2")) {
++ mPrefBranch->GetBoolPref("security.enable_ssl2", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_SSL2, enabled);
++ SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, enabled);
++ clearSessionCache = PR_TRUE;
++ } else if (prefName.Equals("security.enable_ssl3")) {
++ mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
++ clearSessionCache = PR_TRUE;
++ } else if (prefName.Equals("security.enable_tls")) {
++ mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
++ clearSessionCache = PR_TRUE;
++ } else if (prefName.Equals("security.enable_tls_session_tickets")) {
++ mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
++ } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
++ mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
++ SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
++ } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
++ mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
++ enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
++ } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
++ char *unrestricted_hosts=nsnull;
++ mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
++ if (unrestricted_hosts) {
++ nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
++ nsMemory::Free(unrestricted_hosts);
++ }
++ } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
++ mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
++ nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
++ } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
++ PRInt32 warnLevel = 1;
++ mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
++ nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
+ #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
+- } else if (prefName.Equals("security.ssl.enable_false_start")) {
+- mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
++ } else if (prefName.Equals("security.ssl.enable_false_start")) {
++ mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
+ #endif
+- } else if (prefName.Equals("security.OCSP.enabled")
+- || prefName.Equals("security.OCSP.require")) {
+- setOCSPOptions(mPrefBranch);
+- } else {
+- /* Look through the cipher table and set according to pref setting */
+- for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
+- if (prefName.Equals(cp->pref)) {
+- mPrefBranch->GetBoolPref(cp->pref, &enabled);
+- SSL_CipherPrefSetDefault(cp->id, enabled);
+- clearSessionCache = PR_TRUE;
+- break;
++ } else if (prefName.Equals("security.OCSP.enabled")
++ || prefName.Equals("security.OCSP.require")) {
++ setOCSPOptions(mPrefBranch);
++ } else {
++ /* Look through the cipher table and set according to pref setting */
++ for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
++ if (prefName.Equals(cp->pref)) {
++ mPrefBranch->GetBoolPref(cp->pref, &enabled);
++ SSL_CipherPrefSetDefault(cp->id, enabled);
++ clearSessionCache = PR_TRUE;
++ break;
++ }
+ }
+ }
++ if (clearSessionCache)
++ SSL_ClearSessionCache();
+ }
+- if (clearSessionCache)
+- SSL_ClearSessionCache();
+ }
+ else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
+@@ -2447,16 +2496,19 @@ nsNSSComponent::RememberCert(CERTCertificate *cert)
+ return NS_OK;
+ }
+
+-void
++PRBool
+ nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
+ {
+ if (mShutdownObjectList->isUIActive()) {
++ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS UI active in profile change!\n"));
+ ShowAlert(ai_crypto_ui_active);
+ nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
+ if (status) {
+ status->VetoChange();
+ }
++ return false;
+ }
++ return true;
+ }
+
+ void
+@@ -2469,16 +2521,18 @@ nsNSSComponent::DoProfileChangeNetTeardown()
+ mIsNetworkDown = PR_TRUE;
+ }
+
+-void
++PRBool
+ nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
+ {
+ PRBool callVeto = PR_FALSE;
+
+ if (!mShutdownObjectList->ifPossibleDisallowUI()) {
+ callVeto = PR_TRUE;
++ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: Not possible to disallow UI!\n"));
+ ShowAlert(ai_crypto_ui_active);
+ }
+ else if (mShutdownObjectList->areSSLSocketsActive()) {
++ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: SSL Sockets are active!\n"));
+ callVeto = PR_TRUE;
+ ShowAlert(ai_sockets_still_active);
+ }
+@@ -2489,9 +2543,11 @@ nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
+ status->VetoChange();
+ }
+ }
++
++ return !callVeto;
+ }
+
+-void
++PRBool
+ nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
+ {
+ NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
+@@ -2510,16 +2566,20 @@ nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
+ }
+
+ StopCRLUpdateTimer();
++ PRBool allow_change = PR_TRUE;
+
+ if (needsCleanup) {
+ if (NS_FAILED(ShutdownNSS())) {
++ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: Shutdown failed\n"));
+ nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
+ if (status) {
+ status->ChangeFailed();
+ }
++ allow_change = PR_FALSE;
+ }
+ }
+ mShutdownObjectList->allowUI();
++ return allow_change;
+ }
+
+ void
+--- a/security/manager/ssl/src/nsNSSComponent.h
++++ b/security/manager/ssl/src/nsNSSComponent.h
+@@ -321,10 +321,10 @@
+
+ // Methods that we use to handle the profile change notifications (and to
+ // synthesize a full profile change when we're just doing a profile startup):
+- void DoProfileApproveChange(nsISupports* aSubject);
++ PRBool DoProfileApproveChange(nsISupports* aSubject);
+ void DoProfileChangeNetTeardown();
+- void DoProfileChangeTeardown(nsISupports* aSubject);
+- void DoProfileBeforeChange(nsISupports* aSubject);
++ PRBool DoProfileChangeTeardown(nsISupports* aSubject);
++ PRBool DoProfileBeforeChange(nsISupports* aSubject);
+ void DoProfileChangeNetRestore();
+
+ Mutex mutex;
+
+--
+1.7.3.4
+
diff --git a/src/archived-patches/0003-Firefox4-Make-Intermediate-Cert-Store-memory-only.patch b/src/archived-patches/0003-Firefox4-Make-Intermediate-Cert-Store-memory-only.patch
new file mode 100644
index 0000000..d4f7b73
--- /dev/null
+++ b/src/archived-patches/0003-Firefox4-Make-Intermediate-Cert-Store-memory-only.patch
@@ -0,0 +1,283 @@
+From 4db14cbb5a0aff6102189d30b9202555dcc39ff4 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Mon, 20 Jun 2011 17:07:49 -0700
+Subject: [PATCH 3/4] Firefox4: Make Intermediate Cert Store memory-only.
+
+This patch makes the intermediate SSL cert store exist in memory only. It
+exposes a pref ('security.nocertdb') to toggle to clear the store, but this
+seems buggy.
+
+The pref must be set before startup in prefs.js.
+https://trac.torproject.org/projects/tor/ticket/2949
+---
+ security/manager/ssl/src/nsNSSComponent.cpp | 180 ++++++++++++++++++---------
+ 1 files changed, 120 insertions(+), 60 deletions(-)
+
+diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp
+index 33377ac..716bcee 100644
+--- a/security/manager/ssl/src/nsNSSComponent.cpp
++++ b/security/manager/ssl/src/nsNSSComponent.cpp
+@@ -1674,8 +1674,21 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox)
+ // Ubuntu 8.04, which loads any nonexistent "<configdir>/libnssckbi.so" as
+ // "/usr/lib/nss/libnssckbi.so".
+ PRUint32 init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
+- SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "",
++ PRBool nocertdb = false;
++ mPrefBranch->GetBoolPref("security.nocertdb", &nocertdb);
++
++ // XXX: We can also do the the following to only disable the certdb.
++ // Leaving this codepath in as a fallback in case InitNODB fails
++ if (nocertdb)
++ init_flags |= NSS_INIT_NOCERTDB;
++
++ SECStatus init_rv;
++ if (nocertdb) {
++ init_rv = ::NSS_NoDB_Init(NULL);
++ } else {
++ init_rv = ::NSS_Initialize(profileStr.get(), "", "",
+ SECMOD_DB, init_flags);
++ }
+
+ if (init_rv != SECSuccess) {
+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can not init NSS r/w in %s\n", profileStr.get()));
+@@ -2231,70 +2244,106 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
+ }
+ }
+ }
+- else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
+- nsNSSShutDownPreventionLock locker;
+- PRBool clearSessionCache = PR_FALSE;
+- PRBool enabled;
++ else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
+ NS_ConvertUTF16toUTF8 prefName(someData);
++ // XXX: This should be an observer notification, so we can properly cancel it
++ if (prefName.Equals("security.nocertdb")) {
++ // XXX: If these functions tell us to cancel, the browser seems to get left in an
++ // indeterminate state that prevents SSL from being used.
++ //
++ // We apparently need to wait for all SSL sockets to shut down on their
++ // own (this can take up to a minute!) and then attempt to alter the pref
++ // again before doing anything.
++ //
++ // So any implementation of New Identity based on this code will need to keep
++ // attempting to send the notification until it is not canceled. Ugh...
++ if (!DoProfileApproveChange(aSubject)) {
++ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled\n"));
++ return NS_OK;
++ }
+
+- if (prefName.Equals("security.enable_ssl2")) {
+- mPrefBranch->GetBoolPref("security.enable_ssl2", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_SSL2, enabled);
+- SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, enabled);
+- clearSessionCache = PR_TRUE;
+- } else if (prefName.Equals("security.enable_ssl3")) {
+- mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
+- clearSessionCache = PR_TRUE;
+- } else if (prefName.Equals("security.enable_tls")) {
+- mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
+- clearSessionCache = PR_TRUE;
+- } else if (prefName.Equals("security.enable_tls_session_tickets")) {
+- mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
+- } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
+- mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
+- SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
+- } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
+- mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
+- enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
+- } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
+- char *unrestricted_hosts=nsnull;
+- mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
+- if (unrestricted_hosts) {
+- nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
+- nsMemory::Free(unrestricted_hosts);
++ DoProfileChangeNetTeardown();
++ if (!DoProfileChangeTeardown(aSubject)) {
++ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled\n"));
++ return NS_OK;
++ }
++
++ if (!DoProfileBeforeChange(aSubject)) {
++ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled by NSS shutdown\n"));
++ // Need to re-add observer because ShutdownNSS removed it.
++ nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(mPrefBranch);
++ pbi->AddObserver("security.", this, PR_FALSE);
++ return NS_OK;
+ }
+- } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
+- mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
+- nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
+- } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
+- PRInt32 warnLevel = 1;
+- mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
+- nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
++
++ DoProfileChangeNetRestore();
++ InitializeNSS(PR_FALSE);
++ InitializeCRLUpdateTimer();
++ return NS_OK;
++ } else {
++ nsNSSShutDownPreventionLock locker;
++ PRBool clearSessionCache = PR_FALSE;
++ PRBool enabled;
++
++ if (prefName.Equals("security.enable_ssl2")) {
++ mPrefBranch->GetBoolPref("security.enable_ssl2", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_SSL2, enabled);
++ SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, enabled);
++ clearSessionCache = PR_TRUE;
++ } else if (prefName.Equals("security.enable_ssl3")) {
++ mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
++ clearSessionCache = PR_TRUE;
++ } else if (prefName.Equals("security.enable_tls")) {
++ mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
++ clearSessionCache = PR_TRUE;
++ } else if (prefName.Equals("security.enable_tls_session_tickets")) {
++ mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
++ } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
++ mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
++ SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
++ } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
++ mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
++ enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
++ } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
++ char *unrestricted_hosts=nsnull;
++ mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
++ if (unrestricted_hosts) {
++ nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
++ nsMemory::Free(unrestricted_hosts);
++ }
++ } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
++ mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
++ nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
++ } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
++ PRInt32 warnLevel = 1;
++ mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
++ nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
+ #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
+- } else if (prefName.Equals("security.ssl.enable_false_start")) {
+- mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
+- SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
++ } else if (prefName.Equals("security.ssl.enable_false_start")) {
++ mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
++ SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
+ #endif
+- } else if (prefName.Equals("security.OCSP.enabled")
+- || prefName.Equals("security.OCSP.require")) {
+- setOCSPOptions(mPrefBranch);
+- } else {
+- /* Look through the cipher table and set according to pref setting */
+- for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
+- if (prefName.Equals(cp->pref)) {
+- mPrefBranch->GetBoolPref(cp->pref, &enabled);
+- SSL_CipherPrefSetDefault(cp->id, enabled);
+- clearSessionCache = PR_TRUE;
+- break;
++ } else if (prefName.Equals("security.OCSP.enabled")
++ || prefName.Equals("security.OCSP.require")) {
++ setOCSPOptions(mPrefBranch);
++ } else {
++ /* Look through the cipher table and set according to pref setting */
++ for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
++ if (prefName.Equals(cp->pref)) {
++ mPrefBranch->GetBoolPref(cp->pref, &enabled);
++ SSL_CipherPrefSetDefault(cp->id, enabled);
++ clearSessionCache = PR_TRUE;
++ break;
++ }
+ }
+ }
++ if (clearSessionCache)
++ SSL_ClearSessionCache();
+ }
+- if (clearSessionCache)
+- SSL_ClearSessionCache();
+ }
+ else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
+@@ -2463,16 +2512,19 @@ nsNSSComponent::RememberCert(CERTCertificate *cert)
+ return NS_OK;
+ }
+
+-void
++PRBool
+ nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
+ {
+ if (mShutdownObjectList->isUIActive()) {
++ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS UI active in profile change!\n"));
+ ShowAlert(ai_crypto_ui_active);
+ nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
+ if (status) {
+ status->VetoChange();
+ }
++ return false;
+ }
++ return true;
+ }
+
+ void
+@@ -2485,16 +2537,18 @@ nsNSSComponent::DoProfileChangeNetTeardown()
+ mIsNetworkDown = PR_TRUE;
+ }
+
+-void
++PRBool
+ nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
+ {
+ PRBool callVeto = PR_FALSE;
+
+ if (!mShutdownObjectList->ifPossibleDisallowUI()) {
+ callVeto = PR_TRUE;
++ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: Not possible to disallow UI!\n"));
+ ShowAlert(ai_crypto_ui_active);
+ }
+ else if (mShutdownObjectList->areSSLSocketsActive()) {
++ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: SSL Sockets are active!\n"));
+ callVeto = PR_TRUE;
+ ShowAlert(ai_sockets_still_active);
+ }
+@@ -2505,9 +2559,11 @@ nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
+ status->VetoChange();
+ }
+ }
++
++ return !callVeto;
+ }
+
+-void
++PRBool
+ nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
+ {
+ NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
+@@ -2526,16 +2582,20 @@ nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
+ }
+
+ StopCRLUpdateTimer();
++ PRBool allow_change = PR_TRUE;
+
+ if (needsCleanup) {
+ if (NS_FAILED(ShutdownNSS())) {
++ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: Shutdown failed\n"));
+ nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
+ if (status) {
+ status->ChangeFailed();
+ }
++ allow_change = PR_FALSE;
+ }
+ }
+ mShutdownObjectList->allowUI();
++ return allow_change;
+ }
+
+ void
+--
+1.7.3.4
+
diff --git a/src/archived-patches/0003-Firefox5-Make-Permissions-Manager-memory-only.patch b/src/archived-patches/0003-Firefox5-Make-Permissions-Manager-memory-only.patch
new file mode 100644
index 0000000..1384245
--- /dev/null
+++ b/src/archived-patches/0003-Firefox5-Make-Permissions-Manager-memory-only.patch
@@ -0,0 +1,94 @@
+From 16bafbf39c89cce901af6500255822677bc4c36d Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Mon, 20 Jun 2011 17:07:56 -0700
+Subject: [PATCH 3/3] Firefox5: Make Permissions Manager memory-only
+
+This patch exposes a pref 'permissions.memory_only' that properly isolates the
+permissions manager to memory, which is responsible for all user specified
+site permissions, as well as stored STS policy.
+
+The pref does successfully clear the permissions manager memory if toggled. It
+does not need to be set in prefs.js, and can be handled by Torbutton.
+
+https://trac.torproject.org/projects/tor/ticket/2950
+---
+ extensions/cookie/nsPermissionManager.cpp | 34 ++++++++++++++++++++++++++--
+ 1 files changed, 31 insertions(+), 3 deletions(-)
+
+diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp
+index 773a973..5387397 100644
+--- a/extensions/cookie/nsPermissionManager.cpp
++++ b/extensions/cookie/nsPermissionManager.cpp
+@@ -58,6 +58,10 @@
+ #include "mozStorageHelper.h"
+ #include "mozStorageCID.h"
+ #include "nsXULAppAPI.h"
++#include "nsCOMPtr.h"
++#include "nsIPrefService.h"
++#include "nsIPrefBranch.h"
++#include "nsIPrefBranch2.h"
+
+ static nsPermissionManager *gPermissionManager = nsnull;
+
+@@ -227,6 +231,11 @@ nsPermissionManager::Init()
+ mObserverService->AddObserver(this, "profile-do-change", PR_TRUE);
+ }
+
++ nsCOMPtr<nsIPrefBranch2> pbi = do_GetService(NS_PREFSERVICE_CONTRACTID);
++ if (pbi) {
++ pbi->AddObserver("permissions.", this, PR_FALSE);
++ }
++
+ if (IsChildProcess()) {
+ // Get the permissions from the parent process
+ InfallibleTArray<IPC::Permission> perms;
+@@ -275,8 +284,18 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
+ if (!storage)
+ return NS_ERROR_UNEXPECTED;
+
++ PRBool memory_db = false;
++ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
++ if (prefs) {
++ prefs->GetBoolPref("permissions.memory_only", &memory_db);
++ }
++
+ // cache a connection to the hosts database
+- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ if (memory_db) {
++ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
++ } else {
++ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRBool ready;
+@@ -286,7 +305,11 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
+ rv = permissionsFile->Remove(PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ if (memory_db) {
++ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
++ } else {
++ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mDBConn->GetConnectionReady(&ready);
+@@ -805,7 +828,12 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
+ {
+ ENSURE_NOT_CHILD_PROCESS;
+
+- if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
++ if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
++ if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("permissions.memory_only").get())) {
++ // XXX: Should we remove the file? Probably not..
++ InitDB(PR_FALSE);
++ }
++ } else if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
+ // The profile is about to change,
+ // or is going away because the application is shutting down.
+ if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
+--
+1.7.3.4
+
diff --git a/src/archived-patches/0004-Firefox4-Make-Permissions-Manager-memory-only.patch b/src/archived-patches/0004-Firefox4-Make-Permissions-Manager-memory-only.patch
new file mode 100644
index 0000000..8f7ddd9
--- /dev/null
+++ b/src/archived-patches/0004-Firefox4-Make-Permissions-Manager-memory-only.patch
@@ -0,0 +1,94 @@
+From 6f37edd80181906c37ace589fc26eabf6731b09d Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Mon, 20 Jun 2011 17:07:56 -0700
+Subject: [PATCH 4/4] Firefox4: Make Permissions Manager memory-only
+
+This patch exposes a pref 'permissions.memory_only' that properly isolates the
+permissions manager to memory, which is responsible for all user specified
+site permissions, as well as stored STS policy.
+
+The pref does successfully clear the permissions manager memory if toggled. It
+does not need to be set in prefs.js, and can be handled by Torbutton.
+
+https://trac.torproject.org/projects/tor/ticket/2950
+---
+ extensions/cookie/nsPermissionManager.cpp | 34 ++++++++++++++++++++++++++--
+ 1 files changed, 31 insertions(+), 3 deletions(-)
+
+diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp
+index d182013..0a1aea6 100644
+--- a/extensions/cookie/nsPermissionManager.cpp
++++ b/extensions/cookie/nsPermissionManager.cpp
+@@ -60,6 +60,10 @@
+ #include "mozStorageHelper.h"
+ #include "mozStorageCID.h"
+ #include "nsXULAppAPI.h"
++#include "nsCOMPtr.h"
++#include "nsIPrefService.h"
++#include "nsIPrefBranch.h"
++#include "nsIPrefBranch2.h"
+
+ static nsPermissionManager *gPermissionManager = nsnull;
+
+@@ -233,6 +237,11 @@ nsPermissionManager::Init()
+ mObserverService->AddObserver(this, "profile-do-change", PR_TRUE);
+ }
+
++ nsCOMPtr<nsIPrefBranch2> pbi = do_GetService(NS_PREFSERVICE_CONTRACTID);
++ if (pbi) {
++ pbi->AddObserver("permissions.", this, PR_FALSE);
++ }
++
+ #ifdef MOZ_IPC
+ if (IsChildProcess()) {
+ // Get the permissions from the parent process
+@@ -283,8 +292,18 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
+ if (!storage)
+ return NS_ERROR_UNEXPECTED;
+
++ PRBool memory_db = false;
++ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
++ if (prefs) {
++ prefs->GetBoolPref("permissions.memory_only", &memory_db);
++ }
++
+ // cache a connection to the hosts database
+- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ if (memory_db) {
++ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
++ } else {
++ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRBool ready;
+@@ -294,7 +313,11 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
+ rv = permissionsFile->Remove(PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ if (memory_db) {
++ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
++ } else {
++ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mDBConn->GetConnectionReady(&ready);
+@@ -825,7 +848,12 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
+ ENSURE_NOT_CHILD_PROCESS;
+ #endif
+
+- if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
++ if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
++ if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("permissions.memory_only").get())) {
++ // XXX: Should we remove the file? Probably not..
++ InitDB(PR_FALSE);
++ }
++ } else if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
+ // The profile is about to change,
+ // or is going away because the application is shutting down.
+ if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
+--
+1.7.3.4
+
diff --git a/src/current-patches/0001-Firefox4-Fix-SOCKS-timeout.patch b/src/current-patches/0001-Firefox4-Fix-SOCKS-timeout.patch
deleted file mode 100644
index 3b9343e..0000000
--- a/src/current-patches/0001-Firefox4-Fix-SOCKS-timeout.patch
+++ /dev/null
@@ -1,1500 +0,0 @@
-From d37dce07b9eb9b40244d2fa867728e7a57a33f0f Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git(a)fscked.org>
-Date: Mon, 20 Jun 2011 17:07:33 -0700
-Subject: [PATCH 1/4] Firefox4: Fix SOCKS timeout
-
-This patch by chrisd removes the hardcoded SOCKS timeout by rewriting the
-Firefox SOCKS code to use non-blocking IO.
-
-See also: https://bugzilla.mozilla.org/show_bug.cgi?id=280661
-https://trac.torproject.org/projects/tor/ticket/3247
----
- netwerk/base/src/nsSocketTransport2.cpp | 21 +-
- netwerk/socket/nsSOCKSIOLayer.cpp | 1273 ++++++++++++++++++-------------
- 2 files changed, 775 insertions(+), 519 deletions(-)
-
-diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp
-index 3f95dfd..fb363db 100644
---- a/netwerk/base/src/nsSocketTransport2.cpp
-+++ b/netwerk/base/src/nsSocketTransport2.cpp
-@@ -1227,6 +1227,16 @@ nsSocketTransport::InitiateSocket()
- }
- }
- //
-+ // A SOCKS request was rejected; get the actual error code from
-+ // the OS error
-+ //
-+ else if (PR_UNKNOWN_ERROR == code &&
-+ mProxyTransparent &&
-+ !mProxyHost.IsEmpty()) {
-+ code = PR_GetOSError();
-+ rv = ErrorAccordingToNSPR(code);
-+ }
-+ //
- // The connection was refused...
- //
- else {
-@@ -1549,7 +1559,16 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 outFlags)
- mPollFlags = (PR_POLL_EXCEPT | PR_POLL_WRITE);
- // Update poll timeout in case it was changed
- mPollTimeout = mTimeouts[TIMEOUT_CONNECT];
-- }
-+ }
-+ //
-+ // The SOCKS proxy rejected our request. Find out why.
-+ //
-+ else if (PR_UNKNOWN_ERROR == code &&
-+ mProxyTransparent &&
-+ !mProxyHost.IsEmpty()) {
-+ code = PR_GetOSError();
-+ mCondition = ErrorAccordingToNSPR(code);
-+ }
- else {
- //
- // else, the connection failed...
-diff --git a/netwerk/socket/nsSOCKSIOLayer.cpp b/netwerk/socket/nsSOCKSIOLayer.cpp
-index 9a15667..4d3a4e8 100644
---- a/netwerk/socket/nsSOCKSIOLayer.cpp
-+++ b/netwerk/socket/nsSOCKSIOLayer.cpp
-@@ -25,6 +25,7 @@
- * Bradley Baetz <bbaetz(a)acm.org>
- * Darin Fisher <darin(a)meer.net>
- * Malcolm Smith <malsmith(a)cs.rmit.edu.au>
-+ * Christopher Davis <chrisd(a)torproject.org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
-@@ -68,9 +69,28 @@ static PRLogModuleInfo *gSOCKSLog;
-
- class nsSOCKSSocketInfo : public nsISOCKSSocketInfo
- {
-+ enum State {
-+ SOCKS_INITIAL,
-+ SOCKS_CONNECTING_TO_PROXY,
-+ SOCKS4_WRITE_CONNECT_REQUEST,
-+ SOCKS4_READ_CONNECT_RESPONSE,
-+ SOCKS5_WRITE_AUTH_REQUEST,
-+ SOCKS5_READ_AUTH_RESPONSE,
-+ SOCKS5_WRITE_CONNECT_REQUEST,
-+ SOCKS5_READ_CONNECT_RESPONSE_TOP,
-+ SOCKS5_READ_CONNECT_RESPONSE_BOTTOM,
-+ SOCKS_CONNECTED,
-+ SOCKS_FAILED
-+ };
-+
-+ // A buffer of 262 bytes should be enough for any request and response
-+ // in case of SOCKS4 as well as SOCKS5
-+ static const PRUint32 BUFFER_SIZE = 262;
-+ static const PRUint32 MAX_HOSTNAME_LEN = 255;
-+
- public:
- nsSOCKSSocketInfo();
-- virtual ~nsSOCKSSocketInfo() {}
-+ virtual ~nsSOCKSSocketInfo() { HandshakeFinished(); }
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSISOCKSSOCKETINFO
-@@ -81,13 +101,50 @@ public:
- const char *destinationHost,
- PRUint32 flags);
-
-- const nsCString &DestinationHost() { return mDestinationHost; }
-- const nsCString &ProxyHost() { return mProxyHost; }
-- PRInt32 ProxyPort() { return mProxyPort; }
-- PRInt32 Version() { return mVersion; }
-- PRUint32 Flags() { return mFlags; }
-+ void SetConnectTimeout(PRIntervalTime to);
-+ PRStatus DoHandshake(PRFileDesc *fd, PRInt16 oflags = -1);
-+ PRInt16 GetPollFlags() const;
-+ bool IsConnected() const { return mState == SOCKS_CONNECTED; }
-+
-+private:
-+ void HandshakeFinished(PRErrorCode err = 0);
-+ PRStatus ConnectToProxy(PRFileDesc *fd);
-+ PRStatus ContinueConnectingToProxy(PRFileDesc *fd, PRInt16 oflags);
-+ PRStatus WriteV4ConnectRequest();
-+ PRStatus ReadV4ConnectResponse();
-+ PRStatus WriteV5AuthRequest();
-+ PRStatus ReadV5AuthResponse();
-+ PRStatus WriteV5ConnectRequest();
-+ PRStatus ReadV5AddrTypeAndLength(PRUint8 *type, PRUint32 *len);
-+ PRStatus ReadV5ConnectResponseTop();
-+ PRStatus ReadV5ConnectResponseBottom();
-+
-+ void WriteUint8(PRUint8 d);
-+ void WriteUint16(PRUint16 d);
-+ void WriteUint32(PRUint32 d);
-+ void WriteNetAddr(const PRNetAddr *addr);
-+ void WriteNetPort(const PRNetAddr *addr);
-+ void WriteString(const nsACString &str);
-+
-+ PRUint8 ReadUint8();
-+ PRUint16 ReadUint16();
-+ PRUint32 ReadUint32();
-+ void ReadNetAddr(PRNetAddr *addr, PRUint16 fam);
-+ void ReadNetPort(PRNetAddr *addr);
-+
-+ void WantRead(PRUint32 sz);
-+ PRStatus ReadFromSocket(PRFileDesc *fd);
-+ PRStatus WriteToSocket(PRFileDesc *fd);
-
- private:
-+ State mState;
-+ PRUint8 * mData;
-+ PRUint8 * mDataIoPtr;
-+ PRUint32 mDataLength;
-+ PRUint32 mReadOffset;
-+ PRUint32 mAmountToRead;
-+ nsCOMPtr<nsIDNSRecord> mDnsRec;
-+
- nsCString mDestinationHost;
- nsCString mProxyHost;
- PRInt32 mProxyPort;
-@@ -96,13 +153,21 @@ private:
- PRNetAddr mInternalProxyAddr;
- PRNetAddr mExternalProxyAddr;
- PRNetAddr mDestinationAddr;
-+ PRIntervalTime mTimeout;
- };
-
- nsSOCKSSocketInfo::nsSOCKSSocketInfo()
-- : mProxyPort(-1)
-+ : mState(SOCKS_INITIAL)
-+ , mDataIoPtr(nsnull)
-+ , mDataLength(0)
-+ , mReadOffset(0)
-+ , mAmountToRead(0)
-+ , mProxyPort(-1)
- , mVersion(-1)
- , mFlags(0)
-+ , mTimeout(PR_INTERVAL_NO_TIMEOUT)
- {
-+ mData = new PRUint8[BUFFER_SIZE];
- PR_InitializeNetAddr(PR_IpAddrAny, 0, &mInternalProxyAddr);
- PR_InitializeNetAddr(PR_IpAddrAny, 0, &mExternalProxyAddr);
- PR_InitializeNetAddr(PR_IpAddrAny, 0, &mDestinationAddr);
-@@ -162,637 +227,807 @@ nsSOCKSSocketInfo::SetInternalProxyAddr(PRNetAddr *aInternalProxyAddr)
- return NS_OK;
- }
-
--static PRInt32
--pr_RecvAll(PRFileDesc *fd, unsigned char *buf, PRInt32 amount, PRIntn flags,
-- PRIntervalTime *timeout)
-+// There needs to be a means of distinguishing between connection errors
-+// that the SOCKS server reports when it rejects a connection request, and
-+// connection errors that happen while attempting to connect to the SOCKS
-+// server. Otherwise, Firefox will report incorrectly that the proxy server
-+// is refusing connections when a SOCKS request is rejected by the proxy.
-+// When a SOCKS handshake failure occurs, the PR error is set to
-+// PR_UNKNOWN_ERROR, and the real error code is returned via the OS error.
-+void
-+nsSOCKSSocketInfo::HandshakeFinished(PRErrorCode err)
- {
-- PRInt32 bytesRead = 0;
-- PRInt32 offset = 0;
-+ if (err == 0) {
-+ mState = SOCKS_CONNECTED;
-+ } else {
-+ mState = SOCKS_FAILED;
-+ PR_SetError(PR_UNKNOWN_ERROR, err);
-+ }
-
-- while (offset < amount) {
-- PRIntervalTime start_time = PR_IntervalNow();
-- bytesRead = PR_Recv(fd, buf + offset, amount - offset, flags, *timeout);
-- PRIntervalTime elapsed = PR_IntervalNow() - start_time;
-+ // We don't need the buffer any longer, so free it.
-+ delete [] mData;
-+ mData = nsnull;
-+ mDataIoPtr = nsnull;
-+ mDataLength = 0;
-+ mReadOffset = 0;
-+ mAmountToRead = 0;
-+}
-
-- if (elapsed > *timeout) {
-- *timeout = 0;
-- } else {
-- *timeout -= elapsed;
-- }
-+PRStatus
-+nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc *fd)
-+{
-+ PRStatus status;
-+ nsresult rv;
-
-- if (bytesRead > 0) {
-- offset += bytesRead;
-- } else if (bytesRead == 0 || offset != 0) {
-- return offset;
-- } else {
-- return bytesRead;
-- }
-+ NS_ABORT_IF_FALSE(mState == SOCKS_INITIAL,
-+ "Must be in initial state to make connection!");
-
-- if (*timeout == 0) {
-- LOGERROR(("PR_Recv() timed out. amount = %d. offset = %d.",
-- amount, offset));
-- return offset;
-+ // If we haven't performed the DNS lookup, do that now.
-+ if (!mDnsRec) {
-+ nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
-+ if (!dns)
-+ return PR_FAILURE;
-+
-+ rv = dns->Resolve(mProxyHost, 0, getter_AddRefs(mDnsRec));
-+ if (NS_FAILED(rv)) {
-+ LOGERROR(("socks: DNS lookup for SOCKS proxy %s failed",
-+ mProxyHost.get()));
-+ return PR_FAILURE;
- }
- }
-- return offset;
--}
-
--static PRInt32
--pr_Send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
-- PRIntervalTime *timeout)
--{
-- PRIntervalTime start_time = PR_IntervalNow();
-- PRInt32 retval = PR_Send(fd, buf, amount, flags, *timeout);
-- PRIntervalTime elapsed = PR_IntervalNow() - start_time;
--
-- if (elapsed > *timeout) {
-- *timeout = 0;
-- LOGERROR(("PR_Send() timed out. amount = %d. retval = %d.",
-- amount, retval));
-- return retval;
-- } else {
-- *timeout -= elapsed;
-- }
-+ do {
-+ rv = mDnsRec->GetNextAddr(mProxyPort, &mInternalProxyAddr);
-+ // No more addresses to try? If so, we'll need to bail
-+ if (NS_FAILED(rv)) {
-+ LOGERROR(("socks: unable to connect to SOCKS proxy, %s",
-+ mProxyHost.get()));
-+ return PR_FAILURE;
-+ }
-
-- if (retval <= 0) {
-- LOGERROR(("PR_Send() failed. amount = %d. retval = %d.",
-- amount, retval));
-- }
-+#if defined(PR_LOGGING)
-+ char buf[64];
-+ PR_NetAddrToString(&mInternalProxyAddr, buf, sizeof(buf));
-+ LOGDEBUG(("socks: trying proxy server, %s:%hu",
-+ buf, PR_ntohs(PR_NetAddrInetPort(&mInternalProxyAddr))));
-+#endif
-+ status = fd->lower->methods->connect(fd->lower,
-+ &mInternalProxyAddr, mTimeout);
-+ if (status != PR_SUCCESS) {
-+ PRErrorCode c = PR_GetError();
-+ // If EINPROGRESS, return now and check back later after polling
-+ if (c == PR_WOULD_BLOCK_ERROR || c == PR_IN_PROGRESS_ERROR) {
-+ mState = SOCKS_CONNECTING_TO_PROXY;
-+ return status;
-+ }
-+ }
-+ } while (status != PR_SUCCESS);
-
-- return retval;
-+ // Connected now, start SOCKS
-+ if (mVersion == 4)
-+ return WriteV4ConnectRequest();
-+ return WriteV5AuthRequest();
- }
-
--// Negotiate a SOCKS 5 connection. Assumes the TCP connection to the socks
--// server port has been established.
--static nsresult
--ConnectSOCKS5(PRFileDesc *fd, const PRNetAddr *addr, PRNetAddr *extAddr, PRIntervalTime timeout)
-+PRStatus
-+nsSOCKSSocketInfo::ContinueConnectingToProxy(PRFileDesc *fd, PRInt16 oflags)
- {
-- int request_len = 0;
-- int response_len = 0;
-- int desired_len = 0;
-- unsigned char request[22];
-- unsigned char response[262];
--
-- NS_ENSURE_TRUE(fd, NS_ERROR_NOT_INITIALIZED);
-- NS_ENSURE_TRUE(addr, NS_ERROR_NOT_INITIALIZED);
-- NS_ENSURE_TRUE(extAddr, NS_ERROR_NOT_INITIALIZED);
--
-- request[0] = 0x05; // SOCKS version 5
-- request[1] = 0x01; // number of auth procotols we recognize
-- // auth protocols
-- request[2] = 0x00; // no authentication required
-- // compliant implementations MUST implement GSSAPI
-- // and SHOULD implement username/password and MAY
-- // implement CHAP
-- // TODO: we don't implement these
-- //request[3] = 0x01; // GSSAPI
-- //request[4] = 0x02; // username/password
-- //request[5] = 0x03; // CHAP
-+ PRStatus status;
-
-- request_len = 2 + request[1];
-- int write_len = pr_Send(fd, request, request_len, 0, &timeout);
-- if (write_len != request_len) {
-- return NS_ERROR_FAILURE;
-- }
-+ NS_ABORT_IF_FALSE(mState == SOCKS_CONNECTING_TO_PROXY,
-+ "Continuing connection in wrong state!");
-
-- // get the server's response.
-- desired_len = 2;
-- response_len = pr_RecvAll(fd, response, desired_len, 0, &timeout);
-+ LOGDEBUG(("socks: continuing connection to proxy"));
-
-- if (response_len < desired_len) {
-- LOGERROR(("pr_RecvAll() failed. response_len = %d.", response_len));
-- return NS_ERROR_FAILURE;
-- }
-+ status = fd->lower->methods->connectcontinue(fd->lower, oflags);
-+ if (status != PR_SUCCESS) {
-+ PRErrorCode c = PR_GetError();
-+ if (c != PR_WOULD_BLOCK_ERROR && c != PR_IN_PROGRESS_ERROR) {
-+ // A connection failure occured, try another address
-+ mState = SOCKS_INITIAL;
-+ return ConnectToProxy(fd);
-+ }
-
-- if (response[0] != 0x05) {
-- // it's a either not SOCKS or not our version
-- LOGERROR(("Not a SOCKS 5 reply. Expected: 5; received: %x", response[0]));
-- return NS_ERROR_FAILURE;
-- }
-- switch (response[1]) {
-- case 0x00:
-- // no auth
-- break;
-- case 0x01:
-- // GSSAPI
-- // TODO: implement
-- LOGERROR(("Server want to use GSSAPI to authenticate, but we don't support it."));
-- return NS_ERROR_FAILURE;
-- case 0x02:
-- // username/password
-- // TODO: implement
-- LOGERROR(("Server want to use username/password to authenticate, but we don't support it."));
-- return NS_ERROR_FAILURE;
-- case 0x03:
-- // CHAP
-- // TODO: implement?
-- LOGERROR(("Server want to use CHAP to authenticate, but we don't support it."));
-- return NS_ERROR_FAILURE;
-- default:
-- // unrecognized auth method
-- LOGERROR(("Uncrecognized authentication method received: %x", response[1]));
-- return NS_ERROR_FAILURE;
-+ // We're still connecting
-+ return PR_FAILURE;
- }
-
-- // we are now authenticated, so lets tell
-- // the server where to connect to
-+ // Connected now, start SOCKS
-+ if (mVersion == 4)
-+ return WriteV4ConnectRequest();
-+ return WriteV5AuthRequest();
-+}
-
-- request_len = 0;
-+PRStatus
-+nsSOCKSSocketInfo::WriteV4ConnectRequest()
-+{
-+ PRNetAddr *addr = &mDestinationAddr;
-+ PRInt32 proxy_resolve;
-
-- request[0] = 0x05; // SOCKS version 5
-- request[1] = 0x01; // CONNECT command
-- request[2] = 0x00; // obligatory reserved field (perfect for MS tampering!)
-+ NS_ABORT_IF_FALSE(mState == SOCKS_CONNECTING_TO_PROXY,
-+ "Invalid state!");
-+
-+ proxy_resolve = mFlags & nsISocketProvider::PROXY_RESOLVES_HOST;
-+
-+ mDataLength = 0;
-+ mState = SOCKS4_WRITE_CONNECT_REQUEST;
-+
-+ LOGDEBUG(("socks4: sending connection request (socks4a resolve? %s)",
-+ proxy_resolve? "yes" : "no"));
-+
-+ // Send a SOCKS 4 connect request.
-+ WriteUint8(0x04); // version -- 4
-+ WriteUint8(0x01); // command -- connect
-+ WriteNetPort(addr);
-+ if (proxy_resolve) {
-+ // Add the full name, null-terminated, to the request
-+ // according to SOCKS 4a. A fake IP address, with the first
-+ // four bytes set to 0 and the last byte set to something other
-+ // than 0, is used to notify the proxy that this is a SOCKS 4a
-+ // request. This request type works for Tor and perhaps others.
-+ WriteUint32(PR_htonl(0x00000001)); // Fake IP
-+ WriteUint8(0x00); // Send an emtpy username
-+ if (mDestinationHost.Length() > MAX_HOSTNAME_LEN) {
-+ LOGERROR(("socks4: destination host name is too long!"));
-+ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
-+ return PR_FAILURE;
-+ }
-+ WriteString(mDestinationHost); // Hostname
-+ WriteUint8(0x00);
-+ } else if (PR_NetAddrFamily(addr) == PR_AF_INET) {
-+ WriteNetAddr(addr); // Add the IPv4 address
-+ WriteUint8(0x00); // Send an emtpy username
-+ } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
-+ LOGERROR(("socks: SOCKS 4 can't handle IPv6 addresses!"));
-+ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
-+ return PR_FAILURE;
-+ }
-
-- // get destination port
-- PRInt32 destPort = PR_ntohs(PR_NetAddrInetPort(addr));
-- nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
-+ return PR_SUCCESS;
-+}
-
-- if (info->Flags() & nsISocketProvider::PROXY_RESOLVES_HOST) {
-+PRStatus
-+nsSOCKSSocketInfo::ReadV4ConnectResponse()
-+{
-+ NS_ABORT_IF_FALSE(mState == SOCKS4_READ_CONNECT_RESPONSE,
-+ "Handling SOCKS 4 connection reply in wrong state!");
-+ NS_ABORT_IF_FALSE(mDataLength == 8,
-+ "SOCKS 4 connection reply must be 8 bytes!");
-
-- LOGDEBUG(("using server to resolve hostnames rather than resolving it first\n"));
-+ LOGDEBUG(("socks4: checking connection reply"));
-
-- // if the PROXY_RESOLVES_HOST flag is set, we assume
-- // that the transport wants us to pass the SOCKS server the
-- // hostname and port and let it do the name resolution.
-+ if (ReadUint8() != 0x00) {
-+ LOGERROR(("socks4: wrong connection reply"));
-+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
-+ return PR_FAILURE;
-+ }
-
-- // the real destination hostname and port was stored
-- // in our info object earlier when this layer was created.
-+ // See if our connection request was granted
-+ if (ReadUint8() == 90) {
-+ LOGDEBUG(("socks4: connection successful!"));
-+ HandshakeFinished();
-+ return PR_SUCCESS;
-+ }
-
-- const nsCString& destHost = info->DestinationHost();
-+ LOGERROR(("socks4: unable to connect"));
-+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
-+ return PR_FAILURE;
-+}
-
-- LOGDEBUG(("host:port -> %s:%li", destHost.get(), destPort));
-+PRStatus
-+nsSOCKSSocketInfo::WriteV5AuthRequest()
-+{
-+ NS_ABORT_IF_FALSE(mVersion == 5, "SOCKS version must be 5!");
-
-- request[3] = 0x03; // encoding of destination address (3 == hostname)
-+ mState = SOCKS5_WRITE_AUTH_REQUEST;
-
-- int host_len = destHost.Length();
-- if (host_len > 255) {
-- // SOCKS5 transmits the length of the hostname in a single char.
-- // This gives us an absolute limit of 255 chars in a hostname, and
-- // there's nothing we can do to extend it. I don't think many
-- // hostnames will ever be bigger than this, so hopefully it's an
-- // uneventful abort condition.
-- LOGERROR (("Hostname too big for SOCKS5."));
-- return NS_ERROR_INVALID_ARG;
-- }
-- request[4] = (char) host_len;
-- request_len = 5;
--
-- // Send the initial header first...
-- write_len = pr_Send(fd, request, request_len, 0, &timeout);
-- if (write_len != request_len) {
-- // bad write
-- return NS_ERROR_FAILURE;
-- }
-+ // Send an initial SOCKS 5 greeting
-+ LOGDEBUG(("socks5: sending auth methods"));
-+ WriteUint8(0x05); // version -- 5
-+ WriteUint8(0x01); // # auth methods -- 1
-+ WriteUint8(0x00); // we don't support authentication
-
-- // Now send the hostname...
-- write_len = pr_Send(fd, destHost.get(), host_len, 0, &timeout);
-- if (write_len != host_len) {
-- // bad write
-- return NS_ERROR_FAILURE;
-- }
-+ return PR_SUCCESS;
-+}
-
-- // There's no data left because we just sent it.
-- request_len = 0;
-+PRStatus
-+nsSOCKSSocketInfo::ReadV5AuthResponse()
-+{
-+ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_AUTH_RESPONSE,
-+ "Handling SOCKS 5 auth method reply in wrong state!");
-+ NS_ABORT_IF_FALSE(mDataLength == 2,
-+ "SOCKS 5 auth method reply must be 2 bytes!");
-
-- } else if (PR_NetAddrFamily(addr) == PR_AF_INET) {
-+ LOGDEBUG(("socks5: checking auth method reply"));
-
-- request[3] = 0x01; // encoding of destination address (1 == IPv4)
-- request_len = 8; // 4 for address, 4 SOCKS headers
-+ // Check version number
-+ if (ReadUint8() != 0x05) {
-+ LOGERROR(("socks5: unexpected version in the reply"));
-+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
-+ return PR_FAILURE;
-+ }
-
-- char * ip = (char*)(&addr->inet.ip);
-- request[4] = *ip++;
-- request[5] = *ip++;
-- request[6] = *ip++;
-- request[7] = *ip++;
-+ // Make sure our authentication choice was accepted
-+ if (ReadUint8() != 0x00) {
-+ LOGERROR(("socks5: server did not accept our authentication method"));
-+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
-+ return PR_FAILURE;
-+ }
-
-- } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
-+ return WriteV5ConnectRequest();
-+}
-
-- request[3] = 0x04; // encoding of destination address (4 == IPv6)
-- request_len = 20; // 16 for address, 4 SOCKS headers
--
-- char * ip = (char*)(&addr->ipv6.ip.pr_s6_addr);
-- request[4] = *ip++; request[5] = *ip++;
-- request[6] = *ip++; request[7] = *ip++;
-- request[8] = *ip++; request[9] = *ip++;
-- request[10] = *ip++; request[11] = *ip++;
-- request[12] = *ip++; request[13] = *ip++;
-- request[14] = *ip++; request[15] = *ip++;
-- request[16] = *ip++; request[17] = *ip++;
-- request[18] = *ip++; request[19] = *ip++;
--
-- // we're going to test to see if this address can
-- // be mapped back into IPv4 without loss. if so,
-- // we'll use IPv4 instead, as reliable SOCKS server
-- // support for IPv6 is probably questionable.
--
-- if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
-- request[3] = 0x01; // ipv4 encoding
-- request[4] = request[16];
-- request[5] = request[17];
-- request[6] = request[18];
-- request[7] = request[19];
-- request_len -= 12;
-+PRStatus
-+nsSOCKSSocketInfo::WriteV5ConnectRequest()
-+{
-+ // Send SOCKS 5 connect request
-+ PRNetAddr *addr = &mDestinationAddr;
-+ PRInt32 proxy_resolve;
-+ proxy_resolve = mFlags & nsISocketProvider::PROXY_RESOLVES_HOST;
-+
-+ LOGDEBUG(("socks5: sending connection request (socks5 resolve? %s)",
-+ proxy_resolve? "yes" : "no"));
-+
-+ mDataLength = 0;
-+ mState = SOCKS5_WRITE_CONNECT_REQUEST;
-+
-+ WriteUint8(0x05); // version -- 5
-+ WriteUint8(0x01); // command -- connect
-+ WriteUint8(0x00); // reserved
-+
-+ // Add the address to the SOCKS 5 request. SOCKS 5 supports several
-+ // address types, so we pick the one that works best for us.
-+ if (proxy_resolve) {
-+ // Add the host name. Only a single byte is used to store the length,
-+ // so we must prevent long names from being used.
-+ if (mDestinationHost.Length() > MAX_HOSTNAME_LEN) {
-+ LOGERROR(("socks5: destination host name is too long!"));
-+ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
-+ return PR_FAILURE;
- }
-+ WriteUint8(0x03); // addr type -- domainname
-+ WriteUint8(mDestinationHost.Length()); // name length
-+ WriteString(mDestinationHost);
-+ } else if (PR_NetAddrFamily(addr) == PR_AF_INET) {
-+ WriteUint8(0x01); // addr type -- IPv4
-+ WriteNetAddr(addr);
-+ } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
-+ WriteUint8(0x04); // addr type -- IPv6
-+ WriteNetAddr(addr);
- } else {
-- // Unknown address type
-- LOGERROR(("Don't know what kind of IP address this is."));
-- return NS_ERROR_FAILURE;
-- }
--
-- // add the destination port to the request
-- request[request_len] = (unsigned char)(destPort >> 8);
-- request[request_len+1] = (unsigned char)destPort;
-- request_len += 2;
--
-- write_len = pr_Send(fd, request, request_len, 0, &timeout);
-- if (write_len != request_len) {
-- // bad write
-- return NS_ERROR_FAILURE;
-+ LOGERROR(("socks5: destination address of unknown type!"));
-+ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
-+ return PR_FAILURE;
- }
-
-- desired_len = 5;
-- response_len = pr_RecvAll(fd, response, desired_len, 0, &timeout);
-- if (response_len < desired_len) { // bad read
-- LOGERROR(("pr_RecvAll() failed getting connect command reply. response_len = %d.", response_len));
-- return NS_ERROR_FAILURE;
-- }
-+ WriteNetPort(addr); // port
-
-- if (response[0] != 0x05) {
-- // bad response
-- LOGERROR(("Not a SOCKS 5 reply. Expected: 5; received: %x", response[0]));
-- return NS_ERROR_FAILURE;
-- }
-+ return PR_SUCCESS;
-+}
-
-- switch(response[1]) {
-- case 0x00: break; // success
-- case 0x01: LOGERROR(("SOCKS 5 server rejected connect request: 01, General SOCKS server failure."));
-- return NS_ERROR_FAILURE;
-- case 0x02: LOGERROR(("SOCKS 5 server rejected connect request: 02, Connection not allowed by ruleset."));
-- return NS_ERROR_FAILURE;
-- case 0x03: LOGERROR(("SOCKS 5 server rejected connect request: 03, Network unreachable."));
-- return NS_ERROR_FAILURE;
-- case 0x04: LOGERROR(("SOCKS 5 server rejected connect request: 04, Host unreachable."));
-- return NS_ERROR_FAILURE;
-- case 0x05: LOGERROR(("SOCKS 5 server rejected connect request: 05, Connection refused."));
-- return NS_ERROR_FAILURE;
-- case 0x06: LOGERROR(("SOCKS 5 server rejected connect request: 06, TTL expired."));
-- return NS_ERROR_FAILURE;
-- case 0x07: LOGERROR(("SOCKS 5 server rejected connect request: 07, Command not supported."));
-- return NS_ERROR_FAILURE;
-- case 0x08: LOGERROR(("SOCKS 5 server rejected connect request: 08, Address type not supported."));
-- return NS_ERROR_FAILURE;
-- default: LOGERROR(("SOCKS 5 server rejected connect request: %x.", response[1]));
-- return NS_ERROR_FAILURE;
--
--
-- }
--
-- switch (response[3]) {
-- case 0x01: // IPv4
-- desired_len = 4 + 2 - 1;
-- break;
-- case 0x03: // FQDN
-- desired_len = response[4] + 2;
-+PRStatus
-+nsSOCKSSocketInfo::ReadV5AddrTypeAndLength(PRUint8 *type, PRUint32 *len)
-+{
-+ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_CONNECT_RESPONSE_TOP ||
-+ mState == SOCKS5_READ_CONNECT_RESPONSE_BOTTOM,
-+ "Invalid state!");
-+ NS_ABORT_IF_FALSE(mDataLength >= 5,
-+ "SOCKS 5 connection reply must be at least 5 bytes!");
-+
-+ // Seek to the address location
-+ mReadOffset = 3;
-+
-+ *type = ReadUint8();
-+
-+ switch (*type) {
-+ case 0x01: // ipv4
-+ *len = 4 - 1;
- break;
-- case 0x04: // IPv6
-- desired_len = 16 + 2 - 1;
-+ case 0x04: // ipv6
-+ *len = 16 - 1;
- break;
-- default: // unknown format
-- return NS_ERROR_FAILURE;
-+ case 0x03: // fqdn
-+ *len = ReadUint8();
- break;
-+ default: // wrong address type
-+ LOGERROR(("socks5: wrong address type in connection reply!"));
-+ return PR_FAILURE;
- }
-- response_len = pr_RecvAll(fd, response + 5, desired_len, 0, &timeout);
-- if (response_len < desired_len) { // bad read
-- LOGERROR(("pr_RecvAll() failed getting connect command reply. response_len = %d.", response_len));
-- return NS_ERROR_FAILURE;
-- }
-- response_len += 5;
-
-- // get external bound address (this is what
-- // the outside world sees as "us")
-- char *ip = nsnull;
-- PRUint16 extPort = 0;
-+ return PR_SUCCESS;
-+}
-
-- switch (response[3]) {
-- case 0x01: // IPv4
-+PRStatus
-+nsSOCKSSocketInfo::ReadV5ConnectResponseTop()
-+{
-+ PRUint8 res;
-+ PRUint32 len;
-
-- extPort = (response[8] << 8) | response[9];
-+ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_CONNECT_RESPONSE_TOP,
-+ "Invalid state!");
-+ NS_ABORT_IF_FALSE(mDataLength == 5,
-+ "SOCKS 5 connection reply must be exactly 5 bytes!");
-
-- PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET, extPort, extAddr);
-+ LOGDEBUG(("socks5: checking connection reply"));
-
-- ip = (char*)(&extAddr->inet.ip);
-- *ip++ = response[4];
-- *ip++ = response[5];
-- *ip++ = response[6];
-- *ip++ = response[7];
-+ // Check version number
-+ if (ReadUint8() != 0x05) {
-+ LOGERROR(("socks5: unexpected version in the reply"));
-+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
-+ return PR_FAILURE;
-+ }
-
-- break;
-- case 0x04: // IPv6
-+ // Check response
-+ res = ReadUint8();
-+ if (res != 0x00) {
-+ PRErrorCode c = PR_CONNECT_REFUSED_ERROR;
-+
-+ switch (res) {
-+ case 0x01:
-+ LOGERROR(("socks5: connect failed: "
-+ "01, General SOCKS server failure."));
-+ break;
-+ case 0x02:
-+ LOGERROR(("socks5: connect failed: "
-+ "02, Connection not allowed by ruleset."));
-+ break;
-+ case 0x03:
-+ LOGERROR(("socks5: connect failed: 03, Network unreachable."));
-+ c = PR_NETWORK_UNREACHABLE_ERROR;
-+ break;
-+ case 0x04:
-+ LOGERROR(("socks5: connect failed: 04, Host unreachable."));
-+ break;
-+ case 0x05:
-+ LOGERROR(("socks5: connect failed: 05, Connection refused."));
-+ break;
-+ case 0x06:
-+ LOGERROR(("socks5: connect failed: 06, TTL expired."));
-+ c = PR_CONNECT_TIMEOUT_ERROR;
-+ break;
-+ case 0x07:
-+ LOGERROR(("socks5: connect failed: "
-+ "07, Command not supported."));
-+ break;
-+ case 0x08:
-+ LOGERROR(("socks5: connect failed: "
-+ "08, Address type not supported."));
-+ c = PR_BAD_ADDRESS_ERROR;
-+ break;
-+ default:
-+ LOGERROR(("socks5: connect failed."));
-+ break;
-+ }
-
-- extPort = (response[20] << 8) | response[21];
-+ HandshakeFinished(c);
-+ return PR_FAILURE;
-+ }
-
-- PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, extPort, extAddr);
-+ if (ReadV5AddrTypeAndLength(&res, &len) != PR_SUCCESS) {
-+ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
-+ return PR_FAILURE;
-+ }
-
-- ip = (char*)(&extAddr->ipv6.ip.pr_s6_addr);
-- *ip++ = response[4]; *ip++ = response[5];
-- *ip++ = response[6]; *ip++ = response[7];
-- *ip++ = response[8]; *ip++ = response[9];
-- *ip++ = response[10]; *ip++ = response[11];
-- *ip++ = response[12]; *ip++ = response[13];
-- *ip++ = response[14]; *ip++ = response[15];
-- *ip++ = response[16]; *ip++ = response[17];
-- *ip++ = response[18]; *ip++ = response[19];
-+ mState = SOCKS5_READ_CONNECT_RESPONSE_BOTTOM;
-+ WantRead(len + 2);
-
-- break;
-- case 0x03: // FQDN
-- // if we get here, we don't know our external address.
-- // however, as that's possibly not critical to the user,
-- // we let it slide.
-- extPort = (response[response_len - 2] << 8) |
-- response[response_len - 1];
-- PR_InitializeNetAddr(PR_IpAddrNull, extPort, extAddr);
-- break;
-- }
-- return NS_OK;
-+ return PR_SUCCESS;
- }
-
--// Negotiate a SOCKS 4 connection. Assumes the TCP connection to the socks
--// server port has been established.
--static nsresult
--ConnectSOCKS4(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
-+PRStatus
-+nsSOCKSSocketInfo::ReadV5ConnectResponseBottom()
- {
-- int request_len = 0;
-- int write_len;
-- int response_len = 0;
-- int desired_len = 0;
-- char *ip = nsnull;
-- unsigned char request[12];
-- unsigned char response[10];
-+ PRUint8 type;
-+ PRUint32 len;
-
-- NS_ENSURE_TRUE(fd, NS_ERROR_NOT_INITIALIZED);
-- NS_ENSURE_TRUE(addr, NS_ERROR_NOT_INITIALIZED);
-+ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_CONNECT_RESPONSE_BOTTOM,
-+ "Invalid state!");
-
-- request[0] = 0x04; // SOCKS version 4
-- request[1] = 0x01; // CD command code -- 1 for connect
--
-- // destination port
-- PRInt32 destPort = PR_ntohs(PR_NetAddrInetPort(addr));
--
-- // store the port
-- request[2] = (unsigned char)(destPort >> 8);
-- request[3] = (unsigned char)destPort;
--
-- // username
-- request[8] = 'M';
-- request[9] = 'O';
-- request[10] = 'Z';
--
-- request[11] = 0x00;
--
-- request_len = 12;
--
-- nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
-+ if (ReadV5AddrTypeAndLength(&type, &len) != PR_SUCCESS) {
-+ HandshakeFinished(PR_BAD_ADDRESS_ERROR);
-+ return PR_FAILURE;
-+ }
-
-- if (info->Flags() & nsISocketProvider::PROXY_RESOLVES_HOST) {
-+ NS_ABORT_IF_FALSE(mDataLength == 7+len,
-+ "SOCKS 5 unexpected length of connection reply!");
-
-- LOGDEBUG(("using server to resolve hostnames rather than resolving it first\n"));
-+ LOGDEBUG(("socks5: loading source addr and port"));
-+ // Read what the proxy says is our source address
-+ switch (type) {
-+ case 0x01: // ipv4
-+ ReadNetAddr(&mExternalProxyAddr, PR_AF_INET);
-+ break;
-+ case 0x04: // ipv6
-+ ReadNetAddr(&mExternalProxyAddr, PR_AF_INET6);
-+ break;
-+ case 0x03: // fqdn (skip)
-+ mReadOffset += len;
-+ mExternalProxyAddr.raw.family = PR_AF_INET;
-+ break;
-+ }
-
-- // if the PROXY_RESOLVES_HOST flag is set, we assume that the
-- // transport wants us to pass the SOCKS server the hostname
-- // and port and let it do the name resolution.
-+ ReadNetPort(&mExternalProxyAddr);
-
-- // an extension to SOCKS 4, called 4a, specifies a way
-- // to do this, so we'll try that and hope the
-- // server supports it.
-+ LOGDEBUG(("socks5: connected!"));
-+ HandshakeFinished();
-
-- // the real destination hostname and port was stored
-- // in our info object earlier when this layer was created.
-+ return PR_SUCCESS;
-+}
-
-- const nsCString& destHost = info->DestinationHost();
-+void
-+nsSOCKSSocketInfo::SetConnectTimeout(PRIntervalTime to)
-+{
-+ mTimeout = to;
-+}
-
-- LOGDEBUG(("host:port -> %s:%li\n", destHost.get(), destPort));
-+PRStatus
-+nsSOCKSSocketInfo::DoHandshake(PRFileDesc *fd, PRInt16 oflags)
-+{
-+ LOGDEBUG(("socks: DoHandshake(), state = %d", mState));
-+
-+ switch (mState) {
-+ case SOCKS_INITIAL:
-+ return ConnectToProxy(fd);
-+ case SOCKS_CONNECTING_TO_PROXY:
-+ return ContinueConnectingToProxy(fd, oflags);
-+ case SOCKS4_WRITE_CONNECT_REQUEST:
-+ if (WriteToSocket(fd) != PR_SUCCESS)
-+ return PR_FAILURE;
-+ WantRead(8);
-+ mState = SOCKS4_READ_CONNECT_RESPONSE;
-+ return PR_SUCCESS;
-+ case SOCKS4_READ_CONNECT_RESPONSE:
-+ if (ReadFromSocket(fd) != PR_SUCCESS)
-+ return PR_FAILURE;
-+ return ReadV4ConnectResponse();
-+
-+ case SOCKS5_WRITE_AUTH_REQUEST:
-+ if (WriteToSocket(fd) != PR_SUCCESS)
-+ return PR_FAILURE;
-+ WantRead(2);
-+ mState = SOCKS5_READ_AUTH_RESPONSE;
-+ return PR_SUCCESS;
-+ case SOCKS5_READ_AUTH_RESPONSE:
-+ if (ReadFromSocket(fd) != PR_SUCCESS)
-+ return PR_FAILURE;
-+ return ReadV5AuthResponse();
-+ case SOCKS5_WRITE_CONNECT_REQUEST:
-+ if (WriteToSocket(fd) != PR_SUCCESS)
-+ return PR_FAILURE;
-+
-+ // The SOCKS 5 response to the connection request is variable
-+ // length. First, we'll read enough to tell how long the response
-+ // is, and will read the rest later.
-+ WantRead(5);
-+ mState = SOCKS5_READ_CONNECT_RESPONSE_TOP;
-+ return PR_SUCCESS;
-+ case SOCKS5_READ_CONNECT_RESPONSE_TOP:
-+ if (ReadFromSocket(fd) != PR_SUCCESS)
-+ return PR_FAILURE;
-+ return ReadV5ConnectResponseTop();
-+ case SOCKS5_READ_CONNECT_RESPONSE_BOTTOM:
-+ if (ReadFromSocket(fd) != PR_SUCCESS)
-+ return PR_FAILURE;
-+ return ReadV5ConnectResponseBottom();
-+
-+ case SOCKS_CONNECTED:
-+ LOGERROR(("socks: already connected"));
-+ HandshakeFinished(PR_IS_CONNECTED_ERROR);
-+ return PR_FAILURE;
-+ case SOCKS_FAILED:
-+ LOGERROR(("socks: already failed"));
-+ return PR_FAILURE;
-+ }
-
-- // the IP portion of the query is set to this special address.
-- request[4] = 0;
-- request[5] = 0;
-- request[6] = 0;
-- request[7] = 1;
-+ LOGERROR(("socks: executing handshake in invalid state, %d", mState));
-+ HandshakeFinished(PR_INVALID_STATE_ERROR);
-
-- write_len = pr_Send(fd, request, request_len, 0, &timeout);
-- if (write_len != request_len) {
-- return NS_ERROR_FAILURE;
-- }
-+ return PR_FAILURE;
-+}
-
-- // Remember the NULL.
-- int host_len = destHost.Length() + 1;
-+PRInt16
-+nsSOCKSSocketInfo::GetPollFlags() const
-+{
-+ switch (mState) {
-+ case SOCKS_CONNECTING_TO_PROXY:
-+ return PR_POLL_EXCEPT | PR_POLL_WRITE;
-+ case SOCKS4_WRITE_CONNECT_REQUEST:
-+ case SOCKS5_WRITE_AUTH_REQUEST:
-+ case SOCKS5_WRITE_CONNECT_REQUEST:
-+ return PR_POLL_WRITE;
-+ case SOCKS4_READ_CONNECT_RESPONSE:
-+ case SOCKS5_READ_AUTH_RESPONSE:
-+ case SOCKS5_READ_CONNECT_RESPONSE_TOP:
-+ case SOCKS5_READ_CONNECT_RESPONSE_BOTTOM:
-+ return PR_POLL_READ;
-+ default:
-+ break;
-+ }
-
-- write_len = pr_Send(fd, destHost.get(), host_len, 0, &timeout);
-- if (write_len != host_len) {
-- return NS_ERROR_FAILURE;
-- }
-+ return 0;
-+}
-
-- // No data to send, just sent it.
-- request_len = 0;
--
-- } else if (PR_NetAddrFamily(addr) == PR_AF_INET) { // IPv4
--
-- // store the ip
-- ip = (char*)(&addr->inet.ip);
-- request[4] = *ip++;
-- request[5] = *ip++;
-- request[6] = *ip++;
-- request[7] = *ip++;
--
-- } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) { // IPv6
--
-- // IPv4 address encoded in an IPv6 address
-- if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
-- // store the ip
-- ip = (char*)(&addr->ipv6.ip.pr_s6_addr[12]);
-- request[4] = *ip++;
-- request[5] = *ip++;
-- request[6] = *ip++;
-- request[7] = *ip++;
-- } else {
-- LOGERROR(("IPv6 is not supported in SOCKS 4."));
-- return NS_ERROR_FAILURE; // SOCKS 4 can't do IPv6
-- }
-+inline void
-+nsSOCKSSocketInfo::WriteUint8(PRUint8 v)
-+{
-+ NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
-+ "Can't write that much data!");
-+ mData[mDataLength] = v;
-+ mDataLength += sizeof(v);
-+}
-
-- } else {
-- LOGERROR(("Don't know what kind of IP address this is."));
-- return NS_ERROR_FAILURE; // don't recognize this type
-- }
-+inline void
-+nsSOCKSSocketInfo::WriteUint16(PRUint16 v)
-+{
-+ NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
-+ "Can't write that much data!");
-+ memcpy(mData + mDataLength, &v, sizeof(v));
-+ mDataLength += sizeof(v);
-+}
-
-- if (request_len > 0) {
-- write_len = pr_Send(fd, request, request_len, 0, &timeout);
-- if (write_len != request_len) {
-- return NS_ERROR_FAILURE;
-- }
-- }
-+inline void
-+nsSOCKSSocketInfo::WriteUint32(PRUint32 v)
-+{
-+ NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
-+ "Can't write that much data!");
-+ memcpy(mData + mDataLength, &v, sizeof(v));
-+ mDataLength += sizeof(v);
-+}
-
-- // get the server's response
-- desired_len = 8; // size of the response
-- response_len = pr_RecvAll(fd, response, desired_len, 0, &timeout);
-- if (response_len < desired_len) {
-- LOGERROR(("pr_RecvAll() failed. response_len = %d.", response_len));
-- return NS_ERROR_FAILURE;
-- }
-+void
-+nsSOCKSSocketInfo::WriteNetAddr(const PRNetAddr *addr)
-+{
-+ const char *ip = NULL;
-+ PRUint32 len = 0;
-
-- if ((response[0] != 0x00) && (response[0] != 0x04)) {
-- // Novell BorderManager sends a response of type 4, should be zero
-- // According to the spec. Cope with this brokenness.
-- // it's not a SOCKS 4 reply or version 0 of the reply code
-- LOGERROR(("Not a SOCKS 4 reply. Expected: 0; received: %x.", response[0]));
-- return NS_ERROR_FAILURE;
-+ if (PR_NetAddrFamily(addr) == PR_AF_INET) {
-+ ip = (const char*)&addr->inet.ip;
-+ len = sizeof(addr->inet.ip);
-+ } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
-+ ip = (const char*)addr->ipv6.ip.pr_s6_addr;
-+ len = sizeof(addr->ipv6.ip.pr_s6_addr);
- }
-
-- if (response[1] != 0x5A) { // = 90: request granted
-- // connect request not granted
-- LOGERROR(("Connection request refused. Expected: 90; received: %d.", response[1]));
-- return NS_ERROR_FAILURE;
-- }
-+ NS_ABORT_IF_FALSE(ip != NULL, "Unknown address");
-+ NS_ABORT_IF_FALSE(mDataLength + len <= BUFFER_SIZE,
-+ "Can't write that much data!");
-
-- return NS_OK;
-+ memcpy(mData + mDataLength, ip, len);
-+ mDataLength += len;
-+}
-
-+void
-+nsSOCKSSocketInfo::WriteNetPort(const PRNetAddr *addr)
-+{
-+ WriteUint16(PR_NetAddrInetPort(addr));
- }
-
-+void
-+nsSOCKSSocketInfo::WriteString(const nsACString &str)
-+{
-+ NS_ABORT_IF_FALSE(mDataLength + str.Length() <= BUFFER_SIZE,
-+ "Can't write that much data!");
-+ memcpy(mData + mDataLength, str.Data(), str.Length());
-+ mDataLength += str.Length();
-+}
-
--static PRStatus
--nsSOCKSIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime /*timeout*/)
-+inline PRUint8
-+nsSOCKSSocketInfo::ReadUint8()
- {
-+ PRUint8 rv;
-+ NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
-+ "Not enough space to pop a uint8!");
-+ rv = mData[mReadOffset];
-+ mReadOffset += sizeof(rv);
-+ return rv;
-+}
-
-- PRStatus status;
-+inline PRUint16
-+nsSOCKSSocketInfo::ReadUint16()
-+{
-+ PRUint16 rv;
-+ NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
-+ "Not enough space to pop a uint16!");
-+ memcpy(&rv, mData + mReadOffset, sizeof(rv));
-+ mReadOffset += sizeof(rv);
-+ return rv;
-+}
-
-- nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
-- if (info == NULL) return PR_FAILURE;
-+inline PRUint32
-+nsSOCKSSocketInfo::ReadUint32()
-+{
-+ PRUint32 rv;
-+ NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
-+ "Not enough space to pop a uint32!");
-+ memcpy(&rv, mData + mReadOffset, sizeof(rv));
-+ mReadOffset += sizeof(rv);
-+ return rv;
-+}
-
-- // First, we need to look up our proxy...
-- const nsCString &proxyHost = info->ProxyHost();
-+void
-+nsSOCKSSocketInfo::ReadNetAddr(PRNetAddr *addr, PRUint16 fam)
-+{
-+ PRUint32 amt;
-+ const PRUint8 *ip = mData + mReadOffset;
-+
-+ addr->raw.family = fam;
-+ if (fam == PR_AF_INET) {
-+ amt = sizeof(addr->inet.ip);
-+ NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
-+ "Not enough space to pop an ipv4 addr!");
-+ memcpy(&addr->inet.ip, ip, amt);
-+ } else if (fam == PR_AF_INET6) {
-+ amt = sizeof(addr->ipv6.ip.pr_s6_addr);
-+ NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
-+ "Not enough space to pop an ipv6 addr!");
-+ memcpy(addr->ipv6.ip.pr_s6_addr, ip, amt);
-+ }
-
-- if (proxyHost.IsEmpty())
-- return PR_FAILURE;
-+ mReadOffset += amt;
-+}
-
-- PRInt32 socksVersion = info->Version();
-+void
-+nsSOCKSSocketInfo::ReadNetPort(PRNetAddr *addr)
-+{
-+ addr->inet.port = ReadUint16();
-+}
-
-- LOGDEBUG(("nsSOCKSIOLayerConnect SOCKS %u; proxyHost: %s.", socksVersion, proxyHost.get()));
-+void
-+nsSOCKSSocketInfo::WantRead(PRUint32 sz)
-+{
-+ NS_ABORT_IF_FALSE(mDataIoPtr == NULL,
-+ "WantRead() called while I/O already in progress!");
-+ NS_ABORT_IF_FALSE(mDataLength + sz <= BUFFER_SIZE,
-+ "Can't read that much data!");
-+ mAmountToRead = sz;
-+}
-
-- // Sync resolve the proxy hostname.
-- PRNetAddr proxyAddr;
-- nsCOMPtr<nsIDNSRecord> rec;
-- nsresult rv;
-- {
-- nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
-- if (!dns)
-- return PR_FAILURE;
-+PRStatus
-+nsSOCKSSocketInfo::ReadFromSocket(PRFileDesc *fd)
-+{
-+ PRInt32 rc;
-+ const PRUint8 *end;
-
-- rv = dns->Resolve(proxyHost, 0, getter_AddRefs(rec));
-- if (NS_FAILED(rv))
-- return PR_FAILURE;
-+ if (!mAmountToRead) {
-+ LOGDEBUG(("socks: ReadFromSocket(), nothing to do"));
-+ return PR_SUCCESS;
- }
-
-- info->SetInternalProxyAddr(&proxyAddr);
-+ if (!mDataIoPtr) {
-+ mDataIoPtr = mData + mDataLength;
-+ mDataLength += mAmountToRead;
-+ }
-
-- // For now, we'll do this as a blocking connect,
-- // but with nspr 4.1, the necessary functions to
-- // do a non-blocking connect will be available
-+ end = mData + mDataLength;
-+
-+ while (mDataIoPtr < end) {
-+ rc = PR_Read(fd, mDataIoPtr, end - mDataIoPtr);
-+ if (rc <= 0) {
-+ if (rc == 0) {
-+ LOGERROR(("socks: proxy server closed connection"));
-+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
-+ return PR_FAILURE;
-+ } else if (PR_GetError() == PR_WOULD_BLOCK_ERROR) {
-+ LOGDEBUG(("socks: ReadFromSocket(), want read"));
-+ }
-+ break;
-+ }
-
-- // Preserve the non-blocking state of the socket
-- PRBool nonblocking;
-- PRSocketOptionData sockopt;
-- sockopt.option = PR_SockOpt_Nonblocking;
-- status = PR_GetSocketOption(fd, &sockopt);
-+ mDataIoPtr += rc;
-+ }
-
-- if (PR_SUCCESS != status) {
-- LOGERROR(("PR_GetSocketOption() failed. status = %x.", status));
-- return status;
-+ LOGDEBUG(("socks: ReadFromSocket(), have %u bytes total",
-+ unsigned(mDataIoPtr - mData)));
-+ if (mDataIoPtr == end) {
-+ mDataIoPtr = nsnull;
-+ mAmountToRead = 0;
-+ mReadOffset = 0;
-+ return PR_SUCCESS;
- }
-
-- // Store blocking option
-- nonblocking = sockopt.value.non_blocking;
-+ return PR_FAILURE;
-+}
-
-- sockopt.option = PR_SockOpt_Nonblocking;
-- sockopt.value.non_blocking = PR_FALSE;
-- status = PR_SetSocketOption(fd, &sockopt);
-+PRStatus
-+nsSOCKSSocketInfo::WriteToSocket(PRFileDesc *fd)
-+{
-+ PRInt32 rc;
-+ const PRUint8 *end;
-
-- if (PR_SUCCESS != status) {
-- LOGERROR(("PR_SetSocketOption() failed. status = %x.", status));
-- return status;
-+ if (!mDataLength) {
-+ LOGDEBUG(("socks: WriteToSocket(), nothing to do"));
-+ return PR_SUCCESS;
- }
-
-- // Now setup sockopts, so we can restore the value later.
-- sockopt.option = PR_SockOpt_Nonblocking;
-- sockopt.value.non_blocking = nonblocking;
-+ if (!mDataIoPtr)
-+ mDataIoPtr = mData;
-
-- // This connectWait should be long enough to connect to local proxy
-- // servers, but not much longer. Since this protocol negotiation
-- // uses blocking network calls, the app can appear to hang for a maximum
-- // of this time if the user presses the STOP button during the SOCKS
-- // connection negotiation. Note that this value only applies to the
-- // connecting to the SOCKS server: once the SOCKS connection has been
-- // established, the value is not used anywhere else.
-- PRIntervalTime connectWait = PR_SecondsToInterval(10);
-+ end = mData + mDataLength;
-
-- // Connect to the proxy server.
-- PRInt32 addresses = 0;
-- do {
-- rv = rec->GetNextAddr(info->ProxyPort(), &proxyAddr);
-- if (NS_FAILED(rv)) {
-- status = PR_FAILURE;
-+ while (mDataIoPtr < end) {
-+ rc = PR_Write(fd, mDataIoPtr, end - mDataIoPtr);
-+ if (rc < 0) {
-+ if (PR_GetError() == PR_WOULD_BLOCK_ERROR) {
-+ LOGDEBUG(("socks: WriteToSocket(), want write"));
-+ }
- break;
- }
-- ++addresses;
-- status = fd->lower->methods->connect(fd->lower, &proxyAddr, connectWait);
-- } while (PR_SUCCESS != status);
-+
-+ mDataIoPtr += rc;
-+ }
-
-- if (PR_SUCCESS != status) {
-- LOGERROR(("Failed to TCP connect to the proxy server (%s): timeout = %d, status = %x, tried %d addresses.", proxyHost.get(), connectWait, status, addresses));
-- PR_SetSocketOption(fd, &sockopt);
-- return status;
-+ if (mDataIoPtr == end) {
-+ mDataIoPtr = nsnull;
-+ mDataLength = 0;
-+ mReadOffset = 0;
-+ return PR_SUCCESS;
- }
-+
-+ return PR_FAILURE;
-+}
-
-+static PRStatus
-+nsSOCKSIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime to)
-+{
-+ PRStatus status;
-+ PRNetAddr dst;
-
-- // We are now connected to the SOCKS proxy server.
-- // Now we will negotiate a connection to the desired server.
-+ nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
-+ if (info == NULL) return PR_FAILURE;
-
-- // External IP address returned from ConnectSOCKS5(). Not supported in SOCKS4.
-- PRNetAddr extAddr;
-- PR_InitializeNetAddr(PR_IpAddrNull, 0, &extAddr);
-+ if (PR_NetAddrFamily(addr) == PR_AF_INET6 &&
-+ PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
-+ const PRUint8 *srcp;
-
-- NS_ASSERTION((socksVersion == 4) || (socksVersion == 5), "SOCKS Version must be selected");
-+ LOGDEBUG(("socks: converting ipv4-mapped ipv6 address to ipv4"));
-
-- // Try to connect via SOCKS 5.
-- if (socksVersion == 5) {
-- rv = ConnectSOCKS5(fd, addr, &extAddr, connectWait);
-+ // copied from _PR_ConvertToIpv4NetAddr()
-+ PR_InitializeNetAddr(PR_IpAddrAny, 0, &dst);
-+ srcp = addr->ipv6.ip.pr_s6_addr;
-+ memcpy(&dst.inet.ip, srcp + 12, 4);
-+ dst.inet.family = PR_AF_INET;
-+ dst.inet.port = addr->ipv6.port;
-+ } else {
-+ memcpy(&dst, addr, sizeof(dst));
-+ }
-
-- if (NS_FAILED(rv)) {
-- PR_SetSocketOption(fd, &sockopt);
-- return PR_FAILURE;
-- }
-+ info->SetDestinationAddr(&dst);
-+ info->SetConnectTimeout(to);
-
-- }
-+ do {
-+ status = info->DoHandshake(fd, -1);
-+ } while (status == PR_SUCCESS && !info->IsConnected());
-
-- // Try to connect via SOCKS 4.
-- else {
-- rv = ConnectSOCKS4(fd, addr, connectWait);
-+ return status;
-+}
-
-- if (NS_FAILED(rv)) {
-- PR_SetSocketOption(fd, &sockopt);
-- return PR_FAILURE;
-- }
-+static PRStatus
-+nsSOCKSIOLayerConnectContinue(PRFileDesc *fd, PRInt16 oflags)
-+{
-+ PRStatus status;
-
-- }
-+ nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
-+ if (info == NULL) return PR_FAILURE;
-
-+ do {
-+ status = info->DoHandshake(fd, oflags);
-+ } while (status == PR_SUCCESS && !info->IsConnected());
-
-- info->SetDestinationAddr((PRNetAddr*)addr);
-- info->SetExternalProxyAddr(&extAddr);
-+ return status;
-+}
-
-- // restore non-blocking option
-- PR_SetSocketOption(fd, &sockopt);
-+static PRInt16
-+nsSOCKSIOLayerPoll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
-+{
-+ nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
-+ if (info == NULL) return PR_FAILURE;
-
-- // we're set-up and connected.
-- // this socket can be used as normal now.
-+ if (!info->IsConnected()) {
-+ *out_flags = 0;
-+ return info->GetPollFlags();
-+ }
-
-- return PR_SUCCESS;
-+ return fd->lower->methods->poll(fd->lower, in_flags, out_flags);
- }
-
- static PRStatus
-@@ -885,6 +1120,8 @@ nsSOCKSIOLayerAddToSocket(PRInt32 family,
- nsSOCKSIOLayerMethods = *PR_GetDefaultIOMethods();
-
- nsSOCKSIOLayerMethods.connect = nsSOCKSIOLayerConnect;
-+ nsSOCKSIOLayerMethods.connectcontinue = nsSOCKSIOLayerConnectContinue;
-+ nsSOCKSIOLayerMethods.poll = nsSOCKSIOLayerPoll;
- nsSOCKSIOLayerMethods.bind = nsSOCKSIOLayerBind;
- nsSOCKSIOLayerMethods.acceptread = nsSOCKSIOLayerAcceptRead;
- nsSOCKSIOLayerMethods.getsockname = nsSOCKSIOLayerGetName;
---
-1.7.3.4
-
diff --git a/src/current-patches/0001-Firefox5-Block-Components.interfaces-lookupMethod-fr.patch b/src/current-patches/0001-Firefox5-Block-Components.interfaces-lookupMethod-fr.patch
deleted file mode 100644
index 816e2d2..0000000
--- a/src/current-patches/0001-Firefox5-Block-Components.interfaces-lookupMethod-fr.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From cb6df58b95028693007936e423d43223609e17cc Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git(a)fscked.org>
-Date: Mon, 20 Jun 2011 17:07:41 -0700
-Subject: [PATCH 1/3] Firefox5: Block Components.interfaces,lookupMethod from content
-
-This patch removes the ability of content script to access
-Components.interfaces.* as well as call or access Components.lookupMethod.
-
-These two interfaces seem to be exposed to content script only to make our
-lives difficult. Components.lookupMethod can undo our JS hooks, and
-Components.interfaces is useful for fingerprinting the platform, OS, and
-Firebox version.
-
-They appear to have no other legitimate use. See also:
-https://bugzilla.mozilla.org/show_bug.cgi?id=429070
-https://trac.torproject.org/projects/tor/ticket/2873
-https://trac.torproject.org/projects/tor/ticket/2874
----
- js/src/xpconnect/src/xpccomponents.cpp | 8 ++++++--
- 1 files changed, 6 insertions(+), 2 deletions(-)
-
-diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp
-index 5e789e7..5c76981 100644
---- a/js/src/xpconnect/src/xpccomponents.cpp
-+++ b/js/src/xpconnect/src/xpccomponents.cpp
-@@ -4287,7 +4287,9 @@ nsXPCComponents::CanCreateWrapper(const nsIID * iid, char **_retval)
- NS_IMETHODIMP
- nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
- {
-- static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
-+ // XXX: Pref observer? Also, is this what we want? Seems like a plan
-+ //static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
-+ static const char* allowed[] = { "isSuccessCode", nsnull };
- *_retval = xpc_CheckAccessList(methodName, allowed);
- return NS_OK;
- }
-@@ -4296,7 +4298,9 @@ nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, c
- NS_IMETHODIMP
- nsXPCComponents::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
- {
-- static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
-+ // XXX: Pref observer? Also, is this what we want? Seems like a plan
-+ // static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
-+ static const char* allowed[] = { "results", nsnull};
- *_retval = xpc_CheckAccessList(propertyName, allowed);
- return NS_OK;
- }
---
-1.7.3.4
-
diff --git a/src/current-patches/0001-Firefox6-Block-Components.interfaces-lookupMethod-fr.patch b/src/current-patches/0001-Firefox6-Block-Components.interfaces-lookupMethod-fr.patch
new file mode 100644
index 0000000..39a5c99
--- /dev/null
+++ b/src/current-patches/0001-Firefox6-Block-Components.interfaces-lookupMethod-fr.patch
@@ -0,0 +1,50 @@
+From c745f4022a8795e81a690c4a680d46aa407ba6c7 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Mon, 20 Jun 2011 17:07:41 -0700
+Subject: [PATCH 1/3] Firefox6: Block Components.interfaces,lookupMethod from content
+
+This patch removes the ability of content script to access
+Components.interfaces.* as well as call or access Components.lookupMethod.
+
+These two interfaces seem to be exposed to content script only to make our
+lives difficult. Components.lookupMethod can undo our JS hooks, and
+Components.interfaces is useful for fingerprinting the platform, OS, and
+Firebox version.
+
+They appear to have no other legitimate use. See also:
+https://bugzilla.mozilla.org/show_bug.cgi?id=429070
+https://trac.torproject.org/projects/tor/ticket/2873
+https://trac.torproject.org/projects/tor/ticket/2874
+---
+ js/src/xpconnect/src/xpccomponents.cpp | 8 ++++++--
+ 1 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp
+index c1d3e30..48c8b6a 100644
+--- a/js/src/xpconnect/src/xpccomponents.cpp
++++ b/js/src/xpconnect/src/xpccomponents.cpp
+@@ -4231,7 +4231,9 @@ nsXPCComponents::CanCreateWrapper(const nsIID * iid, char **_retval)
+ NS_IMETHODIMP
+ nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
+ {
+- static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
++ // XXX: Pref observer? Also, is this what we want? Seems like a plan
++ //static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
++ static const char* allowed[] = { "isSuccessCode", nsnull };
+ *_retval = xpc_CheckAccessList(methodName, allowed);
+ return NS_OK;
+ }
+@@ -4240,7 +4242,9 @@ nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, c
+ NS_IMETHODIMP
+ nsXPCComponents::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
+ {
+- static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
++ // XXX: Pref observer? Also, is this what we want? Seems like a plan
++ // static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
++ static const char* allowed[] = { "results", nsnull};
+ *_retval = xpc_CheckAccessList(propertyName, allowed);
+ return NS_OK;
+ }
+--
+1.7.3.4
+
diff --git a/src/current-patches/0002-Firefox4-Block-Components.interfaces-lookupMethod-fr.patch b/src/current-patches/0002-Firefox4-Block-Components.interfaces-lookupMethod-fr.patch
deleted file mode 100644
index 8e34500..0000000
--- a/src/current-patches/0002-Firefox4-Block-Components.interfaces-lookupMethod-fr.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From ebaf58a014f98942886ae829da83fadd662df948 Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git(a)fscked.org>
-Date: Mon, 20 Jun 2011 17:07:41 -0700
-Subject: [PATCH 2/4] Firefox4: Block Components.interfaces,lookupMethod from content
-
-This patch removes the ability of content script to access
-Components.interfaces.* as well as call or access Components.lookupMethod.
-
-These two interfaces seem to be exposed to content script only to make our
-lives difficult. Components.lookupMethod can undo our JS hooks, and
-Components.interfaces is useful for fingerprinting the platform, OS, and
-Firebox version.
-
-They appear to have no other legitimate use. See also:
-https://bugzilla.mozilla.org/show_bug.cgi?id=429070
-https://trac.torproject.org/projects/tor/ticket/2873
-https://trac.torproject.org/projects/tor/ticket/2874
----
- js/src/xpconnect/src/xpccomponents.cpp | 8 ++++++--
- 1 files changed, 6 insertions(+), 2 deletions(-)
-
-diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp
-index 1c141f9..85a2b4e 100644
---- a/js/src/xpconnect/src/xpccomponents.cpp
-+++ b/js/src/xpconnect/src/xpccomponents.cpp
-@@ -4294,7 +4294,9 @@ nsXPCComponents::CanCreateWrapper(const nsIID * iid, char **_retval)
- NS_IMETHODIMP
- nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, char **_retval)
- {
-- static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
-+ // XXX: Pref observer? Also, is this what we want? Seems like a plan
-+ //static const char* allowed[] = { "isSuccessCode", "lookupMethod", nsnull };
-+ static const char* allowed[] = { "isSuccessCode", nsnull };
- *_retval = xpc_CheckAccessList(methodName, allowed);
- return NS_OK;
- }
-@@ -4303,7 +4305,9 @@ nsXPCComponents::CanCallMethod(const nsIID * iid, const PRUnichar *methodName, c
- NS_IMETHODIMP
- nsXPCComponents::CanGetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
- {
-- static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
-+ // XXX: Pref observer? Also, is this what we want? Seems like a plan
-+ // static const char* allowed[] = { "interfaces", "interfacesByID", "results", nsnull};
-+ static const char* allowed[] = { "results", nsnull};
- *_retval = xpc_CheckAccessList(propertyName, allowed);
- return NS_OK;
- }
---
-1.7.3.4
-
diff --git a/src/current-patches/0002-Firefox5-Make-Intermediate-Cert-Store-memory-only.patch b/src/current-patches/0002-Firefox5-Make-Intermediate-Cert-Store-memory-only.patch
deleted file mode 100644
index 2bd11e8..0000000
--- a/src/current-patches/0002-Firefox5-Make-Intermediate-Cert-Store-memory-only.patch
+++ /dev/null
@@ -1,300 +0,0 @@
-From 16b89c54032d1ad0acf2d6fa005b292a6f434791 Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git(a)fscked.org>
-Date: Mon, 20 Jun 2011 17:07:49 -0700
-Subject: [PATCH 2/3] Firefox5: Make Intermediate Cert Store memory-only.
-
-This patch makes the intermediate SSL cert store exist in memory only. It
-exposes a pref ('security.nocertdb') to toggle to clear the store, but this
-seems buggy.
-
-The pref must be set before startup in prefs.js.
-https://trac.torproject.org/projects/tor/ticket/2949
----
- security/manager/ssl/src/nsNSSComponent.cpp | 180 ++++++++++++++++++---------
- 1 files changed, 120 insertions(+), 60 deletions(-)
-
-diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp
-index d3ae772..fa37ace 100644
---- a/security/manager/ssl/src/nsNSSComponent.cpp
-+++ b/security/manager/ssl/src/nsNSSComponent.cpp
-@@ -1658,8 +1658,21 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox)
- // Ubuntu 8.04, which loads any nonexistent "<configdir>/libnssckbi.so" as
- // "/usr/lib/nss/libnssckbi.so".
- PRUint32 init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
-- SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "",
-+ PRBool nocertdb = false;
-+ mPrefBranch->GetBoolPref("security.nocertdb", &nocertdb);
-+
-+ // XXX: We can also do the the following to only disable the certdb.
-+ // Leaving this codepath in as a fallback in case InitNODB fails
-+ if (nocertdb)
-+ init_flags |= NSS_INIT_NOCERTDB;
-+
-+ SECStatus init_rv;
-+ if (nocertdb) {
-+ init_rv = ::NSS_NoDB_Init(NULL);
-+ } else {
-+ init_rv = ::NSS_Initialize(profileStr.get(), "", "",
- SECMOD_DB, init_flags);
-+ }
-
- if (init_rv != SECSuccess) {
- PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can not init NSS r/w in %s\n", profileStr.get()));
-@@ -2215,70 +2228,106 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
- }
- }
- }
-- else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
-- nsNSSShutDownPreventionLock locker;
-- PRBool clearSessionCache = PR_FALSE;
-- PRBool enabled;
-+ else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
- NS_ConvertUTF16toUTF8 prefName(someData);
-+ // XXX: This should be an observer notification, so we can properly cancel it
-+ if (prefName.Equals("security.nocertdb")) {
-+ // XXX: If these functions tell us to cancel, the browser seems to get left in an
-+ // indeterminate state that prevents SSL from being used.
-+ //
-+ // We apparently need to wait for all SSL sockets to shut down on their
-+ // own (this can take up to a minute!) and then attempt to alter the pref
-+ // again before doing anything.
-+ //
-+ // So any implementation of New Identity based on this code will need to keep
-+ // attempting to send the notification until it is not canceled. Ugh...
-+ if (!DoProfileApproveChange(aSubject)) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled\n"));
-+ return NS_OK;
-+ }
-
-- if (prefName.Equals("security.enable_ssl2")) {
-- mPrefBranch->GetBoolPref("security.enable_ssl2", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_SSL2, enabled);
-- SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, enabled);
-- clearSessionCache = PR_TRUE;
-- } else if (prefName.Equals("security.enable_ssl3")) {
-- mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
-- clearSessionCache = PR_TRUE;
-- } else if (prefName.Equals("security.enable_tls")) {
-- mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
-- clearSessionCache = PR_TRUE;
-- } else if (prefName.Equals("security.enable_tls_session_tickets")) {
-- mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
-- } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
-- mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
-- SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
-- } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
-- mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
-- enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
-- } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
-- char *unrestricted_hosts=nsnull;
-- mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
-- if (unrestricted_hosts) {
-- nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
-- nsMemory::Free(unrestricted_hosts);
-+ DoProfileChangeNetTeardown();
-+ if (!DoProfileChangeTeardown(aSubject)) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled\n"));
-+ return NS_OK;
-+ }
-+
-+ if (!DoProfileBeforeChange(aSubject)) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled by NSS shutdown\n"));
-+ // Need to re-add observer because ShutdownNSS removed it.
-+ nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(mPrefBranch);
-+ pbi->AddObserver("security.", this, PR_FALSE);
-+ return NS_OK;
- }
-- } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
-- mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
-- nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
-- } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
-- PRInt32 warnLevel = 1;
-- mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
-- nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
-+
-+ DoProfileChangeNetRestore();
-+ InitializeNSS(PR_FALSE);
-+ InitializeCRLUpdateTimer();
-+ return NS_OK;
-+ } else {
-+ nsNSSShutDownPreventionLock locker;
-+ PRBool clearSessionCache = PR_FALSE;
-+ PRBool enabled;
-+
-+ if (prefName.Equals("security.enable_ssl2")) {
-+ mPrefBranch->GetBoolPref("security.enable_ssl2", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_SSL2, enabled);
-+ SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, enabled);
-+ clearSessionCache = PR_TRUE;
-+ } else if (prefName.Equals("security.enable_ssl3")) {
-+ mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
-+ clearSessionCache = PR_TRUE;
-+ } else if (prefName.Equals("security.enable_tls")) {
-+ mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
-+ clearSessionCache = PR_TRUE;
-+ } else if (prefName.Equals("security.enable_tls_session_tickets")) {
-+ mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
-+ } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
-+ mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
-+ SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
-+ } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
-+ mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
-+ enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
-+ } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
-+ char *unrestricted_hosts=nsnull;
-+ mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
-+ if (unrestricted_hosts) {
-+ nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
-+ nsMemory::Free(unrestricted_hosts);
-+ }
-+ } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
-+ mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
-+ nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
-+ } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
-+ PRInt32 warnLevel = 1;
-+ mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
-+ nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
- #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
-- } else if (prefName.Equals("security.ssl.enable_false_start")) {
-- mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
-+ } else if (prefName.Equals("security.ssl.enable_false_start")) {
-+ mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
- #endif
-- } else if (prefName.Equals("security.OCSP.enabled")
-- || prefName.Equals("security.OCSP.require")) {
-- setOCSPOptions(mPrefBranch);
-- } else {
-- /* Look through the cipher table and set according to pref setting */
-- for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
-- if (prefName.Equals(cp->pref)) {
-- mPrefBranch->GetBoolPref(cp->pref, &enabled);
-- SSL_CipherPrefSetDefault(cp->id, enabled);
-- clearSessionCache = PR_TRUE;
-- break;
-+ } else if (prefName.Equals("security.OCSP.enabled")
-+ || prefName.Equals("security.OCSP.require")) {
-+ setOCSPOptions(mPrefBranch);
-+ } else {
-+ /* Look through the cipher table and set according to pref setting */
-+ for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
-+ if (prefName.Equals(cp->pref)) {
-+ mPrefBranch->GetBoolPref(cp->pref, &enabled);
-+ SSL_CipherPrefSetDefault(cp->id, enabled);
-+ clearSessionCache = PR_TRUE;
-+ break;
-+ }
- }
- }
-+ if (clearSessionCache)
-+ SSL_ClearSessionCache();
- }
-- if (clearSessionCache)
-- SSL_ClearSessionCache();
- }
- else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
- PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
-@@ -2447,16 +2496,19 @@ nsNSSComponent::RememberCert(CERTCertificate *cert)
- return NS_OK;
- }
-
--void
-+PRBool
- nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
- {
- if (mShutdownObjectList->isUIActive()) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS UI active in profile change!\n"));
- ShowAlert(ai_crypto_ui_active);
- nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
- if (status) {
- status->VetoChange();
- }
-+ return false;
- }
-+ return true;
- }
-
- void
-@@ -2469,16 +2521,18 @@ nsNSSComponent::DoProfileChangeNetTeardown()
- mIsNetworkDown = PR_TRUE;
- }
-
--void
-+PRBool
- nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
- {
- PRBool callVeto = PR_FALSE;
-
- if (!mShutdownObjectList->ifPossibleDisallowUI()) {
- callVeto = PR_TRUE;
-+ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: Not possible to disallow UI!\n"));
- ShowAlert(ai_crypto_ui_active);
- }
- else if (mShutdownObjectList->areSSLSocketsActive()) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: SSL Sockets are active!\n"));
- callVeto = PR_TRUE;
- ShowAlert(ai_sockets_still_active);
- }
-@@ -2489,9 +2543,11 @@ nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
- status->VetoChange();
- }
- }
-+
-+ return !callVeto;
- }
-
--void
-+PRBool
- nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
- {
- NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
-@@ -2510,16 +2566,20 @@ nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
- }
-
- StopCRLUpdateTimer();
-+ PRBool allow_change = PR_TRUE;
-
- if (needsCleanup) {
- if (NS_FAILED(ShutdownNSS())) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: Shutdown failed\n"));
- nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
- if (status) {
- status->ChangeFailed();
- }
-+ allow_change = PR_FALSE;
- }
- }
- mShutdownObjectList->allowUI();
-+ return allow_change;
- }
-
- void
---- a/security/manager/ssl/src/nsNSSComponent.h
-+++ b/security/manager/ssl/src/nsNSSComponent.h
-@@ -321,10 +321,10 @@
-
- // Methods that we use to handle the profile change notifications (and to
- // synthesize a full profile change when we're just doing a profile startup):
-- void DoProfileApproveChange(nsISupports* aSubject);
-+ PRBool DoProfileApproveChange(nsISupports* aSubject);
- void DoProfileChangeNetTeardown();
-- void DoProfileChangeTeardown(nsISupports* aSubject);
-- void DoProfileBeforeChange(nsISupports* aSubject);
-+ PRBool DoProfileChangeTeardown(nsISupports* aSubject);
-+ PRBool DoProfileBeforeChange(nsISupports* aSubject);
- void DoProfileChangeNetRestore();
-
- Mutex mutex;
-
---
-1.7.3.4
-
diff --git a/src/current-patches/0002-Firefox6-Make-Permissions-Manager-memory-only.patch b/src/current-patches/0002-Firefox6-Make-Permissions-Manager-memory-only.patch
new file mode 100644
index 0000000..35262e6
--- /dev/null
+++ b/src/current-patches/0002-Firefox6-Make-Permissions-Manager-memory-only.patch
@@ -0,0 +1,94 @@
+From 1eb6ddb69b9fa4b82a555398d2c47b8ef1166ae2 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Mon, 20 Jun 2011 17:07:56 -0700
+Subject: [PATCH 2/3] Firefox6: Make Permissions Manager memory-only
+
+This patch exposes a pref 'permissions.memory_only' that properly isolates the
+permissions manager to memory, which is responsible for all user specified
+site permissions, as well as stored STS policy.
+
+The pref does successfully clear the permissions manager memory if toggled. It
+does not need to be set in prefs.js, and can be handled by Torbutton.
+
+https://trac.torproject.org/projects/tor/ticket/2950
+---
+ extensions/cookie/nsPermissionManager.cpp | 34 ++++++++++++++++++++++++++--
+ 1 files changed, 31 insertions(+), 3 deletions(-)
+
+diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp
+index 773a973..5387397 100644
+--- a/extensions/cookie/nsPermissionManager.cpp
++++ b/extensions/cookie/nsPermissionManager.cpp
+@@ -58,6 +58,10 @@
+ #include "mozStorageHelper.h"
+ #include "mozStorageCID.h"
+ #include "nsXULAppAPI.h"
++#include "nsCOMPtr.h"
++#include "nsIPrefService.h"
++#include "nsIPrefBranch.h"
++#include "nsIPrefBranch2.h"
+
+ static nsPermissionManager *gPermissionManager = nsnull;
+
+@@ -227,6 +231,11 @@ nsPermissionManager::Init()
+ mObserverService->AddObserver(this, "profile-do-change", PR_TRUE);
+ }
+
++ nsCOMPtr<nsIPrefBranch2> pbi = do_GetService(NS_PREFSERVICE_CONTRACTID);
++ if (pbi) {
++ pbi->AddObserver("permissions.", this, PR_FALSE);
++ }
++
+ if (IsChildProcess()) {
+ // Get the permissions from the parent process
+ InfallibleTArray<IPC::Permission> perms;
+@@ -275,8 +284,18 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
+ if (!storage)
+ return NS_ERROR_UNEXPECTED;
+
++ PRBool memory_db = false;
++ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
++ if (prefs) {
++ prefs->GetBoolPref("permissions.memory_only", &memory_db);
++ }
++
+ // cache a connection to the hosts database
+- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ if (memory_db) {
++ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
++ } else {
++ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRBool ready;
+@@ -286,7 +305,11 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
+ rv = permissionsFile->Remove(PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ if (memory_db) {
++ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
++ } else {
++ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
++ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mDBConn->GetConnectionReady(&ready);
+@@ -805,7 +828,12 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
+ {
+ ENSURE_NOT_CHILD_PROCESS;
+
+- if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
++ if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
++ if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("permissions.memory_only").get())) {
++ // XXX: Should we remove the file? Probably not..
++ InitDB(PR_FALSE);
++ }
++ } else if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
+ // The profile is about to change,
+ // or is going away because the application is shutting down.
+ if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
+--
+1.7.3.4
+
diff --git a/src/current-patches/0003-Firefox4-Make-Intermediate-Cert-Store-memory-only.patch b/src/current-patches/0003-Firefox4-Make-Intermediate-Cert-Store-memory-only.patch
deleted file mode 100644
index d4f7b73..0000000
--- a/src/current-patches/0003-Firefox4-Make-Intermediate-Cert-Store-memory-only.patch
+++ /dev/null
@@ -1,283 +0,0 @@
-From 4db14cbb5a0aff6102189d30b9202555dcc39ff4 Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git(a)fscked.org>
-Date: Mon, 20 Jun 2011 17:07:49 -0700
-Subject: [PATCH 3/4] Firefox4: Make Intermediate Cert Store memory-only.
-
-This patch makes the intermediate SSL cert store exist in memory only. It
-exposes a pref ('security.nocertdb') to toggle to clear the store, but this
-seems buggy.
-
-The pref must be set before startup in prefs.js.
-https://trac.torproject.org/projects/tor/ticket/2949
----
- security/manager/ssl/src/nsNSSComponent.cpp | 180 ++++++++++++++++++---------
- 1 files changed, 120 insertions(+), 60 deletions(-)
-
-diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp
-index 33377ac..716bcee 100644
---- a/security/manager/ssl/src/nsNSSComponent.cpp
-+++ b/security/manager/ssl/src/nsNSSComponent.cpp
-@@ -1674,8 +1674,21 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox)
- // Ubuntu 8.04, which loads any nonexistent "<configdir>/libnssckbi.so" as
- // "/usr/lib/nss/libnssckbi.so".
- PRUint32 init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
-- SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "",
-+ PRBool nocertdb = false;
-+ mPrefBranch->GetBoolPref("security.nocertdb", &nocertdb);
-+
-+ // XXX: We can also do the the following to only disable the certdb.
-+ // Leaving this codepath in as a fallback in case InitNODB fails
-+ if (nocertdb)
-+ init_flags |= NSS_INIT_NOCERTDB;
-+
-+ SECStatus init_rv;
-+ if (nocertdb) {
-+ init_rv = ::NSS_NoDB_Init(NULL);
-+ } else {
-+ init_rv = ::NSS_Initialize(profileStr.get(), "", "",
- SECMOD_DB, init_flags);
-+ }
-
- if (init_rv != SECSuccess) {
- PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("can not init NSS r/w in %s\n", profileStr.get()));
-@@ -2231,70 +2244,106 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic,
- }
- }
- }
-- else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
-- nsNSSShutDownPreventionLock locker;
-- PRBool clearSessionCache = PR_FALSE;
-- PRBool enabled;
-+ else if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
- NS_ConvertUTF16toUTF8 prefName(someData);
-+ // XXX: This should be an observer notification, so we can properly cancel it
-+ if (prefName.Equals("security.nocertdb")) {
-+ // XXX: If these functions tell us to cancel, the browser seems to get left in an
-+ // indeterminate state that prevents SSL from being used.
-+ //
-+ // We apparently need to wait for all SSL sockets to shut down on their
-+ // own (this can take up to a minute!) and then attempt to alter the pref
-+ // again before doing anything.
-+ //
-+ // So any implementation of New Identity based on this code will need to keep
-+ // attempting to send the notification until it is not canceled. Ugh...
-+ if (!DoProfileApproveChange(aSubject)) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled\n"));
-+ return NS_OK;
-+ }
-
-- if (prefName.Equals("security.enable_ssl2")) {
-- mPrefBranch->GetBoolPref("security.enable_ssl2", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_SSL2, enabled);
-- SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, enabled);
-- clearSessionCache = PR_TRUE;
-- } else if (prefName.Equals("security.enable_ssl3")) {
-- mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
-- clearSessionCache = PR_TRUE;
-- } else if (prefName.Equals("security.enable_tls")) {
-- mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
-- clearSessionCache = PR_TRUE;
-- } else if (prefName.Equals("security.enable_tls_session_tickets")) {
-- mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
-- } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
-- mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
-- SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
-- } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
-- mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
-- enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
-- } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
-- char *unrestricted_hosts=nsnull;
-- mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
-- if (unrestricted_hosts) {
-- nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
-- nsMemory::Free(unrestricted_hosts);
-+ DoProfileChangeNetTeardown();
-+ if (!DoProfileChangeTeardown(aSubject)) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled\n"));
-+ return NS_OK;
-+ }
-+
-+ if (!DoProfileBeforeChange(aSubject)) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDB change canceled by NSS shutdown\n"));
-+ // Need to re-add observer because ShutdownNSS removed it.
-+ nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(mPrefBranch);
-+ pbi->AddObserver("security.", this, PR_FALSE);
-+ return NS_OK;
- }
-- } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
-- mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
-- nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
-- } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
-- PRInt32 warnLevel = 1;
-- mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
-- nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
-+
-+ DoProfileChangeNetRestore();
-+ InitializeNSS(PR_FALSE);
-+ InitializeCRLUpdateTimer();
-+ return NS_OK;
-+ } else {
-+ nsNSSShutDownPreventionLock locker;
-+ PRBool clearSessionCache = PR_FALSE;
-+ PRBool enabled;
-+
-+ if (prefName.Equals("security.enable_ssl2")) {
-+ mPrefBranch->GetBoolPref("security.enable_ssl2", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_SSL2, enabled);
-+ SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, enabled);
-+ clearSessionCache = PR_TRUE;
-+ } else if (prefName.Equals("security.enable_ssl3")) {
-+ mPrefBranch->GetBoolPref("security.enable_ssl3", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled);
-+ clearSessionCache = PR_TRUE;
-+ } else if (prefName.Equals("security.enable_tls")) {
-+ mPrefBranch->GetBoolPref("security.enable_tls", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled);
-+ clearSessionCache = PR_TRUE;
-+ } else if (prefName.Equals("security.enable_tls_session_tickets")) {
-+ mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled);
-+ } else if (prefName.Equals("security.ssl.require_safe_negotiation")) {
-+ mPrefBranch->GetBoolPref("security.ssl.require_safe_negotiation", &enabled);
-+ SSL_OptionSetDefault(SSL_REQUIRE_SAFE_NEGOTIATION, enabled);
-+ } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
-+ mPrefBranch->GetBoolPref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
-+ enabled ? SSL_RENEGOTIATE_UNRESTRICTED : SSL_RENEGOTIATE_REQUIRES_XTN);
-+ } else if (prefName.Equals("security.ssl.renego_unrestricted_hosts")) {
-+ char *unrestricted_hosts=nsnull;
-+ mPrefBranch->GetCharPref("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
-+ if (unrestricted_hosts) {
-+ nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(nsDependentCString(unrestricted_hosts));
-+ nsMemory::Free(unrestricted_hosts);
-+ }
-+ } else if (prefName.Equals("security.ssl.treat_unsafe_negotiation_as_broken")) {
-+ mPrefBranch->GetBoolPref("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
-+ nsSSLIOLayerHelpers::setTreatUnsafeNegotiationAsBroken(enabled);
-+ } else if (prefName.Equals("security.ssl.warn_missing_rfc5746")) {
-+ PRInt32 warnLevel = 1;
-+ mPrefBranch->GetIntPref("security.ssl.warn_missing_rfc5746", &warnLevel);
-+ nsSSLIOLayerHelpers::setWarnLevelMissingRFC5746(warnLevel);
- #ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
-- } else if (prefName.Equals("security.ssl.enable_false_start")) {
-- mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
-- SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
-+ } else if (prefName.Equals("security.ssl.enable_false_start")) {
-+ mPrefBranch->GetBoolPref("security.ssl.enable_false_start", &enabled);
-+ SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, enabled);
- #endif
-- } else if (prefName.Equals("security.OCSP.enabled")
-- || prefName.Equals("security.OCSP.require")) {
-- setOCSPOptions(mPrefBranch);
-- } else {
-- /* Look through the cipher table and set according to pref setting */
-- for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
-- if (prefName.Equals(cp->pref)) {
-- mPrefBranch->GetBoolPref(cp->pref, &enabled);
-- SSL_CipherPrefSetDefault(cp->id, enabled);
-- clearSessionCache = PR_TRUE;
-- break;
-+ } else if (prefName.Equals("security.OCSP.enabled")
-+ || prefName.Equals("security.OCSP.require")) {
-+ setOCSPOptions(mPrefBranch);
-+ } else {
-+ /* Look through the cipher table and set according to pref setting */
-+ for (CipherPref* cp = CipherPrefs; cp->pref; ++cp) {
-+ if (prefName.Equals(cp->pref)) {
-+ mPrefBranch->GetBoolPref(cp->pref, &enabled);
-+ SSL_CipherPrefSetDefault(cp->id, enabled);
-+ clearSessionCache = PR_TRUE;
-+ break;
-+ }
- }
- }
-+ if (clearSessionCache)
-+ SSL_ClearSessionCache();
- }
-- if (clearSessionCache)
-- SSL_ClearSessionCache();
- }
- else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_NET_TEARDOWN_TOPIC) == 0) {
- PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("receiving network teardown topic\n"));
-@@ -2463,16 +2512,19 @@ nsNSSComponent::RememberCert(CERTCertificate *cert)
- return NS_OK;
- }
-
--void
-+PRBool
- nsNSSComponent::DoProfileApproveChange(nsISupports* aSubject)
- {
- if (mShutdownObjectList->isUIActive()) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS UI active in profile change!\n"));
- ShowAlert(ai_crypto_ui_active);
- nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
- if (status) {
- status->VetoChange();
- }
-+ return false;
- }
-+ return true;
- }
-
- void
-@@ -2485,16 +2537,18 @@ nsNSSComponent::DoProfileChangeNetTeardown()
- mIsNetworkDown = PR_TRUE;
- }
-
--void
-+PRBool
- nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
- {
- PRBool callVeto = PR_FALSE;
-
- if (!mShutdownObjectList->ifPossibleDisallowUI()) {
- callVeto = PR_TRUE;
-+ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: Not possible to disallow UI!\n"));
- ShowAlert(ai_crypto_ui_active);
- }
- else if (mShutdownObjectList->areSSLSocketsActive()) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: SSL Sockets are active!\n"));
- callVeto = PR_TRUE;
- ShowAlert(ai_sockets_still_active);
- }
-@@ -2505,9 +2559,11 @@ nsNSSComponent::DoProfileChangeTeardown(nsISupports* aSubject)
- status->VetoChange();
- }
- }
-+
-+ return !callVeto;
- }
-
--void
-+PRBool
- nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
- {
- NS_ASSERTION(mIsNetworkDown, "nsNSSComponent relies on profile manager to wait for synchronous shutdown of all network activity");
-@@ -2526,16 +2582,20 @@ nsNSSComponent::DoProfileBeforeChange(nsISupports* aSubject)
- }
-
- StopCRLUpdateTimer();
-+ PRBool allow_change = PR_TRUE;
-
- if (needsCleanup) {
- if (NS_FAILED(ShutdownNSS())) {
-+ PR_LOG(gPIPNSSLog, PR_LOG_WARN, ("NSS: Shutdown failed\n"));
- nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
- if (status) {
- status->ChangeFailed();
- }
-+ allow_change = PR_FALSE;
- }
- }
- mShutdownObjectList->allowUI();
-+ return allow_change;
- }
-
- void
---
-1.7.3.4
-
diff --git a/src/current-patches/0003-Firefox5-Make-Permissions-Manager-memory-only.patch b/src/current-patches/0003-Firefox5-Make-Permissions-Manager-memory-only.patch
deleted file mode 100644
index 1384245..0000000
--- a/src/current-patches/0003-Firefox5-Make-Permissions-Manager-memory-only.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From 16bafbf39c89cce901af6500255822677bc4c36d Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git(a)fscked.org>
-Date: Mon, 20 Jun 2011 17:07:56 -0700
-Subject: [PATCH 3/3] Firefox5: Make Permissions Manager memory-only
-
-This patch exposes a pref 'permissions.memory_only' that properly isolates the
-permissions manager to memory, which is responsible for all user specified
-site permissions, as well as stored STS policy.
-
-The pref does successfully clear the permissions manager memory if toggled. It
-does not need to be set in prefs.js, and can be handled by Torbutton.
-
-https://trac.torproject.org/projects/tor/ticket/2950
----
- extensions/cookie/nsPermissionManager.cpp | 34 ++++++++++++++++++++++++++--
- 1 files changed, 31 insertions(+), 3 deletions(-)
-
-diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp
-index 773a973..5387397 100644
---- a/extensions/cookie/nsPermissionManager.cpp
-+++ b/extensions/cookie/nsPermissionManager.cpp
-@@ -58,6 +58,10 @@
- #include "mozStorageHelper.h"
- #include "mozStorageCID.h"
- #include "nsXULAppAPI.h"
-+#include "nsCOMPtr.h"
-+#include "nsIPrefService.h"
-+#include "nsIPrefBranch.h"
-+#include "nsIPrefBranch2.h"
-
- static nsPermissionManager *gPermissionManager = nsnull;
-
-@@ -227,6 +231,11 @@ nsPermissionManager::Init()
- mObserverService->AddObserver(this, "profile-do-change", PR_TRUE);
- }
-
-+ nsCOMPtr<nsIPrefBranch2> pbi = do_GetService(NS_PREFSERVICE_CONTRACTID);
-+ if (pbi) {
-+ pbi->AddObserver("permissions.", this, PR_FALSE);
-+ }
-+
- if (IsChildProcess()) {
- // Get the permissions from the parent process
- InfallibleTArray<IPC::Permission> perms;
-@@ -275,8 +284,18 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
- if (!storage)
- return NS_ERROR_UNEXPECTED;
-
-+ PRBool memory_db = false;
-+ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
-+ if (prefs) {
-+ prefs->GetBoolPref("permissions.memory_only", &memory_db);
-+ }
-+
- // cache a connection to the hosts database
-- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
-+ if (memory_db) {
-+ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
-+ } else {
-+ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
-+ }
- NS_ENSURE_SUCCESS(rv, rv);
-
- PRBool ready;
-@@ -286,7 +305,11 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
- rv = permissionsFile->Remove(PR_FALSE);
- NS_ENSURE_SUCCESS(rv, rv);
-
-- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
-+ if (memory_db) {
-+ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
-+ } else {
-+ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
-+ }
- NS_ENSURE_SUCCESS(rv, rv);
-
- mDBConn->GetConnectionReady(&ready);
-@@ -805,7 +828,12 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
- {
- ENSURE_NOT_CHILD_PROCESS;
-
-- if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
-+ if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
-+ if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("permissions.memory_only").get())) {
-+ // XXX: Should we remove the file? Probably not..
-+ InitDB(PR_FALSE);
-+ }
-+ } else if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
- // The profile is about to change,
- // or is going away because the application is shutting down.
- if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
---
-1.7.3.4
-
diff --git a/src/current-patches/0003-Firefox6-Make-Intermediate-Cert-Store-memory-only.patch b/src/current-patches/0003-Firefox6-Make-Intermediate-Cert-Store-memory-only.patch
new file mode 100644
index 0000000..9c568a0
--- /dev/null
+++ b/src/current-patches/0003-Firefox6-Make-Intermediate-Cert-Store-memory-only.patch
@@ -0,0 +1,43 @@
+From 2bdee82990bbda960d23d6122bf89d422bb63211 Mon Sep 17 00:00:00 2001
+From: Mike Perry <mikeperry-git(a)fscked.org>
+Date: Fri, 19 Aug 2011 17:58:23 -0700
+Subject: [PATCH 3/3] Firefox6: Make Intermediate Cert Store memory-only.
+
+This patch makes the intermediate SSL cert store exist in memory only.
+
+The pref must be set before startup in prefs.js.
+https://trac.torproject.org/projects/tor/ticket/2949
+---
+ security/manager/ssl/src/nsNSSComponent.cpp | 16 ++++++++++++++++
+ 1 files changed, 16 insertions(+), 0 deletions(-)
+
+diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp
+index 7a8569b..5261c5e 100644
+--- a/security/manager/ssl/src/nsNSSComponent.cpp
++++ b/security/manager/ssl/src/nsNSSComponent.cpp
+@@ -1729,6 +1729,22 @@ nsNSSComponent::InitializeNSS(PRBool showWarningBox)
+ // Ubuntu 8.04, which loads any nonexistent "<configdir>/libnssckbi.so" as
+ // "/usr/lib/nss/libnssckbi.so".
+ PRUint32 init_flags = NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE;
++ PRBool nocertdb = false;
++ mPrefBranch->GetBoolPref("security.nocertdb", &nocertdb);
++
++ // XXX: We can also do the the following to only disable the certdb.
++ // Leaving this codepath in as a fallback in case InitNODB fails
++ if (nocertdb)
++ init_flags |= NSS_INIT_NOCERTDB;
++
++ SECStatus init_rv;
++ if (nocertdb) {
++ init_rv = ::NSS_NoDB_Init(NULL);
++ } else {
++ init_rv = ::NSS_Initialize(profileStr.get(), "", "",
++ SECMOD_DB, init_flags);
++ }
++
+ SECStatus init_rv = ::NSS_Initialize(profileStr.get(), "", "",
+ SECMOD_DB, init_flags);
+
+--
+1.7.3.4
+
diff --git a/src/current-patches/0004-Firefox4-Make-Permissions-Manager-memory-only.patch b/src/current-patches/0004-Firefox4-Make-Permissions-Manager-memory-only.patch
deleted file mode 100644
index 8f7ddd9..0000000
--- a/src/current-patches/0004-Firefox4-Make-Permissions-Manager-memory-only.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From 6f37edd80181906c37ace589fc26eabf6731b09d Mon Sep 17 00:00:00 2001
-From: Mike Perry <mikeperry-git(a)fscked.org>
-Date: Mon, 20 Jun 2011 17:07:56 -0700
-Subject: [PATCH 4/4] Firefox4: Make Permissions Manager memory-only
-
-This patch exposes a pref 'permissions.memory_only' that properly isolates the
-permissions manager to memory, which is responsible for all user specified
-site permissions, as well as stored STS policy.
-
-The pref does successfully clear the permissions manager memory if toggled. It
-does not need to be set in prefs.js, and can be handled by Torbutton.
-
-https://trac.torproject.org/projects/tor/ticket/2950
----
- extensions/cookie/nsPermissionManager.cpp | 34 ++++++++++++++++++++++++++--
- 1 files changed, 31 insertions(+), 3 deletions(-)
-
-diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp
-index d182013..0a1aea6 100644
---- a/extensions/cookie/nsPermissionManager.cpp
-+++ b/extensions/cookie/nsPermissionManager.cpp
-@@ -60,6 +60,10 @@
- #include "mozStorageHelper.h"
- #include "mozStorageCID.h"
- #include "nsXULAppAPI.h"
-+#include "nsCOMPtr.h"
-+#include "nsIPrefService.h"
-+#include "nsIPrefBranch.h"
-+#include "nsIPrefBranch2.h"
-
- static nsPermissionManager *gPermissionManager = nsnull;
-
-@@ -233,6 +237,11 @@ nsPermissionManager::Init()
- mObserverService->AddObserver(this, "profile-do-change", PR_TRUE);
- }
-
-+ nsCOMPtr<nsIPrefBranch2> pbi = do_GetService(NS_PREFSERVICE_CONTRACTID);
-+ if (pbi) {
-+ pbi->AddObserver("permissions.", this, PR_FALSE);
-+ }
-+
- #ifdef MOZ_IPC
- if (IsChildProcess()) {
- // Get the permissions from the parent process
-@@ -283,8 +292,18 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
- if (!storage)
- return NS_ERROR_UNEXPECTED;
-
-+ PRBool memory_db = false;
-+ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
-+ if (prefs) {
-+ prefs->GetBoolPref("permissions.memory_only", &memory_db);
-+ }
-+
- // cache a connection to the hosts database
-- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
-+ if (memory_db) {
-+ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
-+ } else {
-+ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
-+ }
- NS_ENSURE_SUCCESS(rv, rv);
-
- PRBool ready;
-@@ -294,7 +313,11 @@ nsPermissionManager::InitDB(PRBool aRemoveFile)
- rv = permissionsFile->Remove(PR_FALSE);
- NS_ENSURE_SUCCESS(rv, rv);
-
-- rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
-+ if (memory_db) {
-+ rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(mDBConn));
-+ } else {
-+ rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
-+ }
- NS_ENSURE_SUCCESS(rv, rv);
-
- mDBConn->GetConnectionReady(&ready);
-@@ -825,7 +848,12 @@ NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aT
- ENSURE_NOT_CHILD_PROCESS;
- #endif
-
-- if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
-+ if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
-+ if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("permissions.memory_only").get())) {
-+ // XXX: Should we remove the file? Probably not..
-+ InitDB(PR_FALSE);
-+ }
-+ } else if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
- // The profile is about to change,
- // or is going away because the application is shutting down.
- if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
---
-1.7.3.4
-
[View Less]
1
0
commit 8a14db8ef9880456808904b6b3a6c098606ab321
Author: Jacob Appelbaum <jacob(a)appelbaum.net>
Date: Fri Aug 19 23:04:44 2011 +0200
add package apt to have apt-get
---
freedom-maker/fbx-base.conf | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/freedom-maker/fbx-base.conf b/freedom-maker/fbx-base.conf
index 0096f1a..3412768 100644
--- a/freedom-maker/fbx-base.conf
+++ b/freedom-maker/fbx-base.conf
@@ -6,7 +6,7 @@ aptsources=Debian
debootstrap=Debian
[…
[View More]Debian]
-packages=base-files netbase openssh-server zile wget iproute net-tools hostname module-init-tools wget resolvconf udev isc-dhcp-client ifupdown rsyslog libertas-firmware
+packages=base-files netbase openssh-server zile wget iproute net-tools hostname module-init-tools wget resolvconf udev isc-dhcp-client ifupdown rsyslog libertas-firmware apt
source=http://ftp.ba.debian.org/debian
keyring=debian-archive-keyring
suite=squeeze
[View Less]
1
0

[tor/master] Disable run-time changes to DisableIOCP: They do not work
by nickm@torproject.org 19 Aug '11
by nickm@torproject.org 19 Aug '11
19 Aug '11
commit dd6a9a923d8bda5363c50d5ea7fd8ea403e895cd
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Aug 19 17:07:54 2011 -0400
Disable run-time changes to DisableIOCP: They do not work
---
src/or/config.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/src/or/config.c b/src/or/config.c
index 716d83a..dbc355d 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -3966,6 +3966,12 @@ options_transition_allowed(const or_options_t *old,
return -…
[View More]1;
}
+ if (old->DisableIOCP != new_val->DisableIOCP) {
+ *msg = tor_strdup("While Tor is running, changing DisableIOCP "
+ "is not allowed.");
+ return -1;
+ }
+
return 0;
}
[View Less]
1
0
commit 37668610f78ac5b29ae399fac24ba70e2a2a643c
Author: aagbsn <aagbsn(a)extc.org>
Date: Mon Aug 15 13:42:14 2011 -0700
fix regarding #3701
https://trac.torproject.org/projects/tor/ticket/3701
bwauthority.py will no longer exit if the child dies
with SIGTERM
also modified run_scan.sh to kill -9
---
NetworkScanners/BwAuthority/bwauthority.py | 12 ++++++++++--
NetworkScanners/BwAuthority/run_scan.sh | 2 +-
2 files changed, 11 insertions(+), 3 …
[View More]deletions(-)
diff --git a/NetworkScanners/BwAuthority/bwauthority.py b/NetworkScanners/BwAuthority/bwauthority.py
index 9125044..3e626db 100755
--- a/NetworkScanners/BwAuthority/bwauthority.py
+++ b/NetworkScanners/BwAuthority/bwauthority.py
@@ -28,8 +28,16 @@ def main(argv):
plog('WARN', 'Child process recieved SIGKILL, exiting')
exit()
elif (abs(p.returncode) == SIGTERM):
- plog('WARN', 'Child process recieved SIGTERM, exiting')
- exit()
+ #XXX
+ # see: https://trac.torproject.org/projects/tor/ticket/3701
+ # if uncaught exceptions are raised in user-written handlers, TorCtl
+ # will kill the bwauthority_child process using os.kill() because sys.exit()
+ # only exits the thread in which the exception is caught.
+ # quote mikeperry: "we want this thing not do die. that is priority one"
+ # therefore: we restart the child process and hope for the best :-)
+ plog('WARN', 'Child process recieved SIGTERM')
+ #exit()
+
else:
plog('WARN', 'Child process returned %s' % p.returncode)
diff --git a/NetworkScanners/BwAuthority/run_scan.sh b/NetworkScanners/BwAuthority/run_scan.sh
index 77a7a9a..b3e1355 100755
--- a/NetworkScanners/BwAuthority/run_scan.sh
+++ b/NetworkScanners/BwAuthority/run_scan.sh
@@ -12,7 +12,7 @@ for n in `seq $SCANNER_COUNT`; do
PIDFILE=./data/scanner.${n}/bwauthority.pid
if [ -f $PIDFILE ]; then
echo "Killing off scanner $n."
- kill `head -1 $PIDFILE` && rm $PIDFILE
+ kill -9 `head -1 $PIDFILE` && rm $PIDFILE
fi
done
[View Less]
1
0

[torouter/master] we want to fork the freedom-maker script for the torouter
by runa@torproject.org 19 Aug '11
by runa@torproject.org 19 Aug '11
19 Aug '11
commit b1b7684e861effe1db69a9bcd253ccad21c49fb2
Author: Runa A. Sandvik <runa.sandvik(a)gmail.com>
Date: Fri Aug 19 20:31:46 2011 +0100
we want to fork the freedom-maker script for the torouter
---
freedom-maker/.gitignore | 1 +
freedom-maker/COPYING | 674 +++++++++++++++++++++++++++++++++++++
freedom-maker/Makefile | 17 +
freedom-maker/README | 38 ++
freedom-maker/TODO | 13 +
freedom-maker/bin/copy2dream.…
[View More]sh | 30 ++
freedom-maker/fbx-armel.conf | 3 +
freedom-maker/fbx-base.conf | 13 +
freedom-maker/flashing-notes | 28 ++
freedom-maker/mk_dreamplug_rootfs | 179 ++++++++++
10 files changed, 996 insertions(+), 0 deletions(-)
diff --git a/freedom-maker/.gitignore b/freedom-maker/.gitignore
new file mode 100644
index 0000000..378eac2
--- /dev/null
+++ b/freedom-maker/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/freedom-maker/COPYING b/freedom-maker/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/freedom-maker/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/freedom-maker/Makefile b/freedom-maker/Makefile
new file mode 100644
index 0000000..e8fc80a
--- /dev/null
+++ b/freedom-maker/Makefile
@@ -0,0 +1,17 @@
+# copy DreamPlug root filesystem to a usb stick with an ext3 partition
+dreamstick: stamp-dreamplug-rootfs
+ mount /media/freedom
+ sudo rsync -atvz --progress --delete build/dreamplug/ /media/freedom/
+ umount /media/freedom
+
+# populate a tree with DreamPlug root filesystem
+stamp-dreamplug-rootfs: fbx-armel.conf fbx-base.conf mk_dreamplug_rootfs
+ sudo ./mk_dreamplug_rootfs
+ touch stamp-dreamplug-rootfs
+
+clean:
+ rm -f stamp-dreamplug-rootfs
+ sudo rm -rf build/dreamplug
+
+distclean: clean
+ rm -rf build
diff --git a/freedom-maker/README b/freedom-maker/README
new file mode 100644
index 0000000..215f56e
--- /dev/null
+++ b/freedom-maker/README
@@ -0,0 +1,38 @@
+Freedom-Maker - Bdale's building tools for the FreedomBox project
+
+Install required build packages:
+ apt-get install multistrap qemu-user-static
+
+To build for a DreamPlug, use
+
+ sudo ./mk_dreamplug_rootfs
+
+This will yield a file tree under build/dreamplug, representing the
+contents of a root file system. Get that onto a USB stick with something
+like
+
+ sudo mount /dev/sdc1 /media/freedom
+ sudo rsync -atvz --progress build/dreamplug/ /media/freedom/
+ sudo umount /media/freedom
+
+Move the USB stick to the DreamPlug, and arrange to boot the existing kernel
+from internal microSD pointing to our new root filesystem by interrupting the
+boot to talk to U-Boot:
+
+ setenv x_bootargs_root root=/dev/sdc1 rootdelay=10
+ saveenv
+ reset
+
+The system should boot to a login prompt.
+
+- - - - -
+
+If you want to set things up to boot from the internal microSD card, once
+you're logged into the system booted from root on USB stick you can use:
+
+ sh /boot/copy2dream.sh
+
+- - - - -
+
+Be aware that this is an imcomplete solution for now .. you will want to at
+least do things like create unique ssh host keys for your device!
diff --git a/freedom-maker/TODO b/freedom-maker/TODO
new file mode 100644
index 0000000..32c138d
--- /dev/null
+++ b/freedom-maker/TODO
@@ -0,0 +1,13 @@
+- re-factor the script(s) to allow building for at least Sheeva and Dream
+- fold in use of vmdebootstrap to build x86 image(s)
+- there are a few things we really do want to defer to first boot, or at least
+ make it trivial to fix up per-system
+ - ssh host keys
+ - root password
+- decide what we're going to do about the provided u-boot .. use or replace?
+- decide which kernel we actually want to run and incorporate into the build
+- work out recommended process for getting from freedom-maker outputs to bits
+ installed and running on each target type
+ - DreamPlug: sh /boot/copy2dream.sh
+- add Sheeva as a build target
+- add x86 virtualized as a build target (use vmdebootstrap?)
diff --git a/freedom-maker/bin/copy2dream.sh b/freedom-maker/bin/copy2dream.sh
new file mode 100644
index 0000000..cc800e9
--- /dev/null
+++ b/freedom-maker/bin/copy2dream.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# this script assumes the current root filesystem is the source, and the
+# internal microSD on a DreamPlug is the target .. copy the kernel uImage to
+# the FAT partition on sda1, and the root contents to the ext3 on sda2
+#
+mount /dev/sda1 /media
+mv /media/uImage /media/uImage.old
+cp /boot/uImage /media/uImage
+umount /media
+
+mke2fs -j /dev/sda2
+mount /dev/sda2 /media
+(cd / ; tar cf - `/bin/ls | grep -v proc | grep -v sys | grep -v media | grep -v dev`) | \
+ (cd /media ; tar xvf -)
+
+mkdir /media/proc /media/sys /media/media
+
+echo "Creating basic device nodes"
+mkdir /media/dev
+mknod /media/dev/console c 5 1
+mknod /media/dev/random c 1 8
+mknod /media/dev/urandom c 1 9
+mknod /media/dev/null c 1 3
+mknod /media/dev/ptmx c 5 2
+
+umount /dev/sda2
+
+echo "interrupt the next boot and change the root path to /dev/sda2"
+
diff --git a/freedom-maker/fbx-armel.conf b/freedom-maker/fbx-armel.conf
new file mode 100644
index 0000000..a6a7d6c
--- /dev/null
+++ b/freedom-maker/fbx-armel.conf
@@ -0,0 +1,3 @@
+[General]
+arch=armel
+include=fbx-base.conf
diff --git a/freedom-maker/fbx-base.conf b/freedom-maker/fbx-base.conf
new file mode 100644
index 0000000..0096f1a
--- /dev/null
+++ b/freedom-maker/fbx-base.conf
@@ -0,0 +1,13 @@
+[General]
+cleanup=false
+noauth=false
+unpack=true
+aptsources=Debian
+debootstrap=Debian
+
+[Debian]
+packages=base-files netbase openssh-server zile wget iproute net-tools hostname module-init-tools wget resolvconf udev isc-dhcp-client ifupdown rsyslog libertas-firmware
+source=http://ftp.ba.debian.org/debian
+keyring=debian-archive-keyring
+suite=squeeze
+components=main contrib non-free
diff --git a/freedom-maker/flashing-notes b/freedom-maker/flashing-notes
new file mode 100644
index 0000000..def3f61
--- /dev/null
+++ b/freedom-maker/flashing-notes
@@ -0,0 +1,28 @@
+Jason <u-boot(a)lakedaemon.net> says:
+
+ Sort of. The openocd config for the sheevaplug/guruplug is what I use,
+ and is distributed on the dreamplug download page [1]. It does _not_
+ have support for the SPI flash. You can also use the sheevaplug.cfg
+ shipped with openocd. So, I use openocd or tftp to transfer to RAM,
+ then use u-boot to write to flash.
+
+ To test images, or to reflash, I load the known-good u-boot into RAM via
+ openocd, then I'll either reflash it or load a new testing one from
+ there.
+
+ To write a u-boot.kwb test image to flash, here is what I do:
+
+ openocd$ sheevaplug_init
+ openocd$ load_image u-boot # known good from Marvell
+ openocd$ load_image u-boot.kwb 0x00800000 # monster I created
+ openocd$ resume 0x00600000 # run the known good
+
+ then, in u-boot
+
+ u-boot$ sf probe 0
+ u-boot$ sf erase 0x0 0x100000
+ u-boot$ sf write 0x00800000 0x0 0x100000
+
+ If time allows, I'd like to add SPI flash support to OpenOCD.
+ Unfortunately, time is short and the above process works.
+
diff --git a/freedom-maker/mk_dreamplug_rootfs b/freedom-maker/mk_dreamplug_rootfs
new file mode 100755
index 0000000..a70f032
--- /dev/null
+++ b/freedom-maker/mk_dreamplug_rootfs
@@ -0,0 +1,179 @@
+#!/bin/bash
+#
+# Copyright 2011 by Bdale Garbee <bdale(a)gag.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# based on work by <ivan(a)sanchezortega.es>, who released his script under
+# the following license terms:
+# ----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 42):
+# As long as you retain this notice you can do whatever you want with
+# this stuff. If we meet some day, and you think this stuff is worth it,
+# you can buy me a beer in return.
+# ----------------------------------------------------------------------------
+
+# mk_dreamplug_rootfs
+#
+# Runs multistrap and readies the resulting root filesystem to silently
+# complete package configuration on the first boot-up.
+
+# where to build images, etc
+basedir=`pwd`/build
+target=$basedir/dreamplug
+tmpdir=$basedir/tmp
+pkgcache=$tmpdir/aptcache
+
+mkdir -p $target
+mkdir -p $tmpdir
+mkdir -p $pkgcache
+
+hostname='freedombox'
+rootpassword='freedom'
+
+kernelimage=http://www.newit.co.uk/kernels/Dreamplug/Dreamplug-prerelease/uImage
+kernelmodules=http://www.newit.co.uk/kernels/Dreamplug/Dreamplug-prerelease/Modules.tar.gz
+
+if [ ! -f $tmpdir/uImage ]
+then
+ wget -c $kernelimage --output-document="$tmpdir/uImage"
+fi
+if [ ! -f $tmpdir/linux.tar.gz ]
+then
+ wget -c $kernelmodules --output-document="$tmpdir/linux.tar.gz"
+fi
+
+rm -rf $target/*
+
+mkdir -p $target/var/cache/apt/ && mount -o bind $pkgcache $target/var/cache/apt/
+
+echo "Multistrapping..."
+multistrap -f fbx-armel.conf --no-auth -d $target
+
+umount $target/var/cache/apt/
+mkdir $target/var/cache/apt/archives
+
+echo "Unpacking kernel modules..."
+mkdir -p $target/lib/modules/
+tar -C $target/lib/ -zxvf $tmpdir/linux.tar.gz | tail
+
+echo "copy uImage to target filesystem"
+mkdir -p $target/boot
+cp build/tmp/uImage $target/boot/uImage
+echo "copy copy2dream.sh script to target filesystem"
+cp bin/copy2dream.sh $target/boot/copy2dream.sh
+
+# Until udev is configured and run for the first time, dev nodes won't be created, but we need some basic ones for spawning a console (console) and creating RSA keys for SSH (urandom).
+echo "Creating basic device nodes"
+mknod $target/dev/console c 5 1
+mknod $target/dev/random c 1 8
+mknod $target/dev/urandom c 1 9
+mknod $target/dev/null c 1 3
+mknod $target/dev/ptmx c 5 2
+
+# Basic fstab & mtab..
+echo "Setting up basic fstab & mtab"
+echo "
+rootfs / rootfs relatime,rw 0 0
+proc /proc proc none 0 0
+sys /sys sysfs none 0 0
+none /dev/pts devpts defaults 0 0
+tmpfs /tmp tmpfs rw,nosuid,nodev 0 0
+" > $target/etc/fstab
+
+touch $target/etc/mtab
+
+# Set up hostname
+echo "Setting up hostname, /etc/network/interfaces, nameservers, persistent-net-generator rules"
+echo $hostname > $target/etc/hostname
+
+# Create /etc/network/interfaces
+echo "# This file describes the network interfaces available on your system
+# and how to activate them. For more information, see interfaces(5).
+
+# The loopback network interface
+auto lo
+iface lo inet loopback
+
+# The primary network interface
+allow-hotplug eth0
+iface eth0 inet dhcp
+
+allow-hotplug eth1
+iface eth1 inet dhcp
+ " > $target/etc/network/interfaces
+
+# Setup nameserver (use OpenDNS by default)
+echo "nameserver 208.67.222.222
+nameserver 208.67.220.220" > $target/etc/resolv.conf
+
+# Touch the net generator udev so that eth0 won't be reassigned in case the user
+# changes the MAC address - this may happen if you change the rootfs between plugs.
+touch $target/etc/udev/rules.d/75-persistent-net-generator.rules
+
+# generate configuration script
+
+echo "Create script to configure packages in qemu-user-static"
+
+echo "
+echo \"Preconfiguring dash - else dash and bash will be left in a broken state\"
+/var/lib/dpkg/info/dash.preinst install
+
+echo \"Configuring all packages\"
+export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
+export LC_ALL=C LANGUAGE=C LANG=C
+dpkg --configure -a
+
+# Establish an initial root password
+echo \"Set root password to \"$rootpassword
+echo root:$rootpassword | /usr/sbin/chpasswd
+
+# By default, spawn a console on the serial port
+echo \"Adding a getty on the serial port\"
+echo \"T0:12345:respawn:/sbin/getty -L ttyS0 115200 vt100\" >> /etc/inittab
+
+echo \"Tweaks to reduce flash writes as per http://www.plugcomputer.org/plugwiki/index.php/Reduce_Flash_Writes\"
+echo \"
+# Reduce writes to flash drives
+vm.laptop_mode=5
+vm.swappiness=0
+vm.dirty_writeback_centisecs=1500
+vm.dirty_expire_centisecs=1500
+\" >> /etc/sysctl.conf
+
+echo \"Deleting this very same script\"
+rm -f /install.sh
+
+echo \"Syncing filesystem just in case something didn't get written\"
+sync
+
+echo \"End configuration progress by exiting from the chroot\"
+exit
+
+" > $target/install.sh
+
+chmod 755 $target/install.sh
+
+echo "Use qemu-user-static to perform first-boot configuration now"
+
+mkdir -p $target/usr/bin
+cp /usr/bin/qemu-arm-static $target/usr/bin
+chroot $target /install.sh
+rm $target/usr/bin/qemu-arm-static
+
+echo "Syncing..."
+sync
+
+echo "Finished. You may now copy the rootfs to the plug."
[View Less]
1
0

[torbrowser/master] downgrade to vidalia 0.2.12, 0.2.13 isn't ready for stable bundles
by erinn@torproject.org 19 Aug '11
by erinn@torproject.org 19 Aug '11
19 Aug '11
commit bf2032f077487acfbdfbe673b4d9f970bc9a034f
Author: Erinn Clark <erinn(a)torproject.org>
Date: Fri Aug 19 20:30:19 2011 +0200
downgrade to vidalia 0.2.12, 0.2.13 isn't ready for stable bundles
---
README.Linux | 3 +--
README.OSX | 3 +--
build-scripts/linux.mk | 2 +-
build-scripts/osx.mk | 2 +-
4 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/README.Linux b/README.Linux
index 9dbee53..60b8bce 100644
--- a/README.Linux
+++ b/…
[View More]README.Linux
@@ -4,7 +4,7 @@ Tor Browser Bundle for GNU/Linux
Included applications
---------------------
-Vidalia 0.2.13 (with Qt 4.6.2)
+Vidalia 0.2.12 (with Qt 4.6.2)
Tor 0.2.2.31-rc (with libevent-2.0.13-stable, zlib-1.2.5 and openssl-0.9.8p)
Firefox 3.6.20
\_ Torbutton 1.2.5
@@ -30,7 +30,6 @@ Changelog
1.1.13: Released 2011-08-19
Update Tor to 0.2.2.31-rc
- Update Vidalia to 0.2.13
Update Firefox to 3.6.20
Update Libevent to 2.0.13-stable
Update NoScript to 2.1.2.6
diff --git a/README.OSX b/README.OSX
index cea0edf..a5c6673 100644
--- a/README.OSX
+++ b/README.OSX
@@ -4,7 +4,7 @@ Tor Browser Bundle for Mac OS X
Included applications
---------------------
-Vidalia 0.2.13 (with Qt 4.6.2)
+Vidalia 0.2.12 (with Qt 4.6.2)
Tor 0.2.2.31-rc (with libevent-2.0.13-stable, zlib-1.2.5 and openssl-0.9.8p)
Polipo 1.0.4.1
Firefox 3.6.20
@@ -25,7 +25,6 @@ Changelog
1.0.23: Released 2011-08-19
Update Tor to 0.2.2.31-rc
- Update Vidalia to 0.2.13
Update Firefox to 3.6.20
Update Libevent to 2.0.13-stable
Update NoScript to 2.1.2.6
diff --git a/build-scripts/linux.mk b/build-scripts/linux.mk
index e007388..d725dd0 100644
--- a/build-scripts/linux.mk
+++ b/build-scripts/linux.mk
@@ -53,7 +53,7 @@ POLIPO_VER=1.0.4.1
QT_VER=4.6.2
TOR_VER=0.2.2.31-rc
TORBUTTON_VER=1.2.5
-VIDALIA_VER=0.2.13
+VIDALIA_VER=0.2.12
ZLIB_VER=1.2.5
## Extension IDs
diff --git a/build-scripts/osx.mk b/build-scripts/osx.mk
index bbcddb5..f4a25e1 100644
--- a/build-scripts/osx.mk
+++ b/build-scripts/osx.mk
@@ -53,7 +53,7 @@ POLIPO_VER=1.0.4.1
QT_VER=4.6.2
TOR_VER=0.2.2.31-rc
TORBUTTON_VER=1.2.5
-VIDALIA_VER=0.2.13
+VIDALIA_VER=0.2.12
ZLIB_VER=1.2.5
## Extension IDs
[View Less]
1
0