tbb-commits
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- 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
- 1 participants
- 20056 discussions
[torbutton/master] Bug 9387: Version 0.2 of the Security Slider.
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit cda1d6cd71a5c5b84dfd45bcf042b5ada8ee58b4
Author: Georg Koppen <gk(a)torproject.org>
Date: Thu Oct 30 22:54:32 2014 +0000
Bug 9387: Version 0.2 of the Security Slider.
Version 0.2 contains the slider and the option to choose a mode which
results in preferences enabled/disabled depending on the respective
security level chosen. The UI is in Torbutton's preferences dialog only
for now. If the user manipluates preferences governed by the slider the
custom checkbox is checked and unhidden indicating that the user is
currently in a non-standard user group.
Missing pieces:
-tooltips/help buttons explaining the security levels
-preferences for disabling SVG and MathML (#12827 and #13548)
---
src/chrome/content/preferences.js | 37 +++++++
src/chrome/content/preferences.xul | 62 +++++++++--
src/chrome/content/torbutton.js | 177 +++++++++++++++++++++++++++++++
src/chrome/locale/en/torbutton.dtd | 9 +-
src/defaults/preferences/preferences.js | 3 +
5 files changed, 276 insertions(+), 12 deletions(-)
diff --git a/src/chrome/content/preferences.js b/src/chrome/content/preferences.js
index 4c3c74d..20a6c9f 100644
--- a/src/chrome/content/preferences.js
+++ b/src/chrome/content/preferences.js
@@ -180,10 +180,21 @@ function torbutton_prefs_init(doc) {
doc.getElementById('torbutton_settingsMethod').selectedItem = doc.getElementById('torbutton_transparentTor');
}
+ // Privacy and security settings
doc.getElementById('torbutton_blockDisk').checked = o_torprefs.getBoolPref('block_disk');
doc.getElementById('torbutton_resistFingerprinting').checked = o_torprefs.getBoolPref('resist_fingerprinting');
doc.getElementById('torbutton_blockPlugins').checked = o_torprefs.getBoolPref('no_tor_plugins');
doc.getElementById('torbutton_restrictThirdParty').checked = o_torprefs.getBoolPref('restrict_thirdparty');
+ let sec_slider = doc.getElementById('torbutton_sec_slider');
+ let sec_custom = doc.getElementById('torbutton_sec_custom');
+ let custom_values = o_torprefs.getBoolPref('security_custom');
+ sec_slider.value = o_torprefs.getIntPref('security_slider');
+ sec_slider.disabled = custom_values;
+ // Setting |disabled| to |false| is not enough to have the element
+ // non-responding. We need to handle |movetoclick| as well.
+ sec_slider.setAttribute("movetoclick", !custom_values);
+ sec_custom.checked = custom_values;
+ sec_custom.collapsed = !custom_values;
torbutton_prefs_set_field_attributes(doc);
}
@@ -273,13 +284,22 @@ function torbutton_prefs_save(doc) {
}
}
+ // Privacy and Security Settings
o_torprefs.setBoolPref('block_disk', doc.getElementById('torbutton_blockDisk').checked);
o_torprefs.setBoolPref('resist_fingerprinting', doc.getElementById('torbutton_resistFingerprinting').checked);
o_torprefs.setBoolPref('no_tor_plugins', doc.getElementById('torbutton_blockPlugins').checked);
o_torprefs.setBoolPref('restrict_thirdparty', doc.getElementById('torbutton_restrictThirdParty').checked);
+ o_torprefs.setBoolPref('security_custom',
+ doc.getElementById('torbutton_sec_custom').checked);
+ o_torprefs.setIntPref('security_slider',
+ doc.getElementById('torbutton_sec_slider').value);
// if tor settings were initially active, update the active settings to reflect any changes
if (tor_enabled) torbutton_activate_tor_settings();
+ // If we have non-custom Security Slider settings update them now.
+ if (!o_torprefs.getBoolPref('security_custom')) {
+ win.torbutton_update_security_slider();
+ }
}
function torbutton_prefs_test_settings() {
@@ -413,6 +433,11 @@ function torbutton_prefs_reset_defaults() {
}
}
+ // Resetting the Security Slider preferences
+ o_torprefs.setBoolPref('security_custom', false);
+ o_torprefs.setIntPref('security_slider', 1);
+ chrome.torbutton_update_security_slider();
+
torbutton_log(4, "Preferences reset to defaults");
torbutton_prefs_init(window.document);
@@ -421,3 +446,15 @@ function torbutton_prefs_reset_defaults() {
.getService(Components.interfaces.nsIPrefService);
prefService.savePrefFile(null);
}
+
+function torbutton_toggle_slider(doc) {
+ let slider = doc.getElementById("torbutton_sec_slider");
+ if (doc.getElementById("torbutton_sec_custom").checked) {
+ slider.disabled = true;
+ slider.setAttribute("movetoclick", false);
+ } else {
+ slider.disabled = false;
+ slider.setAttribute("movetoclick", true);
+ }
+}
+
diff --git a/src/chrome/content/preferences.xul b/src/chrome/content/preferences.xul
index 5198565..7c5633b 100644
--- a/src/chrome/content/preferences.xul
+++ b/src/chrome/content/preferences.xul
@@ -19,7 +19,7 @@
<tabbox>
<tabs>
<tab label="&torbutton.prefs.tor_settings;"/>
- <tab label="&torbutton.prefs.sec_settings;"/>
+ <tab label="&torbutton.prefs.privacy_security_settings;"/>
</tabs>
<tabpanels>
<tabpanel>
@@ -140,16 +140,56 @@
</vbox>
</tabpanel>
<tabpanel>
- <vbox>
- <checkbox id="torbutton_blockDisk"
- label="&torbutton.prefs.block_disk;"/>
- <checkbox id="torbutton_blockPlugins"
- label="&torbutton.prefs.block_plugins;"/>
- <checkbox id="torbutton_restrictThirdParty"
- label="&torbutton.prefs.restrict_thirdparty;"/>
- <checkbox id="torbutton_resistFingerprinting"
- label="&torbutton.prefs.resist_fingerprinting;"/>
- </vbox>
+ <vbox>
+ <groupbox>
+ <caption label="&torbutton.prefs.priv_caption;"/>
+ <checkbox id="torbutton_blockDisk"
+ label="&torbutton.prefs.block_disk;"/>
+ <checkbox id="torbutton_blockPlugins"
+ label="&torbutton.prefs.block_plugins;"/>
+ <checkbox id="torbutton_restrictThirdParty"
+ label="&torbutton.prefs.restrict_thirdparty;"/>
+ <checkbox id="torbutton_resistFingerprinting"
+ label="&torbutton.prefs.resist_fingerprinting;"/>
+ </groupbox>
+ <spacer flex="1"/>
+ <groupbox>
+ <caption label="&torbutton.prefs.sec_caption;"/>
+ <hbox>
+ <vbox>
+ <scale id="torbutton_sec_slider" height="200" min="1" max="4"
+ movetoclick="true" orient="vertical"/>
+ </vbox>
+ <vbox height="200">
+ <hbox flex="1" align="center">
+ <description id="torbutton_sec_low">
+ &torbutton.prefs.sec_low;
+ </description>
+ </hbox>
+ <hbox flex="1" align="center">
+ <description id="torbutton_sec_med_low">
+ &torbutton.prefs.sec_med_low;
+ </description>
+ </hbox>
+ <hbox flex="1" align="center">
+ <description id="torbutton_sec_med_high">
+ &torbutton.prefs.sec_med_high;
+ </description>
+ </hbox>
+ <hbox flex="1" align="center">
+ <description id="torbutton_sec_high">
+ &torbutton.prefs.sec_high;
+ </description>
+ </hbox>
+ </vbox>
+ </hbox>
+ <hbox>
+ <checkbox id="torbutton_sec_custom" flex="1"
+ oncommand="torbutton_toggle_slider(document);"
+ label="&torbutton.prefs.sec_custom;"/>
+ </hbox>
+ </groupbox>
+ </vbox>
</tabpanel>
</tabpanels>
diff --git a/src/chrome/content/torbutton.js b/src/chrome/content/torbutton.js
index 44020ec..6995197 100644
--- a/src/chrome/content/torbutton.js
+++ b/src/chrome/content/torbutton.js
@@ -52,6 +52,8 @@ var m_tb_orig_BrowserOnAboutPageLoad = null;
var m_tb_domWindowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
+var m_tb_sliderUpdate = false;
+
// Bug 1506 P1: This object is only for updating the UI for toggling and style
var torbutton_window_pref_observer =
{
@@ -118,6 +120,12 @@ var torbutton_unique_pref_observer =
this._branch.addObserver("network.proxy", this, false);
this._branch.addObserver("network.cookie", this, false);
this._branch.addObserver("browser.privatebrowsing.autostart", this, false);
+ this._branch.addObserver("javascript", this, false);
+ this._branch.addObserver("gfx", this, false);
+ this._branch.addObserver("noscript", this, false);
+ this._branch.addObserver("media", this, false);
+ this._branch.addObserver("capability.policy.maonoscript.sites", this,
+ false);
// We observe xpcom-category-entry-added for plugins w/ Gecko-Content-Viewers
var observerService = Cc["@mozilla.org/observer-service;1"].
@@ -132,6 +140,11 @@ var torbutton_unique_pref_observer =
this._branch.removeObserver("network.proxy", this);
this._branch.removeObserver("network.cookie", this);
this._branch.removeObserver("browser.privatebrowsing.autostart", this);
+ this._branch.removeObserver("javascript", this);
+ this._branch.removeObserver("gfx", this);
+ this._branch.removeObserver("noscript", this);
+ this._branch.removeObserver("media", this);
+ this._branch.removeObserver("capability.policy.maonoscript.sites", this);
var observerService = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
@@ -218,6 +231,32 @@ var torbutton_unique_pref_observer =
case "extensions.torbutton.restrict_thirdparty":
torbutton_update_thirdparty_prefs();
break;
+ case "gfx.font_rendering.opentype_svg.enabled":
+ case "javascript.options.ion.content":
+ case "javascript.options.typeinference":
+ case "javascript.options.asmjs":
+ case "noscript.forbidMedia":
+ case "media.webaudio.enabled":
+ case "javascript.options.baselinejit.content":
+ case "noscript.forbidFonts":
+ case "gfx.font_rendering.graphite.enabled":
+ case "noscript.globalHttpsWhitelist":
+ case "noscript.global":
+ case "media.ogg.enabled":
+ case "media.opus.enabled":
+ case "media.wave.enabled":
+ case "media.apple.mp3.enabled":
+ case "capability.policy.maonoscript.sites":
+ if (!m_tb_sliderUpdate) {
+ // Do we already have custom settings?
+ let customSlider = m_tb_prefs.
+ getBoolPref("extensions.torbutton.security_custom");
+ if (!customSlider) {
+ m_tb_prefs.
+ setBoolPref("extensions.torbutton.security_custom", true);
+ }
+ }
+ break;
}
}
}
@@ -513,6 +552,8 @@ function torbutton_init() {
// initialize preferences before we start our prefs observer
torbutton_init_prefs();
+ // set some important security prefs according to the chosen security level
+ torbutton_update_security_slider();
// set panel style from preferences
torbutton_set_panel_style();
@@ -2092,6 +2133,142 @@ function torbutton_update_thirdparty_prefs() {
prefService.savePrefFile(null);
}
+var torbutton_sec_l_bool_prefs = {
+ "gfx.font_rendering.opentype_svg.enabled" : false,
+};
+
+var torbutton_sec_ml_bool_prefs = {
+ "javascript.options.ion.content" : false,
+ "javascript.options.typeinference" : false,
+ "javascript.options.asmjs" : false,
+ "noscript.forbidMedia" : true,
+ "media.webaudio.enabled" : false,
+ // XXX: pref for disabling MathML is missing
+};
+
+var torbutton_sec_mh_bool_prefs = {
+ "javascript.options.baselinejit.content" : false,
+ "noscript.globalHttpsWhitelist" : true,
+ // XXX: pref for disableing SVG is missing
+};
+
+var torbutton_sec_h_bool_prefs = {
+ "noscript.forbidFonts" : true,
+ "noscript.global" : false,
+ "media.ogg.enabled" : false,
+ "media.opus.enabled" : false,
+ "media.wave.enabled" : false,
+ "media.apple.mp3.enabled" : false
+};
+
+function torbutton_update_security_slider() {
+ // Avoid checking the custom settings checkbox.
+ m_tb_sliderUpdate = true;
+ let mode = m_tb_prefs.getIntPref("extensions.torbutton.security_slider");
+ let capValue = m_tb_prefs.getCharPref("capability.policy.maonoscript.sites");
+ switch (mode) {
+ case 1:
+ for (p in torbutton_sec_l_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_l_bool_prefs[p]);
+ }
+ for (p in torbutton_sec_ml_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, !torbutton_sec_ml_bool_prefs[p])
+ }
+ for (p in torbutton_sec_mh_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, !torbutton_sec_mh_bool_prefs[p])
+ }
+ for (p in torbutton_sec_h_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, !torbutton_sec_h_bool_prefs[p])
+ }
+ // XXX: Adding and removing "https:" is needed due to a bug in Noscript.
+ if (capValue.indexOf(" https:") >= 0) {
+ m_tb_prefs.setCharPref("capability.policy.maonoscript.sites",
+ capValue.replace(" https:", ""));
+ }
+ if (m_tb_prefs.getCharPref("general.useragent.locale") !== "ko" ||
+ m_tb_prefs.getCharPref("general.useragent.locale") !== "vi" ||
+ m_tb_prefs.getCharPref("general.useragent.locale") !== "zh-CN") {
+ m_tb_prefs.setBoolPref("gfx.font_rendering.graphite.enabled", false);
+ } else {
+ m_tb_prefs.setBoolPref("gfx.font_rendering.graphite.enabled", true);
+ }
+ break;
+ case 2:
+ for (p in torbutton_sec_l_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_l_bool_prefs[p]);
+ }
+ for (p in torbutton_sec_ml_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_ml_bool_prefs[p])
+ }
+ for (p in torbutton_sec_mh_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, !torbutton_sec_mh_bool_prefs[p])
+ }
+ for (p in torbutton_sec_h_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, !torbutton_sec_h_bool_prefs[p])
+ }
+ // XXX: Adding and removing "https:" is needed due to a bug in Noscript.
+ if (capValue.indexOf(" https:") >= 0) {
+ m_tb_prefs.setCharPref("capability.policy.maonoscript.sites",
+ capValue.replace(" https:", ""));
+ }
+ if (m_tb_prefs.getCharPref("general.useragent.locale") !== "ko" ||
+ m_tb_prefs.getCharPref("general.useragent.locale") !== "vi" ||
+ m_tb_prefs.getCharPref("general.useragent.locale") !== "zh-CN") {
+ m_tb_prefs.setBoolPref("gfx.font_rendering.graphite.enabled", false);
+ } else {
+ m_tb_prefs.setBoolPref("gfx.font_rendering.graphite.enabled", true);
+ }
+ break;
+ case 3:
+ for (p in torbutton_sec_l_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_l_bool_prefs[p]);
+ }
+ for (p in torbutton_sec_ml_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_ml_bool_prefs[p])
+ }
+ for (p in torbutton_sec_mh_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_mh_bool_prefs[p])
+ }
+ for (p in torbutton_sec_h_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, !torbutton_sec_h_bool_prefs[p])
+ }
+ // XXX: Adding and removing "https:" is needed due to a bug in Noscript.
+ // missing.
+ if (capValue.indexOf(" https:") < 0) {
+ m_tb_prefs.setCharPref("capability.policy.maonoscript.sites", capValue +
+ " https:");
+ }
+ m_tb_prefs.setBoolPref("gfx.font_rendering.graphite.enabled", false);
+ break;
+ case 4:
+ for (p in torbutton_sec_l_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_l_bool_prefs[p]);
+ }
+ for (p in torbutton_sec_ml_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_ml_bool_prefs[p])
+ }
+ for (p in torbutton_sec_mh_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_mh_bool_prefs[p])
+ // noscript.globalHttpsWhitelist is special: We don't want it in this
+ // mode.
+ if (p == "noscript.globalHttpsWhitelist") {
+ m_tb_prefs.setBoolPref(p, !torbutton_sec_mh_bool_prefs[p])
+ }
+ }
+ for (p in torbutton_sec_h_bool_prefs) {
+ m_tb_prefs.setBoolPref(p, torbutton_sec_h_bool_prefs[p])
+ }
+ // XXX: Adding and removing "https:" is needed due to a bug in Noscript.
+ if (capValue.indexOf(" https:") >= 0) {
+ m_tb_prefs.setCharPref("capability.policy.maonoscript.sites",
+ capValue.replace(" https:", ""));
+ }
+ m_tb_prefs.setBoolPref("gfx.font_rendering.graphite.enabled", true);
+ break;
+ }
+ m_tb_sliderUpdate = false;
+}
+
// Bug 1506 P0: This code is a toggle-relic.
//
// It basically just enforces the three Torbutton prefs
diff --git a/src/chrome/locale/en/torbutton.dtd b/src/chrome/locale/en/torbutton.dtd
index 1457b20..283032b 100644
--- a/src/chrome/locale/en/torbutton.dtd
+++ b/src/chrome/locale/en/torbutton.dtd
@@ -44,7 +44,7 @@
<!ENTITY torbutton.context_menu.openTorWindow.key "d">
<!ENTITY torbutton.button.label "Torbutton">
<!ENTITY torbutton.button.tooltip "Click to initialize Torbutton">
-<!ENTITY torbutton.prefs.sec_settings "Security Settings">
+<!ENTITY torbutton.prefs.privacy_security_settings "Privacy and Security Settings">
<!ENTITY torbutton.prefs.block_thread "Block history reads during Tor (crucial)">
<!ENTITY torbutton.prefs.block_thwrite "Block history writes during Tor (recommended)">
<!ENTITY torbutton.prefs.block_nthread "Block history reads during Non-Tor (optional)">
@@ -144,7 +144,14 @@
<!ENTITY torbutton.prefs.engine5 "duckduckgo.com">
<!ENTITY torbutton.prefs.fix_google_srch "Strip platform and language off of Google Search Box queries">
<!ENTITY torbutton.prefs.transparentTor "Transparent Torification (Requires custom transproxy or Tor router)">
+<!ENTITY torbutton.prefs.priv_caption "Privacy Settings">
<!ENTITY torbutton.prefs.block_disk "Don't record browsing history or website data (enables Private Browsing Mode)">
<!ENTITY torbutton.prefs.restrict_thirdparty "Restrict third party cookies and other tracking data">
<!ENTITY torbutton.prefs.block_plugins "Disable browser plugins (such as Flash)">
<!ENTITY torbutton.prefs.resist_fingerprinting "Change details that distinguish you from other Tor Browser users">
+<!ENTITY torbutton.prefs.sec_caption "Security Level">
+<!ENTITY torbutton.prefs.sec_low "Low (default)">
+<!ENTITY torbutton.prefs.sec_med_low "Medium-Low">
+<!ENTITY torbutton.prefs.sec_med_high "Medium-High">
+<!ENTITY torbutton.prefs.sec_high "High">
+<!ENTITY torbutton.prefs.sec_custom "Custom Values">
diff --git a/src/defaults/preferences/preferences.js b/src/defaults/preferences/preferences.js
index af9838a..d527d7e 100644
--- a/src/defaults/preferences/preferences.js
+++ b/src/defaults/preferences/preferences.js
@@ -173,6 +173,9 @@ pref("extensions.torbutton(a)torproject.org.getAddons.cache.enabled", false);
pref("extensions.torbutton.block_disk", true);
pref("extensions.torbutton.resist_fingerprinting", true);
pref("extensions.torbutton.restrict_thirdparty", true);
+// Security Slider
+pref("extensions.torbutton.security_slider", 1);
+pref("extensions.torbutton.security_custom", false);
// Google Captcha prefs
// FIXME: NID cookie?
1
0
[torbutton/master] Bug #3455.3: Add DomainIsolator, for isolating circuit by domain.
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit 59445b7baed58e712bd38c02e6dc75882ff0c997
Author: Arthur Edelstein <arthuredelstein(a)gmail.com>
Date: Mon Jul 14 00:40:13 2014 -0700
Bug #3455.3: Add DomainIsolator, for isolating circuit by domain.
An XPCOM component that registers a ProtocolProxyChannelFilter
which sets the username/password for each web request according to
url bar domain.
---
src/chrome.manifest | 5 +-
src/components/domain-isolator.js | 128 +++++++++++++++++++++++++++++++++++++
2 files changed, 132 insertions(+), 1 deletion(-)
diff --git a/src/chrome.manifest b/src/chrome.manifest
index af44862..d211984 100644
--- a/src/chrome.manifest
+++ b/src/chrome.manifest
@@ -155,7 +155,10 @@ contract @torproject.org/torbutton-torCheckService;1 {5d57312b-5d8c-4169-b4af-e8
component {f36d72c9-9718-4134-b550-e109638331d7} components/torbutton-logger.js
contract @torproject.org/torbutton-logger;1 {f36d72c9-9718-4134-b550-e109638331d7}
+component {e33fd6d4-270f-475f-a96f-ff3140279f68} components/domain-isolator.js
+contract @torproject.org/domain-isolator;1 {e33fd6d4-270f-475f-a96f-ff3140279f68}
+
category profile-after-change CookieJarSelector @torproject.org/cookie-jar-selector;1
-# category profile-after-change RefSpoofer @torproject.org/torRefSpoofer;1
category profile-after-change TBSessionBlocker @torproject.org/torbutton-ss-blocker;1
category profile-after-change StartupObserver @torproject.org/startup-observer;1
+category profile-after-change DomainIsolator @torproject.org/domain-isolator;1
\ No newline at end of file
diff --git a/src/components/domain-isolator.js b/src/components/domain-isolator.js
new file mode 100644
index 0000000..e8e6bfa
--- /dev/null
+++ b/src/components/domain-isolator.js
@@ -0,0 +1,128 @@
+// # domain-isolator.js
+// A component for TorBrowser that puts requests from different
+// first party domains on separate tor circuits.
+
+// This file is written in call stack order (later functions
+// call earlier functions). The code file can be processed
+// with docco.js to provide clear documentation.
+
+/* jshint moz: true */
+/* global Components, console, XPCOMUtils */
+
+// ### Abbreviations
+const Cc = Components.classes, Ci = Components.interfaces, Cu = Components.utils;
+
+// Make the logger available.
+let logger = Cc["@torproject.org/torbutton-logger;1"]
+ .getService(Components.interfaces.nsISupports).wrappedJSObject;
+
+// ## mozilla namespace.
+// Useful functionality for interacting with Mozilla services.
+let mozilla = mozilla || {};
+
+// __mozilla.protocolProxyService__.
+// Mozilla's protocol proxy service, useful for managing proxy connections made
+// by the browser.
+mozilla.protocolProxyService = Cc["@mozilla.org/network/protocol-proxy-service;1"]
+ .getService(Ci.nsIProtocolProxyService);
+
+// __mozilla.thirdPartyUtil__.
+// Mozilla's Thirdy Party Utilities, for figuring out first party domain.
+mozilla.thirdPartyUtil = Cc["@mozilla.org/thirdpartyutil;1"]
+ .getService(Ci.mozIThirdPartyUtil);
+
+// __mozilla.registerProxyChannelFilter(filterFunction, positionIndex)__.
+// Registers a proxy channel filter with the Mozilla Protocol Proxy Service,
+// which will help to decide the proxy to be used for a given channel.
+// The filterFunction should expect two arguments, (aChannel, aProxy),
+// where aProxy is the proxy or list of proxies that would be used by default
+// for the given channel, and should return a new Proxy or list of Proxies.
+mozilla.registerProxyChannelFilter = function (filterFunction, positionIndex) {
+ let proxyFilter = {
+ applyFilter : function (aProxyService, aChannel, aProxy) {
+ return filterFunction(aChannel, aProxy);
+ }
+ };
+ mozilla.protocolProxyService.registerChannelFilter(proxyFilter, positionIndex);
+};
+
+// ## tor functionality.
+let tor = tor || {};
+
+// __tor.noncesForDomains__.
+// A mutable map that records what nonce we are using for each domain.
+tor.noncesForDomains = {};
+
+// __tor.socksProxyCredentials(originalProxy, domain)__.
+// Takes a proxyInfo object (originalProxy) and returns a new proxyInfo
+// object with the same properties, except the username is set to the
+// the domain, and the password is a nonce.
+tor.socksProxyCredentials = function (originalProxy, domain) {
+ // Check if we already have a nonce. If not, create
+ // one for this domain.
+ if (!tor.noncesForDomains.hasOwnProperty(domain)) {
+ tor.noncesForDomains[domain] = 0;
+ }
+ let proxy = originalProxy.QueryInterface(Ci.nsIProxyInfo);
+ return mozilla.protocolProxyService
+ .newSOCKSProxyInfo(proxy.host,
+ proxy.port,
+ domain, // username
+ tor.noncesForDomains[domain].toString(), // password
+ proxy.flags,
+ proxy.failoverTimeout,
+ proxy.failoverProxy);
+};
+
+// __tor.isolateCircuitsByDomain()__.
+// For every HTTPChannel, replaces the default SOCKS proxy with one that authenticates
+// to the SOCKS server (the tor client process) with a username (the first party domain)
+// and a nonce password. Tor provides a separate circuit for each username+password
+// combination.
+tor.isolateCircuitsByDomain = function () {
+ mozilla.registerProxyChannelFilter(function (aChannel, aProxy) {
+ try {
+ let channel = aChannel.QueryInterface(Ci.nsIHttpChannel),
+ firstPartyURI = mozilla.thirdPartyUtil.getFirstPartyURIFromChannel(channel, true)
+ .QueryInterface(Ci.nsIURI),
+ firstPartyDomain = mozilla.thirdPartyUtil
+ .getFirstPartyHostForIsolation(firstPartyURI),
+ proxy = aProxy.QueryInterface(Ci.nsIProxyInfo),
+ replacementProxy = tor.socksProxyCredentials(aProxy, firstPartyDomain);
+ logger.eclog(3, "tor SOCKS: " + channel.URI.spec + " via " +
+ replacementProxy.username + ":" + replacementProxy.password);
+ return replacementProxy;
+ } catch (err) {
+ // If we fail, then just use the default proxyInfo.
+ return aProxy;
+ }
+ }, 0);
+};
+
+// ## XPCOM component construction.
+// Module specific constants
+const kMODULE_NAME = "TorBrowser Domain Isolator";
+const kMODULE_CONTRACTID = "@torproject.org/domain-isolator;1";
+const kMODULE_CID = Components.ID("e33fd6d4-270f-475f-a96f-ff3140279f68");
+
+// Import XPCOMUtils object.
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+// DomainIsolator object. Constructor does nothing.
+function DomainIsolator() { }
+// Firefox component requirements
+DomainIsolator.prototype = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]),
+ classDescription: kMODULE_NAME,
+ classID: kMODULE_CID,
+ contractID: kMODULE_CONTRACTID,
+ observe: function (subject, topic, data) {
+ if (topic === "profile-after-change") {
+ logger.eclog(3, "domain isolator: set up isolating circuits by domain");
+ tor.isolateCircuitsByDomain();
+ }
+ }
+};
+
+// Assign factory to global object.
+const NSGetFactory = XPCOMUtils.generateNSGetFactory([DomainIsolator]);
1
0
[torbutton/master] Bug #8641: TorButton popup menu that displays current Tor circuit
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit 2c2c5a8aceae44c68915e8fe33bc3865f00b535c
Author: Arthur Edelstein <arthuredelstein(a)gmail.com>
Date: Fri Aug 1 23:28:06 2014 -0700
Bug #8641: TorButton popup menu that displays current Tor circuit
---
src/chrome.manifest | 3 +-
src/chrome/content/popup.xul | 33 +-
src/chrome/content/tor-circuit-display.js | 185 ++++++++++
src/chrome/content/torbutton.js | 2 +
src/chrome/content/torbutton.xul | 1 +
src/chrome/skin/torbutton.css | 15 +
src/modules/tor-control-port.js | 575 +++++++++++++++++++++++++++++
7 files changed, 809 insertions(+), 5 deletions(-)
diff --git a/src/chrome.manifest b/src/chrome.manifest
index d211984..2ab3c8f 100644
--- a/src/chrome.manifest
+++ b/src/chrome.manifest
@@ -3,6 +3,7 @@ overlay chrome://browser/content/browser.xul chrome://torbutton/content/torbutto
overlay chrome://browser/content/preferences/connection.xul chrome://torbutton/content/pref-connection.xul
overlay chrome://messenger/content/messenger.xul chrome://torbutton/content/torbutton_tb.xul
overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://torbutton/content/torbutton_tb.xul
+resource torbutton ./
# browser branding
override chrome://branding/locale/brand.dtd chrome://torbutton/locale/brand.dtd
@@ -161,4 +162,4 @@ contract @torproject.org/domain-isolator;1 {e33fd6d4-270f-475f-a96f-ff3140279f68
category profile-after-change CookieJarSelector @torproject.org/cookie-jar-selector;1
category profile-after-change TBSessionBlocker @torproject.org/torbutton-ss-blocker;1
category profile-after-change StartupObserver @torproject.org/startup-observer;1
-category profile-after-change DomainIsolator @torproject.org/domain-isolator;1
\ No newline at end of file
+category profile-after-change DomainIsolator @torproject.org/domain-isolator;1
diff --git a/src/chrome/content/popup.xul b/src/chrome/content/popup.xul
index 3ee953b..2965ec5 100644
--- a/src/chrome/content/popup.xul
+++ b/src/chrome/content/popup.xul
@@ -9,14 +9,16 @@
<stringbundleset id="torbutton-stringbundleset">
<stringbundle id="torbutton-bundle" src="chrome://torbutton/locale/torbutton.properties"/>
</stringbundleset>
- <menupopup id="torbutton-context-menu" onpopupshowing="torbutton_check_protections();"
- anchor="torbutton-button" position="after_start">
+ <panel id="torbutton-context-menu" onpopupshowing="torbutton_check_protections();" titlebar="normal" noautohide="true"
+ anchor="torbutton-button" position="after_start" >
+ <hbox align="start">
+ <vbox>
<menuitem id="torbutton-new-identity"
label="&torbutton.context_menu.new_identity;"
accesskey="&torbutton.context_menu.new_identity_key;"
insertafter="context-stop"
oncommand="torbutton_new_identity()"/>
- <menuitem id="torbutton-cookie-protector"
+ <menuitem id="torbutton-cookie-protector"
label="&torbutton.context_menu.cookieProtections;"
accesskey="&torbutton.context_menu.cookieProtections.key;"
insertafter="context-stop"
@@ -42,6 +44,29 @@
insertafter="context-stop"
oncommand="torbutton_download_update()"
hidden="true"/>
- </menupopup>
+ </vbox>
+ <vbox>
+ <!-- The following SVG is used to display a Tor circuit diagram for the current tab.
+ It is not displayed unless activated by tor-circuit-display.js. -->
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full"
+ width="290" height="140" id="tor-circuit" style="display:none;">
+ <rect x="0" y="0" width="100%" height="100%" fill="#e8f4f4" />
+ <text id="title" style="font-size:14px;font-weight:bold;" x="10" y="20" fill="#2c26a7">Tor circuit for this site</text>
+ <text id="domain" style="font-size:13px;" x="10" y="38" fill="black">(trac.torproject.org)</text>
+ <rect x="18.5" width="3" y="56" height="64" fill="#4d363a" stroke-width="0"/>
+ <circle class="node-circle" cx="20" cy="56" r="4" />
+ <text class="node-text" x="32" y="56">This Browser</text>
+ <circle class="node-circle" cx="20" cy="72" r="4" />
+ <text class="node-text" x="32" y="72">Test123 (54.67.87.34)</text>
+ <circle class="node-circle" cx="20" cy="88" r="4" />
+ <text class="node-text" x="32" y="88">TestABC (121.4.56.67)</text>
+ <circle class="node-circle" cx="20" cy="104" r="4" />
+ <text class="node-text" x="32" y="104">TestXYZ (74.3.30.9)</text>
+ <circle class="node-circle" cx="20" cy="120" r="4" />
+ <text class="node-text" x="32" y="120">Internet</text>
+ </svg>
+ </vbox>
+ </hbox>
+ </panel>
</overlay>
diff --git a/src/chrome/content/tor-circuit-display.js b/src/chrome/content/tor-circuit-display.js
new file mode 100644
index 0000000..5f4d8bf
--- /dev/null
+++ b/src/chrome/content/tor-circuit-display.js
@@ -0,0 +1,185 @@
+// A script that automatically displays the Tor Circuit used for the
+// current domain for the currently selected tab.
+//
+// This file is written in call stack order (later functions
+// call earlier functions). The file can be processed
+// with docco.js to produce pretty documentation.
+//
+// This script is to be embedded in torbutton.xul. It defines a single global function,
+// runTorCircuitDisplay(host, port, password), which activates the automatic Tor
+// circuit display for the current tab and any future tabs.
+//
+// See https://trac.torproject.org/8641
+
+/* jshint esnext: true */
+/* global document, gBrowser, Components */
+
+// ### Main function
+// __runTorCircuitDisplay(host, port, password)__.
+// The single function we run to activate automatic display of the Tor circuit..
+let runTorCircuitDisplay = (function () {
+
+"use strict";
+
+// Mozilla utilities
+const Cu = Components.utils;
+Cu.import("resource://gre/modules/Services.jsm");
+
+// Import the controller code.
+let { controller } = Cu.import("resource://torbutton/modules/tor-control-port.js");
+
+// Make the TorButton logger available.
+let logger = Cc["@torproject.org/torbutton-logger;1"]
+ .getService(Components.interfaces.nsISupports).wrappedJSObject;
+
+// __regionBundle__.
+// A list of localized region (country) names.
+let regionBundle = Services.strings.createBundle(
+ "chrome://global/locale/regionNames.properties");
+
+// __localizedCountryNameFromCode(countryCode)__.
+// Convert a country code to a localized country name.
+// Example: `'de'` -> `'Deutschland'` in German locale.
+let localizedCountryNameFromCode = function (countryCode) {
+ try {
+ return regionBundle.GetStringFromName(countryCode.toLowerCase());
+ } catch (e) {
+ return countryCode.toUpperCase();
+ }
+};
+
+// __domainToNodeDataMap__.
+// A mutable map that stores the current nodes for each domain.
+let domainToNodeDataMap = {};
+
+// __trimQuotes(s)__.
+// Removes quotation marks around a quoted string.
+let trimQuotes = s => s.match(/^\"(.*)\"$/)[1];
+
+// nodeDataForID(controller, id, onResult)__.
+// Requests the IP, country code, and name of a node with given ID.
+// Returns result via onResult.
+// Example: nodeData(["20BC91DC525C3DC9974B29FBEAB51230DE024C44"], show);
+let nodeDataForID = function (controller, ids, onResult) {
+ let idRequests = ids.map(id => "ns/id/" + id);
+ controller.getInfoMultiple(idRequests, function (statusMaps) {
+ let IPs = statusMaps.map(statusMap => statusMap.IP),
+ countryRequests = IPs.map(ip => "ip-to-country/" + ip);
+ controller.getInfoMultiple(countryRequests, function (countries) {
+ let results = [];
+ for (let i = 0; i < ids.length; ++i) {
+ results.push({ name : statusMaps[i].nickname, id : ids[i] ,
+ ip : statusMaps[i].IP , country : countries[i] });
+ }
+ onResult(results);
+ });
+ });
+};
+
+// __nodeDataForCircuit(controller, circuitEvent, onResult)__.
+// Gets the information for a circuit.
+let nodeDataForCircuit = function (controller, circuitEvent, onResult) {
+ let ids = circuitEvent.circuit.map(circ => circ[0]);
+ nodeDataForID(controller, ids, onResult);
+};
+
+// __nodeLines(nodeData)__.
+// Takes a nodeData array of three items each like
+// `{ ip : "12.34.56.78", country : "fr" }`
+// and converts each node data to text, as
+// `"France (12.34.56.78)"`.
+let nodeLines = function (nodeData) {
+ let result = ["This browser"];
+ for (let {ip, country} of nodeData) {
+ result.push(localizedCountryNameFromCode(country) + " (" + ip + ")");
+ }
+ result.push("Internet");
+ return result;
+};
+
+// __updateCircuitDisplay()__.
+// Updates the Tor circuit display SVG, showing the current domain
+// and the relay nodes for that domain.
+let updateCircuitDisplay = function () {
+ let URI = gBrowser.selectedBrowser.currentURI,
+ domain = null,
+ nodeData = null;
+ // Try to get a domain for this URI. Otherwise it remains null.
+ try {
+ domain = URI.host;
+ } catch (e) { }
+ if (domain) {
+ // Check if we have anything to show for this domain.
+ nodeData = domainToNodeDataMap[domain];
+ if (nodeData) {
+ // Update the displayed domain.
+ document.querySelector("svg#tor-circuit text#domain").innerHTML = "(" + domain + "):";
+ // Update the displayed information for the relay nodes.
+ let diagramNodes = document.querySelectorAll("svg#tor-circuit text.node-text"),
+ lines = nodeLines(nodeData);
+ for (let i = 0; i < diagramNodes.length; ++i) {
+ diagramNodes[i].innerHTML = lines[i];
+ }
+ }
+ }
+ // Only show the Tor circuit if we have a domain and node data.
+ document.querySelector("svg#tor-circuit").style.display = (domain && nodeData) ?
+ 'block' : 'none';
+};
+
+// __collectBuiltCircuitData(aController)__.
+// Watches for CIRC BUILT events and records their data in the domainToNodeDataMap.
+let collectBuiltCircuitData = function (aController) {
+ aController.watchEvent(
+ "CIRC",
+ circuitEvent => circuitEvent.status === "EXTENDED" ||
+ circuitEvent.status === "BUILT",
+ function (circuitEvent) {
+ let domain = trimQuotes(circuitEvent.SOCKS_USERNAME);
+ if (domain) {
+ nodeDataForCircuit(aController, circuitEvent, function (nodeData) {
+ domainToNodeDataMap[domain] = nodeData;
+ updateCircuitDisplay();
+ });
+ } else {
+ updateCircuitDisplay();
+ }
+ });
+};
+
+// __syncDisplayWithSelectedTab()__.
+// We may have multiple tabs, but there is only one instance of TorButton's popup
+// panel for displaying the Tor circuit UI. Therefore we need to update the display
+// to show the currently selected tab at its current location.
+let syncDisplayWithSelectedTab = function () {
+ // Whenever a different tab is selected, change the circuit display
+ // to show the circuit for that tab's domain.
+ gBrowser.tabContainer.addEventListener("TabSelect", function (event) {
+ updateCircuitDisplay();
+ });
+ // If the currently selected tab has been sent to a new location,
+ // update the circuit to reflect that.
+ gBrowser.addTabsProgressListener({ onLocationChange : function (aBrowser) {
+ if (aBrowser == gBrowser.selectedBrowser) {
+ updateCircuitDisplay();
+ }
+ } });
+
+ // Get started with a correct display.
+ updateCircuitDisplay();
+};
+
+// __display(host, port, password)__.
+// The main function for activating automatic display of the Tor circuit.
+// A reference to this function (called runTorCircuitDisplay) is exported as a global.
+let display = function (host, port, password) {
+ let myController = controller(host, port || 9151, password, function (x) { logger.eclog(5, x); });
+ syncDisplayWithSelectedTab();
+ collectBuiltCircuitData(myController);
+};
+
+return display;
+
+// Finish runTorCircuitDisplay()
+})();
+
diff --git a/src/chrome/content/torbutton.js b/src/chrome/content/torbutton.js
index 7fddf07..5be2c6d 100644
--- a/src/chrome/content/torbutton.js
+++ b/src/chrome/content/torbutton.js
@@ -578,6 +578,8 @@ function torbutton_init() {
torbutton_update_statusbar(mode);
torbutton_notify_if_update_needed();
+ runTorCircuitDisplay(m_tb_control_host, m_tb_control_port, m_tb_control_pass);
+
torbutton_log(3, 'init completed');
}
diff --git a/src/chrome/content/torbutton.xul b/src/chrome/content/torbutton.xul
index 9e10b09..00dc6f0 100644
--- a/src/chrome/content/torbutton.xul
+++ b/src/chrome/content/torbutton.xul
@@ -11,6 +11,7 @@
<script src="chrome://torbutton/content/stanford-safecache.js" />
<script type="application/x-javascript" src="chrome://torbutton/content/torbutton_util.js" />
+ <script type="application/x-javascript" src="chrome://torbutton/content/tor-circuit-display.js" />
<script type="application/x-javascript" src="chrome://torbutton/content/torbutton.js" />
<script language="JavaScript">
//onLoad Hander
diff --git a/src/chrome/skin/torbutton.css b/src/chrome/skin/torbutton.css
index ef8abbc..f368c9c 100644
--- a/src/chrome/skin/torbutton.css
+++ b/src/chrome/skin/torbutton.css
@@ -104,3 +104,18 @@ statusbarpanel#plugins-status[status="0"] {
#torbutton-downloadUpdate {
font-weight: bold;
}
+
+svg.circuit text {
+ font-family: Arial;
+}
+
+svg#tor-circuit text.node-text {
+ dominant-baseline: central;
+ font-size: 14px;
+}
+
+svg#tor-circuit circle.node-circle {
+ stroke: #195021;
+ stroke-width: 2px;
+ fill: white;
+}
\ No newline at end of file
diff --git a/src/modules/tor-control-port.js b/src/modules/tor-control-port.js
new file mode 100644
index 0000000..2f993d7
--- /dev/null
+++ b/src/modules/tor-control-port.js
@@ -0,0 +1,575 @@
+// A module for TorBrowser that provides an asynchronous controller for
+// Tor, through its ControlPort.
+//
+// This file is written in call stack order (later functions
+// call earlier functions). The file can be processed
+// with docco.js to produce pretty documentation.
+//
+// To import the module, use
+//
+// let { controller } = Components.utils.import("path/to/controlPort.jsm");
+//
+// See the last function defined in this file, controller(host, port, password, onError)
+// for usage of the controller function.
+
+/* jshint esnext: true */
+/* jshint -W097 */
+/* global Components, console */
+"use strict";
+
+// ### Mozilla Abbreviations
+let {classes: Cc, interfaces: Ci, results: Cr, Constructor: CC, utils: Cu } = Components;
+
+// ## io
+// I/O utilities namespace
+let io = io || {};
+
+// __io.asyncSocketStreams(host, port)__.
+// Creates a pair of asynchronous input and output streams for a socket at the
+// given host and port.
+io.asyncSocketStreams = function (host, port) {
+ let socketTransportService = Cc["@mozilla.org/network/socket-transport-service;1"]
+ .getService(Components.interfaces.nsISocketTransportService),
+ BLOCKING = Ci.nsITransport.OPEN_BLOCKING,
+ UNBUFFERED = Ci.nsITransport.OPEN_UNBUFFERED,
+ // Create an instance of a socket transport.
+ socketTransport = socketTransportService.createTransport(null, 0, host, port, null),
+ // Open unbuffered synchronous outputStream.
+ outputStream = socketTransport.openOutputStream(BLOCKING | UNBUFFERED, 1, 1),
+ // Open unbuffered asynchronous inputStream.
+ inputStream = socketTransport.openInputStream(UNBUFFERED, 1, 1)
+ .QueryInterface(Ci.nsIAsyncInputStream);
+ return [inputStream, outputStream];
+};
+
+// __io.pumpInputStream(scriptableInputStream, onInputData, onError)__.
+// Run an "input stream pump" that takes an input stream and
+// asynchronously pumps incoming data to the onInputData callback.
+io.pumpInputStream = function (inputStream, onInputData, onError) {
+ // Wrap raw inputStream with a "ScriptableInputStream" so we can read incoming data.
+ let ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
+ "nsIScriptableInputStream", "init"),
+ scriptableInputStream = new ScriptableInputStream(inputStream),
+ // A private method to read all data available on the input stream.
+ readAll = function() {
+ return scriptableInputStream.read(scriptableInputStream.available());
+ },
+ pump = Cc["@mozilla.org/network/input-stream-pump;1"]
+ .createInstance(Components.interfaces.nsIInputStreamPump);
+ // Start the pump.
+ pump.init(inputStream, -1, -1, 0, 0, true);
+ // Tell the pump to read all data whenever it is available, and pass the data
+ // to the onInputData callback. The first argument to asyncRead implements
+ // nsIStreamListener.
+ pump.asyncRead({ onStartRequest: function (request, context) { },
+ onStopRequest: function (request, context, code) { },
+ onDataAvailable : function (request, context, stream, offset, count) {
+ try {
+ onInputData(readAll());
+ } catch (error) {
+ // readAll() or onInputData(...) has thrown an error.
+ // Notify calling code through onError.
+ onError(error);
+ }
+ } }, null);
+};
+
+// __io.asyncSocket(host, port, onInputData, onError)__.
+// Creates an asynchronous, text-oriented TCP socket at host:port.
+// The onInputData callback should accept a single argument, which will be called
+// repeatedly, whenever incoming text arrives. Returns a socket object with two methods:
+// socket.write(text) and socket.close(). onError will be passed the error object
+// whenever a write fails.
+io.asyncSocket = function (host, port, onInputData, onError) {
+ let [inputStream, outputStream] = io.asyncSocketStreams(host, port);
+ // Run an input stream pump to send incoming data to the onInputData callback.
+ io.pumpInputStream(inputStream, onInputData, onError);
+ return {
+ // Write a message to the socket.
+ write : function(aString) {
+ try {
+ outputStream.write(aString, aString.length);
+ // console.log(aString);
+ } catch (err) {
+ // This write() method is not necessarily called by a callback,
+ // but we pass any thrown errors to onError to ensure the socket
+ // error handling uses a consistent single path.
+ onError(err);
+ }
+ },
+ // Close the socket.
+ close : function () {
+ // Close stream objects.
+ inputStream.close();
+ outputStream.close();
+ }
+ };
+};
+
+// __io.onDataFromOnLine(onLine)__.
+// Converts a callback that expects incoming individual lines of text to a callback that
+// expects incoming raw socket string data.
+io.onDataFromOnLine = function (onLine) {
+ // A private variable that stores the last unfinished line.
+ let pendingData = "";
+ // Return a callback to be passed to io.asyncSocket. First, splits data into lines of
+ // text. If the incoming data is not terminated by CRLF, then the last
+ // unfinished line will be stored in pendingData, to be prepended to the data in the
+ // next call to onData. The already complete lines of text are then passed in sequence
+ // to onLine.
+ return function (data) {
+ let totalData = pendingData + data,
+ lines = totalData.split("\r\n"),
+ n = lines.length;
+ pendingData = lines[n - 1];
+ // Call onLine for all completed lines.
+ lines.slice(0,-1).map(onLine);
+ };
+};
+
+// __io.onLineFromOnMessage(onMessage)__.
+// Converts a callback that expects incoming control port multiline message strings to a
+// callback that expects individual lines.
+io.onLineFromOnMessage = function (onMessage) {
+ // A private variable that stores the last unfinished line.
+ let pendingLines = [];
+ // Return a callback that expects individual lines.
+ return function (line) {
+ // Add to the list of pending lines.
+ pendingLines.push(line);
+ // If line is the last in a message, then pass on the full multiline message.
+ if (line.match(/^\d\d\d /) && (pendingLines.length == 1 ||
+ pendingLines[0].startsWith(line.substring(0,3)))) {
+ // Combine pending lines to form message.
+ let message = pendingLines.join("\r\n");
+ // Wipe pendingLines before we call onMessage, in case onMessage throws an error.
+ pendingLines = [];
+ // Pass multiline message to onMessage.
+ onMessage(message);
+ // console.log(message);
+ }
+ };
+};
+
+// __io.callbackDispatcher()__.
+// Returns [onString, dispatcher] where the latter is an object with two member functions:
+// dispatcher.addCallback(regex, callback), and dispatcher.removeCallback(callback).
+// Pass onString to another function that needs a callback with a single string argument.
+// Whenever dispatcher.onString receives a string, the dispatcher will check for any
+// regex matches and pass the string on to the corresponding callback(s).
+io.callbackDispatcher = function () {
+ let callbackPairs = [],
+ removeCallback = function (aCallback) {
+ callbackPairs = callbackPairs.filter(function ([regex, callback]) {
+ return callback !== aCallback;
+ });
+ },
+ addCallback = function (regex, callback) {
+ if (callback) {
+ callbackPairs.push([regex, callback]);
+ }
+ return function () { removeCallback(callback); };
+ },
+ onString = function (message) {
+ for (let [regex, callback] of callbackPairs) {
+ if (message.match(regex)) {
+ callback(message);
+ }
+ }
+ };
+ return [onString, {addCallback : addCallback, removeCallback : removeCallback}];
+};
+
+// __io.matchRepliesToCommands(asyncSend)__.
+// Takes asyncSend(message), an asynchronous send function, and returns two functions
+// sendCommand(command, replyCallback) and onReply(response). If we call sendCommand,
+// then when onReply is called, the corresponding replyCallback will be called.
+io.matchRepliesToCommands = function (asyncSend) {
+ let commandQueue = [],
+ sendCommand = function (command, replyCallback) {
+ commandQueue.push([command, replyCallback]);
+ asyncSend(command);
+ },
+ onReply = function (reply) {
+ let [command, replyCallback] = commandQueue.shift();
+ if (replyCallback) { replyCallback(reply); }
+ },
+ onFailure = function () {
+ commandQueue.shift();
+ };
+ return [sendCommand, onReply, onFailure];
+};
+
+// __io.controlSocket(host, port, password, onError)__.
+// Instantiates and returns a socket to a tor ControlPort at host:port,
+// authenticating with the given password. onError is called with an
+// error object as its single argument whenever an error occurs. Example:
+//
+// // Open the socket
+// let socket = controlSocket("127.0.0.1", 9151, "MyPassw0rd",
+// function (error) { console.log(error.message || error); });
+// // Send command and receive "250" reply or error message
+// socket.sendCommand(commandText, replyCallback);
+// // Register or deregister for "650" notifications
+// // that match regex
+// socket.addNotificationCallback(regex, callback);
+// socket.removeNotificationCallback(callback);
+// // Close the socket permanently
+// socket.close();
+io.controlSocket = function (host, port, password, onError) {
+ // Produce a callback dispatcher for Tor messages.
+ let [onMessage, mainDispatcher] = io.callbackDispatcher(),
+ // Open the socket and convert format to Tor messages.
+ socket = io.asyncSocket(host, port,
+ io.onDataFromOnLine(io.onLineFromOnMessage(onMessage)),
+ onError),
+ // Tor expects any commands to be terminated by CRLF.
+ writeLine = function (text) { socket.write(text + "\r\n"); },
+ // Ensure we return the correct reply for each sendCommand.
+ [sendCommand, onReply, onFailure] = io.matchRepliesToCommands(writeLine),
+ // Create a secondary callback dispatcher for Tor notification messages.
+ [onNotification, notificationDispatcher] = io.callbackDispatcher();
+ // Pass successful reply back to sendCommand callback.
+ mainDispatcher.addCallback(/^2\d\d/, onReply);
+ // Pass error message to sendCommand callback.
+ mainDispatcher.addCallback(/^[45]\d\d/, function (message) {
+ onFailure();
+ onError(new Error(message));
+ });
+ // Pass asynchronous notifications to notification dispatcher.
+ mainDispatcher.addCallback(/^650/, onNotification);
+ // Log in to control port.
+ sendCommand("authenticate " + (password || ""));
+ // Activate needed events.
+ sendCommand("setevents stream circ");
+ return { close : socket.close, sendCommand : sendCommand,
+ addNotificationCallback : notificationDispatcher.addCallback,
+ removeNotificationCallback : notificationDispatcher.removeCallback };
+};
+
+// ## utils
+// A namespace for utility functions
+let utils = utils || {};
+
+// __utils.identity(x)__.
+// Returns its argument unchanged.
+utils.identity = function (x) { return x; };
+
+// __utils.isString(x)__.
+// Returns true iff x is a string.
+utils.isString = function (x) {
+ return typeof(x) === 'string' || x instanceof String;
+};
+
+// __utils.capture(string, regex)__.
+// Takes a string and returns an array of capture items, where regex must have a single
+// capturing group and use the suffix /.../g to specify a global search.
+utils.capture = function (string, regex) {
+ let matches = [];
+ // Special trick to use string.replace for capturing multiple matches.
+ string.replace(regex, function (a, captured) {
+ matches.push(captured);
+ });
+ return matches;
+};
+
+// __utils.extractor(regex)__.
+// Returns a function that takes a string and returns an array of regex matches. The
+// regex must use the suffix /.../g to specify a global search.
+utils.extractor = function (regex) {
+ return function (text) {
+ return utils.capture(text, regex);
+ };
+};
+
+// __utils.splitLines(string)__.
+// Splits a string into an array of strings, each corresponding to a line.
+utils.splitLines = function (string) { return string.split(/\r?\n/); };
+
+// __utils.splitAtSpaces(string)__.
+// Splits a string into chunks between spaces. Does not split at spaces
+// inside pairs of quotation marks.
+utils.splitAtSpaces = utils.extractor(/((\S*?"(.*?)")+\S*|\S+)/g);
+
+// __utils.splitAtEquals(string)__.
+// Splits a string into chunks between equals. Does not split at equals
+// inside pairs of quotation marks.
+utils.splitAtEquals = utils.extractor(/(([^=]*?"(.*?)")+[^=]*|[^=]+)/g);
+
+// __utils.mergeObjects(arrayOfObjects)__.
+// Takes an array of objects like [{"a":"b"},{"c":"d"}] and merges to a single object.
+// Pure function.
+utils.mergeObjects = function (arrayOfObjects) {
+ let result = {};
+ for (let obj of arrayOfObjects) {
+ for (var key in obj) {
+ result[key] = obj[key];
+ }
+ }
+ return result;
+};
+
+// __utils.listMapData(parameterString, listNames)__.
+// Takes a list of parameters separated by spaces, of which the first several are
+// unnamed, and the remainder are named, in the form `NAME=VALUE`. Apply listNames
+// to the unnamed parameters, and combine them in a map with the named parameters.
+// Example: `40 FAILED 0 95.78.59.36:80 REASON=CANT_ATTACH`
+//
+// utils.listMapData("40 FAILED 0 95.78.59.36:80 REASON=CANT_ATTACH",
+// ["streamID", "event", "circuitID", "IP"])
+// // --> {"streamID" : "40", "event" : "FAILED", "circuitID" : "0",
+// // "address" : "95.78.59.36:80", "REASON" : "CANT_ATTACH"}"
+utils.listMapData = function (parameterString, listNames) {
+ // Split out the space-delimited parameters.
+ let parameters = utils.splitAtSpaces(parameterString),
+ dataMap = {};
+ // Assign listNames to the first n = listNames.length parameters.
+ for (let i = 0; i < listNames.length; ++i) {
+ dataMap[listNames[i]] = parameters[i];
+ }
+ // Read key-value pairs and copy these to the dataMap.
+ for (let i = listNames.length; i < parameters.length; ++i) {
+ let [key, value] = utils.splitAtEquals(parameters[i]);
+ if (key && value) {
+ dataMap[key] = value;
+ }
+ }
+ return dataMap;
+};
+
+// ## info
+// A namespace for functions related to tor's GETINFO command.
+let info = info || {};
+
+// __info.keyValueStringsFromMessage(messageText)__.
+// Takes a message (text) response to GETINFO and provides a series of key-value
+// strings, which are either multiline (with a `250+` prefix):
+//
+// 250+config/defaults=
+// AccountingMax "0 bytes"
+// AllowDotExit "0"
+// .
+//
+// or single-line (with a `250-` prefix):
+//
+// 250-version=0.2.6.0-alpha-dev (git-b408125288ad6943)
+info.keyValueStringsFromMessage = utils.extractor(/^(250\+[\s\S]+?^\.|250-.+?)$/gmi);
+
+// __info.applyPerLine(transformFunction)__.
+// Returns a function that splits text into lines,
+// and applies transformFunction to each line.
+info.applyPerLine = function (transformFunction) {
+ return function (text) {
+ return utils.splitLines(text.trim()).map(transformFunction);
+ };
+};
+
+// __info.routerStatusParser(valueString)__.
+// Parses a router status entry as, described in
+// https://gitweb.torproject.org/torspec.git/blob/HEAD:/dir-spec.txt
+// (search for "router status entry")
+info.routerStatusParser = function (valueString) {
+ let lines = utils.splitLines(valueString),
+ objects = [];
+ for (let line of lines) {
+ // Drop first character and grab data following it.
+ let myData = line.substring(2),
+ // Accumulate more maps with data, depending on the first character in the line.
+ dataFun = {
+ "r" : data => utils.listMapData(data, ["nickname", "identity", "digest",
+ "publicationDate", "publicationTime",
+ "IP", "ORPort", "DirPort"]) ,
+ "a" : data => ({ "IPv6" : data }) ,
+ "s" : data => ({ "statusFlags" : utils.splitAtSpaces(data) }) ,
+ "v" : data => ({ "version" : data }) ,
+ "w" : data => utils.listMapData(data, []) ,
+ "p" : data => ({ "portList" : data.split(",") }) ,
+ "m" : data => utils.listMapData(data, [])
+ }[line.charAt(0)];
+ if (dataFun !== undefined) {
+ objects.push(dataFun(myData));
+ }
+ }
+ return utils.mergeObjects(objects);
+};
+
+// __info.circuitStatusParser(line)__.
+// Parse the output of a circuit status line.
+info.circuitStatusParser = function (line) {
+ let data = utils.listMapData(line, ["id","status","circuit"]),
+ circuit = data.circuit;
+ // Parse out the individual circuit IDs and names.
+ if (circuit) {
+ data.circuit = circuit.split(",").map(function (x) {
+ return x.split(/~|=/);
+ });
+ }
+ return data;
+};
+
+// __info.streamStatusParser(line)__.
+// Parse the output of a stream status line.
+info.streamStatusParser = function (text) {
+ return utils.listMapData(text, ["StreamID", "StreamStatus",
+ "CircuitID", "Target"]);
+};
+
+// __info.parsers__.
+// A map of GETINFO keys to parsing function, which convert result strings to JavaScript
+// data.
+info.parsers = {
+ "version" : utils.identity,
+ "config-file" : utils.identity,
+ "config-defaults-file" : utils.identity,
+ "config-text" : utils.identity,
+ "ns/id/" : info.routerStatusParser,
+ "ns/name/" : info.routerStatusParser,
+ "ip-to-country/" : utils.identity,
+ "circuit-status" : info.applyPerLine(info.circuitStatusParser),
+ "stream-status" : info.applyPerLine(info.streamStatusParser)
+};
+
+// __info.getParser(key)__.
+// Takes a key and determines the parser function that should be used to
+// convert its corresponding valueString to JavaScript data.
+info.getParser = function(key) {
+ return info.parsers[key] ||
+ info.parsers[key.substring(0, key.lastIndexOf("/") + 1)] ||
+ "unknown";
+};
+
+// __info.stringToValue(string)__.
+// Converts a key-value string as from GETINFO to a value.
+info.stringToValue = function (string) {
+ // key should look something like `250+circuit-status=` or `250-circuit-status=...`
+ let key = string.match(/^250[\+-](.+?)=/mi)[1],
+ // matchResult finds a single-line result for `250-` or a multi-line one for `250+`.
+ matchResult = string.match(/250\-.+?=(.*?)$/mi) ||
+ string.match(/250\+.+?=([\s\S]*?)^\.$/mi),
+ // Retrieve the captured group (the text of the value in the key-value pair)
+ valueString = matchResult ? matchResult[1] : null;
+ // Return value where the latter has been parsed according to the key requested.
+ return info.getParser(key)(valueString);
+};
+
+// __info.getInfoMultiple(aControlSocket, keys, onData)__.
+// Sends GETINFO for an array of keys. Passes onData an array of their respective results,
+// in order.
+info.getInfoMultiple = function (aControlSocket, keys, onData) {
+ /*
+ if (!(keys instanceof Array)) {
+ throw new Error("keys argument should be an array");
+ }
+ if (!(onData instanceof Function)) {
+ throw new Error("onData argument should be a function");
+ }
+ let parsers = keys.map(info.getParser);
+ if (parsers.indexOf("unknown") !== -1) {
+ throw new Error("unknown key");
+ }
+ if (parsers.indexOf("not supported") !== -1) {
+ throw new Error("unsupported key");
+ }
+ */
+ aControlSocket.sendCommand("getinfo " + keys.join(" "), function (message) {
+ onData(info.keyValueStringsFromMessage(message).map(info.stringToValue));
+ });
+};
+
+// __info.getInfo(controlSocket, key, onValue)__.
+// Sends GETINFO for a single key. Passes onValue the value for that key.
+info.getInfo = function (aControlSocket, key, onValue) {
+ /*
+ if (!utils.isString(key)) {
+ throw new Error("key argument should be a string");
+ }
+ if (!(onValue instanceof Function)) {
+ throw new Error("onValue argument should be a function");
+ }
+ */
+ info.getInfoMultiple(aControlSocket, [key], function (data) {
+ onValue(data[0]);
+ });
+};
+
+// ## event
+// Handlers for events
+
+let event = event || {};
+
+// __event.parsers__.
+// A map of EVENT keys to parsing functions, which convert result strings to JavaScript
+// data.
+event.parsers = {
+ "stream" : info.streamStatusParser,
+ "circ" : info.circuitStatusParser
+};
+
+// __event.messageToData(type, message)__.
+// Extract the data from an event.
+event.messageToData = function (type, message) {
+ let dataText = message.match(/^650 \S+?\s(.*?)$/mi)[1];
+ return dataText ? event.parsers[type.toLowerCase()](dataText) : null;
+};
+
+// __event.watchEvent(controlSocket, type, filter, onData)__.
+// Watches for a particular type of event. If filter(data) returns true, the event's
+// data is pass to the onData callback.
+event.watchEvent = function (controlSocket, type, filter, onData) {
+ controlSocket.addNotificationCallback(new RegExp("^650." + type, "i"),
+ function (message) {
+ let data = event.messageToData(type, message);
+ if (filter === null || filter(data)) {
+ onData(data);
+ }
+ });
+};
+
+// ## tor
+// Things related to the main controller.
+let tor = tor || {};
+
+// __tor.controller(host, port, password, onError)__.
+// Creates a tor controller at the given host and port, with the given password.
+// onError returns asynchronously whenever a connection error occurs.
+tor.controller = function (host, port, password, onError) {
+ let socket = io.controlSocket(host, port, password, onError);
+ return { getInfo : function (key, log) { info.getInfo(socket, key, log); } ,
+ getInfoMultiple : function (keys, log) {
+ info.getInfoMultiple(socket, keys, log);
+ },
+ watchEvent : function (type, filter, onData) {
+ event.watchEvent(socket, type, filter, onData);
+ },
+ close : socket.close };
+};
+
+// __tor.controllerCache__.
+// A map from "host:port" to controller objects. Prevents redundant instantiation
+// of control sockets.
+tor.controllerCache = {};
+
+// ## Export
+
+// __controller(host, port, password, onError)__.
+// Instantiates and returns a controller object connected to a tor ControlPort
+// at host:port, authenticating with the given password, if the controller doesn't yet
+// exist. Otherwise returns the existing controller to the given host:port.
+// onError is called with an error object as its single argument whenever
+// an error occurs. Example:
+//
+// // Get the controller
+// let c = controller("127.0.0.1", 9151, "MyPassw0rd",
+// function (error) { console.log(error.message || error); });
+// // Send command and receive `250` reply or error message
+// c.getInfo("ip-to-country/16.16.16.16", console.log);
+// // Close the controller permanently
+// c.close();
+let controller = function (host, port, password, onError) {
+ let dest = host + ":" + port;
+ return (tor.controllerCache[dest] = tor.controllerCache[dest] ||
+ tor.controller(host, port, password, onError));
+};
+
+// Export the controller function for external use.
+var EXPORTED_SYMBOLS = ["controller"];
1
0
[tor-browser/tor-browser-31.2.0esr-4.5-1] Bug #3455.1: Allow proxy settings to be set per URL bar domain.
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit 08991021207bcc7c982fa5ae5a9984a12ec7bf5f
Author: Arthur Edelstein <arthuredelstein(a)gmail.com>
Date: Tue Oct 21 02:15:25 2014 -0700
Bug #3455.1: Allow proxy settings to be set per URL bar domain.
---
dom/plugins/base/moz.build | 1 +
dom/plugins/base/nsPluginHost.cpp | 27 ++--
netwerk/base/public/nsIProtocolProxyCallback.idl | 10 +-
netwerk/base/public/nsIProtocolProxyFilter.idl | 34 ++++-
netwerk/base/public/nsIProtocolProxyService.idl | 32 +++-
netwerk/base/public/nsIProtocolProxyService2.idl | 13 +-
netwerk/base/src/nsIOService.cpp | 18 ++-
netwerk/base/src/nsPACMan.cpp | 9 +-
netwerk/base/src/nsPACMan.h | 10 +-
netwerk/base/src/nsProtocolProxyService.cpp | 157 +++++++++++++-------
netwerk/base/src/nsProtocolProxyService.h | 49 ++++--
netwerk/protocol/ftp/nsFtpConnectionThread.cpp | 11 +-
netwerk/protocol/http/HttpBaseChannel.cpp | 10 ++
netwerk/protocol/http/HttpBaseChannel.h | 1 +
netwerk/protocol/http/nsHttpChannel.cpp | 6 +-
netwerk/protocol/http/nsIHttpChannel.idl | 6 +
.../protocol/viewsource/nsViewSourceChannel.cpp | 6 +
netwerk/protocol/websocket/WebSocketChannel.cpp | 4 +-
18 files changed, 281 insertions(+), 123 deletions(-)
diff --git a/dom/plugins/base/moz.build b/dom/plugins/base/moz.build
index ded5fb5..25bae79 100644
--- a/dom/plugins/base/moz.build
+++ b/dom/plugins/base/moz.build
@@ -103,6 +103,7 @@ LOCAL_INCLUDES += [
'/gfx/skia/include/core',
'/layout/generic',
'/layout/xul',
+ '/netwerk/base/src',
'/widget/android',
'/widget/xpwidgets',
'/xpcom/base',
diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
index bc6bf72..1efe59f 100644
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -30,7 +30,7 @@
#include "nsIURL.h"
#include "nsTArray.h"
#include "nsReadableUtils.h"
-#include "nsIProtocolProxyService2.h"
+#include "nsProtocolProxyService.h"
#include "nsIStreamConverterService.h"
#include "nsIFile.h"
#if defined(XP_MACOSX)
@@ -583,32 +583,29 @@ nsresult nsPluginHost::FindProxyForURL(const char* url, char* *result)
}
nsresult res;
- nsCOMPtr<nsIURI> uriIn;
- nsCOMPtr<nsIProtocolProxyService> proxyService;
- nsCOMPtr<nsIProtocolProxyService2> proxyService2;
- nsCOMPtr<nsIIOService> ioService;
-
- proxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res);
+ nsCOMPtr<nsIProtocolProxyService> proxyService =
+ do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res);
if (NS_FAILED(res) || !proxyService)
return res;
- proxyService2 = do_QueryInterface(proxyService, &res);
- if (NS_FAILED(res) || !proxyService2)
- return res;
+ nsRefPtr<nsProtocolProxyService> rawProxyService = do_QueryObject(proxyService);
+ if (!rawProxyService)
+ return NS_ERROR_FAILURE;
- ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res);
+ nsCOMPtr<nsIIOService> ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res);
if (NS_FAILED(res) || !ioService)
return res;
- // make an nsURI from the argument url
- res = ioService->NewURI(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(uriIn));
+ // make a temporary channel from the argument url
+ nsCOMPtr<nsIChannel> tempChannel;
+ res = ioService->NewChannel(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(tempChannel));
if (NS_FAILED(res))
return res;
nsCOMPtr<nsIProxyInfo> pi;
- // Remove this with bug 778201
- res = proxyService2->DeprecatedBlockingResolve(uriIn, 0, getter_AddRefs(pi));
+ // Remove this deprecated call in the future (see Bug 778201):
+ res = rawProxyService->DeprecatedBlockingResolve(tempChannel, 0, getter_AddRefs(pi));
if (NS_FAILED(res))
return res;
diff --git a/netwerk/base/public/nsIProtocolProxyCallback.idl b/netwerk/base/public/nsIProtocolProxyCallback.idl
index ca1ab51..96c2181 100644
--- a/netwerk/base/public/nsIProtocolProxyCallback.idl
+++ b/netwerk/base/public/nsIProtocolProxyCallback.idl
@@ -6,7 +6,7 @@
#include "nsISupports.idl"
-interface nsIURI;
+interface nsIChannel;
interface nsIProxyInfo;
interface nsICancelable;
@@ -14,7 +14,7 @@ interface nsICancelable;
* This interface serves as a closure for nsIProtocolProxyService's
* asyncResolve method.
*/
-[scriptable, uuid(a9967200-f95e-45c2-beb3-9b060d874bfd)]
+[scriptable, uuid(fbb6eff6-0cc2-4d99-8d6f-0a12b462bdeb)]
interface nsIProtocolProxyCallback : nsISupports
{
/**
@@ -23,8 +23,8 @@ interface nsIProtocolProxyCallback : nsISupports
*
* @param aRequest
* The value returned from asyncResolve.
- * @param aURI
- * The URI passed to asyncResolve.
+ * @param aChannel
+ * The channel passed to asyncResolve.
* @param aProxyInfo
* The resulting proxy info or null if there is no associated proxy
* info for aURI. As with the result of nsIProtocolProxyService's
@@ -36,7 +36,7 @@ interface nsIProtocolProxyCallback : nsISupports
* indicates the reason for the failure and aProxyInfo will be null.
*/
void onProxyAvailable(in nsICancelable aRequest,
- in nsIURI aURI,
+ in nsIChannel aChannel,
in nsIProxyInfo aProxyInfo,
in nsresult aStatus);
};
diff --git a/netwerk/base/public/nsIProtocolProxyFilter.idl b/netwerk/base/public/nsIProtocolProxyFilter.idl
index 8ad6ca4..8798a49 100644
--- a/netwerk/base/public/nsIProtocolProxyFilter.idl
+++ b/netwerk/base/public/nsIProtocolProxyFilter.idl
@@ -6,6 +6,7 @@
#include "nsISupports.idl"
+interface nsIChannel;
interface nsIProtocolProxyService;
interface nsIProxyInfo;
interface nsIURI;
@@ -13,7 +14,7 @@ interface nsIURI;
/**
* This interface is used to apply filters to the proxies selected for a given
* URI. Use nsIProtocolProxyService::registerFilter to hook up instances of
- * this interface.
+ * this interface. See also nsIProtocolProxyChannelFilter.
*/
[scriptable, uuid(f424abd3-32b4-456c-9f45-b7e3376cb0d1)]
interface nsIProtocolProxyFilter : nsISupports
@@ -40,3 +41,34 @@ interface nsIProtocolProxyFilter : nsISupports
nsIProxyInfo applyFilter(in nsIProtocolProxyService aProxyService,
in nsIURI aURI, in nsIProxyInfo aProxy);
};
+
+/**
+ * This interface is used to apply filters to the proxies selected for a given
+ * channel. Use nsIProtocolProxyService::registerChannelFilter to hook up instances of
+ * this interface. See also nsIProtocolProxyFilter.
+ */
+[scriptable, uuid(245b0880-82c5-4e6e-be6d-bc586aa55a90)]
+interface nsIProtocolProxyChannelFilter : nsISupports
+{
+ /**
+ * This method is called to apply proxy filter rules for the given channel
+ * and proxy object (or list of proxy objects).
+ *
+ * @param aProxyService
+ * A reference to the Protocol Proxy Service. This is passed so that
+ * implementations may easily access methods such as newProxyInfo.
+ * @param aChannel
+ * The channel for which these proxy settings apply.
+ * @param aProxy
+ * The proxy (or list of proxies) that would be used by default for
+ * the given channel. This may be null.
+ *
+ * @return The proxy (or list of proxies) that should be used in place of
+ * aProxy. This can be just be aProxy if the filter chooses not to
+ * modify the proxy. It can also be null to indicate that a direct
+ * connection should be used. Use aProxyService.newProxyInfo to
+ * construct nsIProxyInfo objects.
+ */
+ nsIProxyInfo applyFilter(in nsIProtocolProxyService aProxyService,
+ in nsIChannel aChannel, in nsIProxyInfo aProxy);
+};
diff --git a/netwerk/base/public/nsIProtocolProxyService.idl b/netwerk/base/public/nsIProtocolProxyService.idl
index 526eab8..9365658 100644
--- a/netwerk/base/public/nsIProtocolProxyService.idl
+++ b/netwerk/base/public/nsIProtocolProxyService.idl
@@ -9,6 +9,7 @@
interface nsICancelable;
interface nsIProtocolProxyCallback;
interface nsIProtocolProxyFilter;
+interface nsIProtocolProxyChannelFilter;
interface nsIProxyInfo;
interface nsIChannel;
interface nsIURI;
@@ -17,7 +18,7 @@ interface nsIURI;
* nsIProtocolProxyService provides methods to access information about
* various network proxies.
*/
-[scriptable, uuid(e77c642b-026f-41ce-9b23-f829a6e3f300)]
+[scriptable, uuid(ab363090-c331-489f-aabb-7fe4481795b8)]
interface nsIProtocolProxyService : nsISupports
{
/** Flag 1 << 0 is unused **/
@@ -64,11 +65,11 @@ interface nsIProtocolProxyService : nsISupports
/**
* This method returns via callback a nsIProxyInfo instance that identifies
- * a proxy to be used for loading the given URI. Otherwise, this method returns
+ * a proxy to be used for the given channel. Otherwise, this method returns
* null indicating that a direct connection should be used.
*
- * @param aURI
- * The URI to test.
+ * @param aChannel
+ * The channel for which a proxy is to be found.
* @param aFlags
* A bit-wise combination of the RESOLVE_ flags defined above. Pass
* 0 to specify the default behavior. Any additional bits that do
@@ -94,7 +95,7 @@ interface nsIProtocolProxyService : nsISupports
*
* @see nsIProxiedProtocolHandler::newProxiedChannel
*/
- nsICancelable asyncResolve(in nsIURI aURI, in unsigned long aFlags,
+ nsICancelable asyncResolve(in nsIChannel aChannel, in unsigned long aFlags,
in nsIProtocolProxyCallback aCallback);
/**
@@ -191,6 +192,18 @@ interface nsIProtocolProxyService : nsISupports
in unsigned long aPosition);
/**
+ * Similar to registerFilter, but accepts an nsIProtocolProxyChannelFilter,
+ * which selects proxies according to channel rather than URI.
+ *
+ * @param aFilter
+ * The nsIProtocolProxyChannelFilter instance to be registered.
+ * @param aPosition
+ * The position of the filter.
+ */
+ void registerChannelFilter(in nsIProtocolProxyChannelFilter aFilter,
+ in unsigned long aPosition);
+
+ /**
* This method may be used to unregister a proxy filter instance. All
* filters will be automatically unregistered at XPCOM shutdown.
*
@@ -199,6 +212,15 @@ interface nsIProtocolProxyService : nsISupports
*/
void unregisterFilter(in nsIProtocolProxyFilter aFilter);
+ /**
+ * This method may be used to unregister a proxy channel filter instance. All
+ * filters will be automatically unregistered at XPCOM shutdown.
+ *
+ * @param aFilter
+ * The nsIProtocolProxyChannelFilter instance to be unregistered.
+ */
+ void unregisterChannelFilter(in nsIProtocolProxyChannelFilter aFilter);
+
/**
* These values correspond to the possible integer values for the
* network.proxy.type preference.
diff --git a/netwerk/base/public/nsIProtocolProxyService2.idl b/netwerk/base/public/nsIProtocolProxyService2.idl
index cb39a33..9e4f548 100644
--- a/netwerk/base/public/nsIProtocolProxyService2.idl
+++ b/netwerk/base/public/nsIProtocolProxyService2.idl
@@ -9,7 +9,7 @@
/**
* An extension of nsIProtocolProxyService
*/
-[scriptable, uuid(bb52e571-4a0e-4363-83d0-52034910dd14)]
+[scriptable, uuid(b2e5b2c0-e21e-4845-b336-be6d60a38951)]
interface nsIProtocolProxyService2 : nsIProtocolProxyService
{
/**
@@ -18,21 +18,12 @@ interface nsIProtocolProxyService2 : nsIProtocolProxyService
*/
void reloadPAC();
- /**
- * This exists so Java(tm) can migrate to an asynchronous interface.
- * Do not use this unless you are the plugin interface, and even then you
- * ought to feel horribly guilty because you will create main thread jank.
- *
- * No documentation - it is deprecated!
- **/
- nsIProxyInfo deprecatedBlockingResolve(in nsIURI aURI, in unsigned long aFlags);
-
/**
* This method is identical to asyncResolve() except it may execute the
* callback function immediately (i.e from the stack of asyncResolve2()) if
* it is immediately ready to run. The nsICancelable return value will be
* null in that case.
*/
- nsICancelable asyncResolve2(in nsIURI aURI, in unsigned long aFlags,
+ nsICancelable asyncResolve2(in nsIChannel aChannel, in unsigned long aFlags,
in nsIProtocolProxyCallback aCallback);
};
diff --git a/netwerk/base/src/nsIOService.cpp b/netwerk/base/src/nsIOService.cpp
index b64e7d3..99efa57 100644
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -1197,7 +1197,7 @@ private:
NS_IMPL_ISUPPORTS(IOServiceProxyCallback, nsIProtocolProxyCallback)
NS_IMETHODIMP
-IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI,
+IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIChannel *channel,
nsIProxyInfo *pi, nsresult status)
{
// Checking proxy status for speculative connect
@@ -1209,8 +1209,13 @@ IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI,
return NS_OK;
}
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = channel->GetURI(getter_AddRefs(uri));
+ if (NS_FAILED(rv))
+ return NS_OK;
+
nsAutoCString scheme;
- nsresult rv = aURI->GetScheme(scheme);
+ rv = uri->GetScheme(scheme);
if (NS_FAILED(rv))
return NS_OK;
@@ -1225,7 +1230,7 @@ IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI,
if (!speculativeHandler)
return NS_OK;
- speculativeHandler->SpeculativeConnect(aURI,
+ speculativeHandler->SpeculativeConnect(uri,
mCallbacks);
return NS_OK;
}
@@ -1243,8 +1248,13 @@ nsIOService::SpeculativeConnect(nsIURI *aURI,
if (NS_FAILED(rv))
return rv;
+ nsCOMPtr<nsIChannel> channel;
+ rv = NewChannelFromURI(aURI, getter_AddRefs(channel));
+ if (NS_FAILED(rv))
+ return rv;
+
nsCOMPtr<nsICancelable> cancelable;
nsRefPtr<IOServiceProxyCallback> callback =
new IOServiceProxyCallback(aCallbacks, this);
- return pps->AsyncResolve(aURI, 0, callback, getter_AddRefs(cancelable));
+ return pps->AsyncResolve(channel, 0, callback, getter_AddRefs(cancelable));
}
diff --git a/netwerk/base/src/nsPACMan.cpp b/netwerk/base/src/nsPACMan.cpp
index 81bc17e..e8b0b2d 100644
--- a/netwerk/base/src/nsPACMan.cpp
+++ b/netwerk/base/src/nsPACMan.cpp
@@ -320,8 +320,8 @@ nsPACMan::Shutdown()
}
nsresult
-nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback,
- bool mainThreadResponse)
+nsPACMan::AsyncGetProxyForChannel(nsIChannel *channel, nsPACManCallback *callback,
+ bool mainThreadResponse)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "wrong thread");
if (mShutdown)
@@ -332,6 +332,11 @@ nsPACMan::AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback,
TimeStamp::Now() > mScheduledReload)
LoadPACFromURI(EmptyCString());
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = channel->GetURI(getter_AddRefs(uri));
+ if (NS_FAILED(rv))
+ return rv;
+
nsRefPtr<PendingPACQuery> query =
new PendingPACQuery(this, uri, callback, mainThreadResponse);
diff --git a/netwerk/base/src/nsPACMan.h b/netwerk/base/src/nsPACMan.h
index 410ae5641..6f95d97 100644
--- a/netwerk/base/src/nsPACMan.h
+++ b/netwerk/base/src/nsPACMan.h
@@ -27,13 +27,13 @@ class nsIThread;
class WaitForThreadShutdown;
/**
- * This class defines a callback interface used by AsyncGetProxyForURI.
+ * This class defines a callback interface used by AsyncGetProxyForChannel.
*/
class NS_NO_VTABLE nsPACManCallback : public nsISupports
{
public:
/**
- * This method is invoked on the same thread that called AsyncGetProxyForURI.
+ * This method is invoked on the same thread that called AsyncGetProxyForChannel.
*
* @param status
* This parameter indicates whether or not the PAC query succeeded.
@@ -101,14 +101,14 @@ public:
* will queue up the request, and complete it once the PAC file has been
* loaded.
*
- * @param uri
- * The URI to query.
+ * @param channel
+ * The channel to query.
* @param callback
* The callback to run once the PAC result is available.
* @param mustCallbackOnMainThread
* If set to false the callback can be made from the PAC thread
*/
- nsresult AsyncGetProxyForURI(nsIURI *uri, nsPACManCallback *callback,
+ nsresult AsyncGetProxyForChannel(nsIChannel *channel, nsPACManCallback *callback,
bool mustCallbackOnMainThread);
/**
diff --git a/netwerk/base/src/nsProtocolProxyService.cpp b/netwerk/base/src/nsProtocolProxyService.cpp
index 98ea68b..3878c58d 100644
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -14,6 +14,7 @@
#include "nsIObserverService.h"
#include "nsIProtocolHandler.h"
#include "nsIProtocolProxyCallback.h"
+#include "nsIChannel.h"
#include "nsICancelable.h"
#include "nsIDNSService.h"
#include "nsPIDNSService.h"
@@ -67,7 +68,7 @@ struct nsProtocolInfo {
//----------------------------------------------------------------------------
// The nsPACManCallback portion of this implementation should be run
-// on the main thread - so call nsPACMan::AsyncGetProxyForURI() with
+// on the main thread - so call nsPACMan::AsyncGetProxyForChannel() with
// a true mainThreadResponse parameter.
class nsAsyncResolveRequest MOZ_FINAL : public nsIRunnable
, public nsPACManCallback
@@ -76,7 +77,7 @@ class nsAsyncResolveRequest MOZ_FINAL : public nsIRunnable
public:
NS_DECL_THREADSAFE_ISUPPORTS
- nsAsyncResolveRequest(nsProtocolProxyService *pps, nsIURI *uri,
+ nsAsyncResolveRequest(nsProtocolProxyService *pps, nsIChannel *channel,
uint32_t aResolveFlags,
nsIProtocolProxyCallback *callback)
: mStatus(NS_OK)
@@ -84,7 +85,7 @@ public:
, mResolveFlags(aResolveFlags)
, mPPS(pps)
, mXPComPPS(pps)
- , mURI(uri)
+ , mChannel(channel)
, mCallback(callback)
{
NS_ASSERTION(mCallback, "null callback");
@@ -100,9 +101,9 @@ public:
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
- if (mURI) {
- nsIURI *forgettable;
- mURI.forget(&forgettable);
+ if (mChannel) {
+ nsIChannel *forgettable;
+ mChannel.forget(&forgettable);
NS_ProxyRelease(mainThread, forgettable, false);
}
@@ -207,19 +208,21 @@ private:
if (NS_SUCCEEDED(mStatus) && !mProxyInfo && !mPACString.IsEmpty()) {
mPPS->ProcessPACString(mPACString, mResolveFlags,
getter_AddRefs(mProxyInfo));
+ nsCOMPtr<nsIURI> uri;
+ mChannel->GetURI(getter_AddRefs(uri));
// Now apply proxy filters
nsProtocolInfo info;
- mStatus = mPPS->GetProtocolInfo(mURI, &info);
+ mStatus = mPPS->GetProtocolInfo(uri, &info);
if (NS_SUCCEEDED(mStatus))
- mPPS->ApplyFilters(mURI, info, mProxyInfo);
+ mPPS->ApplyFilters(mChannel, info, mProxyInfo);
else
mProxyInfo = nullptr;
LOG(("pac thread callback %s\n", mPACString.get()));
if (NS_SUCCEEDED(mStatus))
mPPS->MaybeDisableDNSPrefetch(mProxyInfo);
- mCallback->OnProxyAvailable(this, mURI, mProxyInfo, mStatus);
+ mCallback->OnProxyAvailable(this, mChannel, mProxyInfo, mStatus);
}
else if (NS_SUCCEEDED(mStatus) && !mPACURL.IsEmpty()) {
LOG(("pac thread callback indicates new pac file load\n"));
@@ -229,12 +232,12 @@ private:
if (NS_SUCCEEDED(rv)) {
// now that the load is triggered, we can resubmit the query
nsRefPtr<nsAsyncResolveRequest> newRequest =
- new nsAsyncResolveRequest(mPPS, mURI, mResolveFlags, mCallback);
- rv = mPPS->mPACMan->AsyncGetProxyForURI(mURI, newRequest, true);
+ new nsAsyncResolveRequest(mPPS, mChannel, mResolveFlags, mCallback);
+ rv = mPPS->mPACMan->AsyncGetProxyForChannel(mChannel, newRequest, true);
}
if (NS_FAILED(rv))
- mCallback->OnProxyAvailable(this, mURI, nullptr, rv);
+ mCallback->OnProxyAvailable(this, mChannel, nullptr, rv);
// do not call onproxyavailable() in SUCCESS case - the newRequest will
// take care of that
@@ -243,7 +246,7 @@ private:
LOG(("pac thread callback did not provide information %X\n", mStatus));
if (NS_SUCCEEDED(mStatus))
mPPS->MaybeDisableDNSPrefetch(mProxyInfo);
- mCallback->OnProxyAvailable(this, mURI, mProxyInfo, mStatus);
+ mCallback->OnProxyAvailable(this, mChannel, mProxyInfo, mStatus);
}
// We are on the main thread now and don't need these any more so
@@ -252,7 +255,7 @@ private:
mCallback = nullptr; // in case the callback holds an owning ref to us
mPPS = nullptr;
mXPComPPS = nullptr;
- mURI = nullptr;
+ mChannel = nullptr;
mProxyInfo = nullptr;
}
@@ -266,7 +269,7 @@ private:
nsProtocolProxyService *mPPS;
nsCOMPtr<nsIProtocolProxyService> mXPComPPS;
- nsCOMPtr<nsIURI> mURI;
+ nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIProtocolProxyCallback> mCallback;
nsCOMPtr<nsIProxyInfo> mProxyInfo;
};
@@ -964,7 +967,7 @@ nsProtocolProxyService::ReloadPAC()
// The nsPACManCallback portion of this implementation should be run
// off the main thread, because it uses a condvar for signaling and
// the main thread is blocking on that condvar -
-// so call nsPACMan::AsyncGetProxyForURI() with
+// so call nsPACMan::AsyncGetProxyForChannel() with
// a false mainThreadResponse parameter.
class nsAsyncBridgeRequest MOZ_FINAL : public nsPACManCallback
{
@@ -1010,16 +1013,19 @@ private:
};
NS_IMPL_ISUPPORTS0(nsAsyncBridgeRequest)
-// nsIProtocolProxyService2
+// nsProtocolProxyService
NS_IMETHODIMP
-nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI,
+nsProtocolProxyService::DeprecatedBlockingResolve(nsIChannel *aChannel,
uint32_t aFlags,
nsIProxyInfo **retval)
{
- NS_ENSURE_ARG_POINTER(aURI);
+ NS_ENSURE_ARG_POINTER(aChannel);
+
+ nsCOMPtr<nsIURI> uri;
+ aChannel->GetURI(getter_AddRefs(uri));
nsProtocolInfo info;
- nsresult rv = GetProtocolInfo(aURI, &info);
+ nsresult rv = GetProtocolInfo(uri, &info);
if (NS_FAILED(rv))
return rv;
@@ -1030,12 +1036,12 @@ nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI,
// but if neither of them are in use, we can just do the work
// right here and directly invoke the callback
- rv = Resolve_Internal(aURI, info, aFlags, &usePACThread, getter_AddRefs(pi));
+ rv = Resolve_Internal(aChannel, info, aFlags, &usePACThread, getter_AddRefs(pi));
if (NS_FAILED(rv))
return rv;
if (!usePACThread || !mPACMan) {
- ApplyFilters(aURI, info, pi);
+ ApplyFilters(aChannel, info, pi);
pi.forget(retval);
return NS_OK;
}
@@ -1044,7 +1050,7 @@ nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI,
// code, but block this thread on that completion.
nsRefPtr<nsAsyncBridgeRequest> ctx = new nsAsyncBridgeRequest();
ctx->Lock();
- if (NS_SUCCEEDED(mPACMan->AsyncGetProxyForURI(aURI, ctx, false))) {
+ if (NS_SUCCEEDED(mPACMan->AsyncGetProxyForChannel(aChannel, ctx, false))) {
// this can really block the main thread, so cap it at 3 seconds
ctx->Wait();
}
@@ -1060,7 +1066,7 @@ nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI,
if (!ctx->mPACString.IsEmpty()) {
LOG(("sync pac thread callback %s\n", ctx->mPACString.get()));
ProcessPACString(ctx->mPACString, 0, getter_AddRefs(pi));
- ApplyFilters(aURI, info, pi);
+ ApplyFilters(aChannel, info, pi);
pi.forget(retval);
return NS_OK;
}
@@ -1084,17 +1090,20 @@ nsProtocolProxyService::DeprecatedBlockingResolve(nsIURI *aURI,
}
nsresult
-nsProtocolProxyService::AsyncResolveInternal(nsIURI *uri, uint32_t flags,
+nsProtocolProxyService::AsyncResolveInternal(nsIChannel *channel, uint32_t flags,
nsIProtocolProxyCallback *callback,
nsICancelable **result,
bool isSyncOK)
{
- NS_ENSURE_ARG_POINTER(uri);
+ NS_ENSURE_ARG_POINTER(channel);
NS_ENSURE_ARG_POINTER(callback);
+ nsCOMPtr<nsIURI> uri;
+ channel->GetURI(getter_AddRefs(uri));
+
*result = nullptr;
nsRefPtr<nsAsyncResolveRequest> ctx =
- new nsAsyncResolveRequest(this, uri, flags, callback);
+ new nsAsyncResolveRequest(this, channel, flags, callback);
nsProtocolInfo info;
nsresult rv = GetProtocolInfo(uri, &info);
@@ -1108,13 +1117,13 @@ nsProtocolProxyService::AsyncResolveInternal(nsIURI *uri, uint32_t flags,
// but if neither of them are in use, we can just do the work
// right here and directly invoke the callback
- rv = Resolve_Internal(uri, info, flags, &usePACThread, getter_AddRefs(pi));
+ rv = Resolve_Internal(channel, info, flags, &usePACThread, getter_AddRefs(pi));
if (NS_FAILED(rv))
return rv;
if (!usePACThread || !mPACMan) {
// we can do it locally
- ApplyFilters(uri, info, pi);
+ ApplyFilters(channel, info, pi);
ctx->SetResult(NS_OK, pi);
if (isSyncOK) {
ctx->Run();
@@ -1129,7 +1138,7 @@ nsProtocolProxyService::AsyncResolveInternal(nsIURI *uri, uint32_t flags,
// else kick off a PAC thread query
- rv = mPACMan->AsyncGetProxyForURI(uri, ctx, true);
+ rv = mPACMan->AsyncGetProxyForChannel(channel, ctx, true);
if (NS_SUCCEEDED(rv))
ctx.forget(result);
return rv;
@@ -1137,19 +1146,19 @@ nsProtocolProxyService::AsyncResolveInternal(nsIURI *uri, uint32_t flags,
// nsIProtocolProxyService
NS_IMETHODIMP
-nsProtocolProxyService::AsyncResolve2(nsIURI *uri, uint32_t flags,
+nsProtocolProxyService::AsyncResolve2(nsIChannel *channel, uint32_t flags,
nsIProtocolProxyCallback *callback,
nsICancelable **result)
{
- return AsyncResolveInternal(uri, flags, callback, result, true);
+ return AsyncResolveInternal(channel, flags, callback, result, true);
}
NS_IMETHODIMP
-nsProtocolProxyService::AsyncResolve(nsIURI *uri, uint32_t flags,
+nsProtocolProxyService::AsyncResolve(nsIChannel *channel, uint32_t flags,
nsIProtocolProxyCallback *callback,
nsICancelable **result)
{
- return AsyncResolveInternal(uri, flags, callback, result, false);
+ return AsyncResolveInternal(channel, flags, callback, result, false);
}
NS_IMETHODIMP
@@ -1221,16 +1230,9 @@ nsProtocolProxyService::GetFailoverForProxy(nsIProxyInfo *aProxy,
return NS_OK;
}
-NS_IMETHODIMP
-nsProtocolProxyService::RegisterFilter(nsIProtocolProxyFilter *filter,
- uint32_t position)
+nsresult
+nsProtocolProxyService::InsertFilterLink(FilterLink *link, uint32_t position)
{
- UnregisterFilter(filter); // remove this filter if we already have it
-
- FilterLink *link = new FilterLink(position, filter);
- if (!link)
- return NS_ERROR_OUT_OF_MEMORY;
-
if (!mFilters) {
mFilters = link;
return NS_OK;
@@ -1258,11 +1260,32 @@ nsProtocolProxyService::RegisterFilter(nsIProtocolProxyFilter *filter,
}
NS_IMETHODIMP
-nsProtocolProxyService::UnregisterFilter(nsIProtocolProxyFilter *filter)
+nsProtocolProxyService::RegisterFilter(nsIProtocolProxyFilter *filter,
+ uint32_t position)
{
- // QI to nsISupports so we can safely test object identity.
- nsCOMPtr<nsISupports> givenObject = do_QueryInterface(filter);
+ UnregisterFilter(filter); // remove this filter if we already have it
+
+ FilterLink *link = new FilterLink(position, filter);
+ if (!link)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return InsertFilterLink(link, position);
+}
+NS_IMETHODIMP
+nsProtocolProxyService::RegisterChannelFilter(nsIProtocolProxyChannelFilter *channelFilter,
+ uint32_t position)
+{
+ UnregisterChannelFilter(channelFilter); // remove this filter if we already have it
+
+ FilterLink *link = new FilterLink(position, channelFilter);
+ if (!link)
+ return NS_ERROR_OUT_OF_MEMORY;
+ return InsertFilterLink(link, position);
+}
+
+nsresult
+nsProtocolProxyService::RemoveFilterLink(nsISupports* givenObject)
+{
FilterLink *last = nullptr;
for (FilterLink *iter = mFilters; iter; iter = iter->next) {
nsCOMPtr<nsISupports> object = do_QueryInterface(iter->filter);
@@ -1283,6 +1306,20 @@ nsProtocolProxyService::UnregisterFilter(nsIProtocolProxyFilter *filter)
}
NS_IMETHODIMP
+nsProtocolProxyService::UnregisterFilter(nsIProtocolProxyFilter *filter) {
+ // QI to nsISupports so we can safely test object identity.
+ nsCOMPtr<nsISupports> givenObject = do_QueryInterface(filter);
+ return RemoveFilterLink(givenObject);
+}
+
+NS_IMETHODIMP
+nsProtocolProxyService::UnregisterChannelFilter(nsIProtocolProxyChannelFilter *channelFilter) {
+ // QI to nsISupports so we can safely test object identity.
+ nsCOMPtr<nsISupports> givenObject = do_QueryInterface(channelFilter);
+ return RemoveFilterLink(givenObject);
+}
+
+NS_IMETHODIMP
nsProtocolProxyService::GetProxyConfigType(uint32_t* aProxyConfigType)
{
*aProxyConfigType = mProxyConfig;
@@ -1489,13 +1526,13 @@ nsProtocolProxyService::NewProxyInfo_Internal(const char *aType,
}
nsresult
-nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
+nsProtocolProxyService::Resolve_Internal(nsIChannel *channel,
const nsProtocolInfo &info,
uint32_t flags,
bool *usePACThread,
nsIProxyInfo **result)
{
- NS_ENSURE_ARG_POINTER(uri);
+ NS_ENSURE_ARG_POINTER(channel);
nsresult rv = SetupPACThread();
if (NS_FAILED(rv))
return rv;
@@ -1506,6 +1543,9 @@ nsProtocolProxyService::Resolve_Internal(nsIURI *uri,
if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
return NS_OK; // Can't proxy this (filters may not override)
+ nsCOMPtr<nsIURI> uri;
+ channel->GetURI(getter_AddRefs(uri));
+
// See bug #586908.
// Avoid endless loop if |uri| is the current PAC-URI. Returning OK
// here means that we will not use a proxy for this connection.
@@ -1675,7 +1715,7 @@ nsProtocolProxyService::MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy)
}
void
-nsProtocolProxyService::ApplyFilters(nsIURI *uri, const nsProtocolInfo &info,
+nsProtocolProxyService::ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info,
nsIProxyInfo **list)
{
if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
@@ -1690,9 +1730,22 @@ nsProtocolProxyService::ApplyFilters(nsIURI *uri, const nsProtocolInfo &info,
for (FilterLink *iter = mFilters; iter; iter = iter->next) {
PruneProxyInfo(info, list);
-
- rv = iter->filter->ApplyFilter(this, uri, *list,
- getter_AddRefs(result));
+ if (!!iter->filter) {
+ nsCOMPtr<nsIURI> uri;
+ channel->GetURI(getter_AddRefs(uri));
+ if (!!uri) {
+ nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
+ nsCOMPtr<nsIURI> proxyURI = nullptr;
+ if (!!httpChannel) {
+ httpChannel->GetProxyURI(getter_AddRefs(proxyURI));
+ }
+ rv = iter->filter->ApplyFilter(this, proxyURI ? proxyURI : uri, *list,
+ getter_AddRefs(result));
+ }
+ } else if (!!iter->channelFilter) {
+ rv = iter->channelFilter->ApplyFilter(this, channel, *list,
+ getter_AddRefs(result));
+ }
if (NS_FAILED(rv))
continue;
result.swap(*list);
diff --git a/netwerk/base/src/nsProtocolProxyService.h b/netwerk/base/src/nsProtocolProxyService.h
index 4108e30..9ef68b9 100644
--- a/netwerk/base/src/nsProtocolProxyService.h
+++ b/netwerk/base/src/nsProtocolProxyService.h
@@ -27,6 +27,12 @@ class nsIPrefBranch;
class nsISystemProxySettings;
class nsPACMan;
+// CID for the nsProtocolProxyService class
+// 091eedd8-8bae-4fe3-ad62-0c87351e640d
+#define NS_PROTOCOL_PROXY_SERVICE_IMPL_CID \
+{ 0x091eedd8, 0x8bae, 0x4fe3, \
+ { 0xad, 0x62, 0x0c, 0x87, 0x35, 0x1e, 0x64, 0x0d } }
+
class nsProtocolProxyService MOZ_FINAL : public nsIProtocolProxyService2
, public nsIObserver
{
@@ -36,9 +42,14 @@ public:
NS_DECL_NSIPROTOCOLPROXYSERVICE
NS_DECL_NSIOBSERVER
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)
+
nsProtocolProxyService() NS_HIDDEN;
NS_HIDDEN_(nsresult) Init();
+ nsresult DeprecatedBlockingResolve(nsIChannel *aChannel,
+ uint32_t aFlags,
+ nsIProxyInfo **retval);
protected:
friend class nsAsyncResolveRequest;
@@ -192,8 +203,8 @@ protected:
* caller with either the proxy info result or a flag to instruct the
* caller to use PAC instead.
*
- * @param uri
- * The URI to test.
+ * @param channel
+ * The channel to test.
* @param info
* Information about the URI's protocol.
* @param flags
@@ -204,7 +215,7 @@ protected:
* @param result
* The resulting proxy info or null.
*/
- NS_HIDDEN_(nsresult) Resolve_Internal(nsIURI *uri,
+ NS_HIDDEN_(nsresult) Resolve_Internal(nsIChannel *channel,
const nsProtocolInfo &info,
uint32_t flags,
bool *usePAC,
@@ -214,26 +225,26 @@ protected:
* This method applies the registered filters to the given proxy info
* list, and returns a possibly modified list.
*
- * @param uri
- * The URI corresponding to this proxy info list.
+ * @param channel
+ * The channel corresponding to this proxy info list.
* @param info
* Information about the URI's protocol.
* @param proxyInfo
* The proxy info list to be modified. This is an inout param.
*/
- NS_HIDDEN_(void) ApplyFilters(nsIURI *uri, const nsProtocolInfo &info,
+ NS_HIDDEN_(void) ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info,
nsIProxyInfo **proxyInfo);
/**
* This method is a simple wrapper around ApplyFilters that takes the
* proxy info list inout param as a nsCOMPtr.
*/
- inline void ApplyFilters(nsIURI *uri, const nsProtocolInfo &info,
+ inline void ApplyFilters(nsIChannel *channel, const nsProtocolInfo &info,
nsCOMPtr<nsIProxyInfo> &proxyInfo)
{
nsIProxyInfo *pi = nullptr;
proxyInfo.swap(pi);
- ApplyFilters(uri, info, &pi);
+ ApplyFilters(channel, info, &pi);
proxyInfo.swap(pi);
}
@@ -317,19 +328,27 @@ protected:
}
};
- // This structure is allocated for each registered nsIProtocolProxyFilter.
+ // An instance of this struct is allocated for each registered
+ // nsIProtocolProxyFilter and each nsIProtocolProxyChannelFilter.
struct FilterLink {
struct FilterLink *next;
uint32_t position;
- nsCOMPtr<nsIProtocolProxyFilter> filter;
-
+ nsCOMPtr<nsIProtocolProxyFilter> filter;
+ nsCOMPtr<nsIProtocolProxyChannelFilter> channelFilter;
FilterLink(uint32_t p, nsIProtocolProxyFilter *f)
- : next(nullptr), position(p), filter(f) {}
-
+ : next(nullptr), position(p), filter(f), channelFilter(nullptr) {}
+ FilterLink(uint32_t p, nsIProtocolProxyChannelFilter *cf)
+ : next(nullptr), position(p), filter(nullptr), channelFilter(cf) {}
// Chain deletion to simplify cleaning up the filter links
~FilterLink() { if (next) delete next; }
};
+private:
+ // Private methods to insert and remove FilterLinks from the FilterLink chain.
+ nsresult InsertFilterLink(FilterLink *link, uint32_t position);
+ nsresult RemoveFilterLink(nsISupports *givenObject);
+
+protected:
// Indicates if local hosts (plain hostnames, no dots) should use the proxy
bool mFilterLocalHosts;
@@ -364,11 +383,13 @@ protected:
int32_t mFailedProxyTimeout;
private:
- nsresult AsyncResolveInternal(nsIURI *uri, uint32_t flags,
+ nsresult AsyncResolveInternal(nsIChannel *channel, uint32_t flags,
nsIProtocolProxyCallback *callback,
nsICancelable **result,
bool isSyncOK);
};
+NS_DEFINE_STATIC_IID_ACCESSOR(nsProtocolProxyService, NS_PROTOCOL_PROXY_SERVICE_IMPL_CID)
+
#endif // !nsProtocolProxyService_h__
diff --git a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
index 6d8d9f1..5073dbb 100644
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -1872,7 +1872,7 @@ nsFtpState::Init(nsFtpChannel *channel)
do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
if (pps && !mChannel->ProxyInfo()) {
- pps->AsyncResolve(mChannel->URI(), 0, this,
+ pps->AsyncResolve(mChannel, 0, this,
getter_AddRefs(mProxyRequest));
}
@@ -2358,7 +2358,7 @@ nsFtpState::CloseWithStatus(nsresult status)
}
static nsresult
-CreateHTTPProxiedChannel(nsIURI *uri, nsIProxyInfo *pi, nsIChannel **newChannel)
+CreateHTTPProxiedChannel(nsIChannel *channel, nsIProxyInfo *pi, nsIChannel **newChannel)
{
nsresult rv;
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
@@ -2374,11 +2374,14 @@ CreateHTTPProxiedChannel(nsIURI *uri, nsIProxyInfo *pi, nsIChannel **newChannel)
if (NS_FAILED(rv))
return rv;
+ nsCOMPtr<nsIURI> uri;
+ channel->GetURI(getter_AddRefs(uri));
+
return pph->NewProxiedChannel(uri, pi, 0, nullptr, newChannel);
}
NS_IMETHODIMP
-nsFtpState::OnProxyAvailable(nsICancelable *request, nsIURI *uri,
+nsFtpState::OnProxyAvailable(nsICancelable *request, nsIChannel *channel,
nsIProxyInfo *pi, nsresult status)
{
mProxyRequest = nullptr;
@@ -2395,7 +2398,7 @@ nsFtpState::OnProxyAvailable(nsICancelable *request, nsIURI *uri,
LOG(("FTP:(%p) Configured to use a HTTP proxy channel\n", this));
nsCOMPtr<nsIChannel> newChannel;
- if (NS_SUCCEEDED(CreateHTTPProxiedChannel(uri, pi,
+ if (NS_SUCCEEDED(CreateHTTPProxiedChannel(channel, pi,
getter_AddRefs(newChannel))) &&
NS_SUCCEEDED(mChannel->Redirect(newChannel,
nsIChannelEventSink::REDIRECT_INTERNAL,
diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp
index 40123da..64b202a 100644
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -68,6 +68,7 @@ HttpBaseChannel::HttpBaseChannel()
, mContentDispositionHint(UINT32_MAX)
, mHttpHandler(gHttpHandler)
, mRedirectCount(0)
+ , mProxyURI(nullptr)
{
LOG(("Creating HttpBaseChannel @%x\n", this));
@@ -1075,6 +1076,15 @@ HttpBaseChannel::SetReferrer(nsIURI *referrer)
}
NS_IMETHODIMP
+HttpBaseChannel::GetProxyURI(nsIURI** proxyURI)
+{
+ NS_ENSURE_ARG_POINTER(proxyURI);
+ *proxyURI = mProxyURI;
+ NS_IF_ADDREF(*proxyURI);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
HttpBaseChannel::GetRequestHeader(const nsACString& aHeader,
nsACString& aValue)
{
diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h
index e177a39..abaf789 100644
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -115,6 +115,7 @@ public:
NS_IMETHOD SetRequestMethod(const nsACString& aMethod);
NS_IMETHOD GetReferrer(nsIURI **referrer);
NS_IMETHOD SetReferrer(nsIURI *referrer);
+ NS_IMETHOD GetProxyURI(nsIURI **proxyURI);
NS_IMETHOD GetRequestHeader(const nsACString& aHeader, nsACString& aValue);
NS_IMETHOD SetRequestHeader(const nsACString& aHeader,
const nsACString& aValue, bool aMerge);
diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp
index 6449769..41ef8bb 100644
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -1823,10 +1823,10 @@ nsHttpChannel::ResolveProxy()
// then it is ok to use that version.
nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
if (pps2) {
- rv = pps2->AsyncResolve2(mProxyURI ? mProxyURI : mURI, mProxyResolveFlags,
+ rv = pps2->AsyncResolve2(this, mProxyResolveFlags,
this, getter_AddRefs(mProxyRequest));
} else {
- rv = pps->AsyncResolve(mProxyURI ? mProxyURI : mURI, mProxyResolveFlags,
+ rv = pps->AsyncResolve(this, mProxyResolveFlags,
this, getter_AddRefs(mProxyRequest));
}
@@ -4707,7 +4707,7 @@ nsHttpChannel::SetPriority(int32_t value)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
-nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIURI *uri,
+nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIChannel *channel,
nsIProxyInfo *pi, nsresult status)
{
LOG(("nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%x mStatus=%x]\n",
diff --git a/netwerk/protocol/http/nsIHttpChannel.idl b/netwerk/protocol/http/nsIHttpChannel.idl
index abb2ee4..24df18b 100644
--- a/netwerk/protocol/http/nsIHttpChannel.idl
+++ b/netwerk/protocol/http/nsIHttpChannel.idl
@@ -56,6 +56,12 @@ interface nsIHttpChannel : nsIChannel
attribute nsIURI referrer;
/**
+ * Read the proxy URI, which, if non-null, will be used to resolve
+ * proxies for this channel.
+ */
+ readonly attribute nsIURI proxyURI;
+
+ /**
* Get the value of a particular request header.
*
* @param aHeader
diff --git a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
index f92c36e..350c920 100644
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -115,6 +115,12 @@ nsViewSourceChannel::GetName(nsACString &result)
}
NS_IMETHODIMP
+nsViewSourceChannel::GetProxyURI(nsIURI** proxyURI)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
nsViewSourceChannel::IsPending(bool *result)
{
NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp
index 90f023c..5e14f97 100644
--- a/netwerk/protocol/websocket/WebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannel.cpp
@@ -2292,7 +2292,7 @@ WebSocketChannel::ApplyForAdmission()
MOZ_ASSERT(!mCancelable);
- return pps->AsyncResolve(mURI,
+ return pps->AsyncResolve(mHttpChannel,
nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL,
this, getter_AddRefs(mCancelable));
@@ -2406,7 +2406,7 @@ WebSocketChannel::OnLookupComplete(nsICancelable *aRequest,
// nsIProtocolProxyCallback
NS_IMETHODIMP
-WebSocketChannel::OnProxyAvailable(nsICancelable *aRequest, nsIURI *aURI,
+WebSocketChannel::OnProxyAvailable(nsICancelable *aRequest, nsIChannel *aChannel,
nsIProxyInfo *pi, nsresult status)
{
if (mStopped) {
1
0
[tor-browser/tor-browser-31.2.0esr-4.5-1] Bug #3455.2. Allow RFC1929 authentication (username/password) to SOCKS servers.
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit e0eaf6b471ae3bbc06066232a00f3b27c2bedeee
Author: Arthur Edelstein <arthuredelstein(a)gmail.com>
Date: Tue Oct 21 02:17:55 2014 -0700
Bug #3455.2. Allow RFC1929 authentication (username/password) to SOCKS servers.
---
netwerk/base/public/nsIProtocolProxyService.idl | 29 ++++
netwerk/base/public/nsIProxyInfo.idl | 12 +-
netwerk/base/src/nsProtocolProxyService.cpp | 39 ++++-
netwerk/base/src/nsProtocolProxyService.h | 8 +
netwerk/base/src/nsProxyInfo.cpp | 14 ++
netwerk/base/src/nsProxyInfo.h | 2 +
netwerk/base/src/nsSocketTransport2.cpp | 84 +++++++---
netwerk/base/src/nsSocketTransport2.h | 15 +-
netwerk/socket/nsISocketProvider.idl | 9 +-
netwerk/socket/nsSOCKSIOLayer.cpp | 196 +++++++++++++++++-----
netwerk/socket/nsSOCKSIOLayer.h | 4 +-
netwerk/socket/nsSOCKSSocketProvider.cpp | 12 +-
netwerk/socket/nsUDPSocketProvider.cpp | 6 +-
security/manager/ssl/src/nsNSSIOLayer.cpp | 23 ++-
security/manager/ssl/src/nsNSSIOLayer.h | 7 +-
security/manager/ssl/src/nsSSLSocketProvider.cpp | 12 +-
security/manager/ssl/src/nsTLSSocketProvider.cpp | 12 +-
17 files changed, 361 insertions(+), 123 deletions(-)
diff --git a/netwerk/base/public/nsIProtocolProxyService.idl b/netwerk/base/public/nsIProtocolProxyService.idl
index 9365658..f974f40 100644
--- a/netwerk/base/public/nsIProtocolProxyService.idl
+++ b/netwerk/base/public/nsIProtocolProxyService.idl
@@ -136,6 +136,35 @@ interface nsIProtocolProxyService : nsISupports
in nsIProxyInfo aFailoverProxy);
/**
+ * This method may be called to construct a nsIProxyInfo instance for
+ * a SOCKS connection, with the specified username and password.
+ * @param aHost
+ * The proxy hostname or IP address.
+ * @param aPort
+ * The proxy port.
+ * @param aUsername
+ * The SOCKS5 username
+ * @param aPassword
+ * The SOCKS5 password
+ * @param aFlags
+ * Flags associated with this connection. See nsIProxyInfo.idl
+ * for currently defined flags.
+ * @param aFailoverTimeout
+ * Specifies the length of time (in seconds) to ignore this proxy if
+ * this proxy fails. Pass UINT32_MAX to specify the default
+ * timeout value, causing nsIProxyInfo::failoverTimeout to be
+ * assigned the default value.
+ * @param aFailoverProxy
+ * Specifies the next proxy to try if this proxy fails. This
+ * parameter may be null.
+ */
+ nsIProxyInfo newSOCKSProxyInfo(in AUTF8String aHost, in long aPort,
+ in ACString aUsername, in ACString aPassword,
+ in unsigned long aFlags,
+ in unsigned long aFailoverTimeout,
+ in nsIProxyInfo aFailoverProxy);
+
+ /**
* If the proxy identified by aProxyInfo is unavailable for some reason,
* this method may be called to access an alternate proxy that may be used
* instead. As a side-effect, this method may affect future result values
diff --git a/netwerk/base/public/nsIProxyInfo.idl b/netwerk/base/public/nsIProxyInfo.idl
index f6f0bf3..56beb02 100644
--- a/netwerk/base/public/nsIProxyInfo.idl
+++ b/netwerk/base/public/nsIProxyInfo.idl
@@ -8,7 +8,7 @@
/**
* This interface identifies a proxy server.
*/
-[scriptable, uuid(9e557d99-7af0-4895-95b7-e6dba28c9ad9)]
+[scriptable, uuid(63fff172-2564-4138-96c6-3ae7d245fbed)]
interface nsIProxyInfo : nsISupports
{
/**
@@ -50,6 +50,16 @@ interface nsIProxyInfo : nsISupports
readonly attribute unsigned long resolveFlags;
/**
+ * Specifies a SOCKS5 username.
+ */
+ readonly attribute ACString username;
+
+ /**
+ * Specifies a SOCKS5 password.
+ */
+ readonly attribute ACString password;
+
+ /**
* This attribute specifies the failover timeout in seconds for this proxy.
* If a nsIProxyInfo is reported as failed via nsIProtocolProxyService::
* getFailoverForProxy, then the failed proxy will not be used again for this
diff --git a/netwerk/base/src/nsProtocolProxyService.cpp b/netwerk/base/src/nsProtocolProxyService.cpp
index 3878c58d..ed8b311 100644
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -516,6 +516,12 @@ nsProtocolProxyService::PrefsChanged(nsIPrefBranch *prefBranch,
if (!pref || !strcmp(pref, PROXY_PREF("socks_port")))
proxy_GetIntPref(prefBranch, PROXY_PREF("socks_port"), mSOCKSProxyPort);
+ if (!pref || !strcmp(pref, PROXY_PREF("socks_username")))
+ proxy_GetStringPref(prefBranch, PROXY_PREF("socks_username"), mSOCKSProxyUsername);
+
+ if (!pref || !strcmp(pref, PROXY_PREF("socks_password")))
+ proxy_GetStringPref(prefBranch, PROXY_PREF("socks_password"), mSOCKSProxyPassword);
+
if (!pref || !strcmp(pref, PROXY_PREF("socks_version"))) {
int32_t version;
proxy_GetIntPref(prefBranch, PROXY_PREF("socks_version"), version);
@@ -1188,10 +1194,25 @@ nsProtocolProxyService::NewProxyInfo(const nsACString &aType,
}
NS_ENSURE_TRUE(type, NS_ERROR_INVALID_ARG);
- if (aPort <= 0)
- aPort = -1;
+ return NewProxyInfo_Internal(type, aHost, aPort,
+ mSOCKSProxyUsername, mSOCKSProxyPassword,
+ aFlags, aFailoverTimeout,
+ aFailoverProxy, 0, aResult);
+}
- return NewProxyInfo_Internal(type, aHost, aPort, aFlags, aFailoverTimeout,
+NS_IMETHODIMP
+nsProtocolProxyService::NewSOCKSProxyInfo(const nsACString &aHost,
+ int32_t aPort,
+ const nsACString &aUsername,
+ const nsACString &aPassword,
+ uint32_t aFlags,
+ uint32_t aFailoverTimeout,
+ nsIProxyInfo *aFailoverProxy,
+ nsIProxyInfo **aResult)
+{
+ return NewProxyInfo_Internal(kProxyType_SOCKS, aHost, aPort,
+ aUsername, aPassword,
+ aFlags, aFailoverTimeout,
aFailoverProxy, 0, aResult);
}
@@ -1496,12 +1517,17 @@ nsresult
nsProtocolProxyService::NewProxyInfo_Internal(const char *aType,
const nsACString &aHost,
int32_t aPort,
+ const nsACString &aUsername,
+ const nsACString &aPassword,
uint32_t aFlags,
uint32_t aFailoverTimeout,
nsIProxyInfo *aFailoverProxy,
uint32_t aResolveFlags,
nsIProxyInfo **aResult)
{
+ if (aPort <= 0)
+ aPort = -1;
+
nsCOMPtr<nsProxyInfo> failover;
if (aFailoverProxy) {
failover = do_QueryInterface(aFailoverProxy);
@@ -1515,6 +1541,8 @@ nsProtocolProxyService::NewProxyInfo_Internal(const char *aType,
proxyInfo->mType = aType;
proxyInfo->mHost = aHost;
proxyInfo->mPort = aPort;
+ proxyInfo->mUsername = aUsername;
+ proxyInfo->mPassword = aPassword;
proxyInfo->mFlags = aFlags;
proxyInfo->mResolveFlags = aResolveFlags;
proxyInfo->mTimeout = aFailoverTimeout == UINT32_MAX
@@ -1680,8 +1708,9 @@ nsProtocolProxyService::Resolve_Internal(nsIChannel *channel,
}
if (type) {
- rv = NewProxyInfo_Internal(type, *host, port, proxyFlags,
- UINT32_MAX, nullptr, flags,
+ rv = NewProxyInfo_Internal(type, *host, port,
+ mSOCKSProxyUsername, mSOCKSProxyPassword,
+ proxyFlags, UINT32_MAX, nullptr, flags,
result);
if (NS_FAILED(rv))
return rv;
diff --git a/netwerk/base/src/nsProtocolProxyService.h b/netwerk/base/src/nsProtocolProxyService.h
index 9ef68b9..04c642f 100644
--- a/netwerk/base/src/nsProtocolProxyService.h
+++ b/netwerk/base/src/nsProtocolProxyService.h
@@ -177,6 +177,10 @@ protected:
* The proxy host name (UTF-8 ok).
* @param port
* The proxy port number.
+ * @param username
+ * The username for the proxy (ASCII). May be "", but not null.
+ * @param password
+ * The password for the proxy (ASCII). May be "", but not null.
* @param flags
* The proxy flags (nsIProxyInfo::flags).
* @param timeout
@@ -191,6 +195,8 @@ protected:
NS_HIDDEN_(nsresult) NewProxyInfo_Internal(const char *type,
const nsACString &host,
int32_t port,
+ const nsACString &username,
+ const nsACString &password,
uint32_t flags,
uint32_t timeout,
nsIProxyInfo *next,
@@ -374,6 +380,8 @@ protected:
int32_t mSOCKSProxyPort;
int32_t mSOCKSProxyVersion;
bool mSOCKSProxyRemoteDNS;
+ nsCString mSOCKSProxyUsername;
+ nsCString mSOCKSProxyPassword;
nsRefPtr<nsPACMan> mPACMan; // non-null if we are using PAC
nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;
diff --git a/netwerk/base/src/nsProxyInfo.cpp b/netwerk/base/src/nsProxyInfo.cpp
index 4e727c4..66a78a4 100644
--- a/netwerk/base/src/nsProxyInfo.cpp
+++ b/netwerk/base/src/nsProxyInfo.cpp
@@ -48,6 +48,20 @@ nsProxyInfo::GetResolveFlags(uint32_t *result)
}
NS_IMETHODIMP
+nsProxyInfo::GetUsername(nsACString &result)
+{
+ result = mUsername;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProxyInfo::GetPassword(nsACString &result)
+{
+ result = mPassword;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsProxyInfo::GetFailoverTimeout(uint32_t *result)
{
*result = mTimeout;
diff --git a/netwerk/base/src/nsProxyInfo.h b/netwerk/base/src/nsProxyInfo.h
index 550bbf2..5432d95 100644
--- a/netwerk/base/src/nsProxyInfo.h
+++ b/netwerk/base/src/nsProxyInfo.h
@@ -59,6 +59,8 @@ private:
const char *mType; // pointer to statically allocated value
nsCString mHost;
+ nsCString mUsername;
+ nsCString mPassword;
int32_t mPort;
uint32_t mFlags;
uint32_t mResolveFlags;
diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp
index e202044..ea0dd68 100644
--- a/netwerk/base/src/nsSocketTransport2.cpp
+++ b/netwerk/base/src/nsSocketTransport2.cpp
@@ -751,7 +751,8 @@ nsSocketTransport::nsSocketTransport()
: mTypes(nullptr)
, mTypeCount(0)
, mPort(0)
- , mProxyPort(0)
+ , mHttpsProxy(false)
+ , mProxyUse(false)
, mProxyTransparent(false)
, mProxyTransparentResolvesHost(false)
, mConnectionFlags(0)
@@ -813,18 +814,25 @@ nsSocketTransport::Init(const char **types, uint32_t typeCount,
const char *proxyType = nullptr;
if (proxyInfo) {
- mProxyPort = proxyInfo->Port();
- mProxyHost = proxyInfo->Host();
+ mProxyInfo = proxyInfo;
// grab proxy type (looking for "socks" for example)
proxyType = proxyInfo->Type();
if (proxyType && (strcmp(proxyType, "http") == 0 ||
strcmp(proxyType, "direct") == 0 ||
strcmp(proxyType, "unknown") == 0))
proxyType = nullptr;
+
+ mProxyUse = true;
+ // check that we don't have a proxyInfo without proxy
+ nsCString proxyHost;
+ proxyInfo->GetHost(proxyHost);
+ if (!proxyType || proxyHost.IsEmpty()) {
+ mProxyUse = false;
+ }
}
- SOCKET_LOG(("nsSocketTransport::Init [this=%p host=%s:%hu proxy=%s:%hu]\n",
- this, mHost.get(), mPort, mProxyHost.get(), mProxyPort));
+ SOCKET_LOG(("nsSocketTransport::Init [this=%x host=%s:%hu proxy=%s]\n",
+ this, mHost.get(), mPort, mProxyUse ? "yes" : "no"));
// include proxy type as a socket type if proxy type is not "http"
mTypeCount = typeCount + (proxyType != nullptr);
@@ -997,7 +1005,7 @@ nsSocketTransport::ResolveHost()
nsresult rv;
- if (!mProxyHost.IsEmpty()) {
+ if (mProxyUse) {
if (!mProxyTransparent || mProxyTransparentResolvesHost) {
#if defined(XP_UNIX)
NS_ABORT_IF_FALSE(!mNetAddrIsSet || mNetAddr.raw.family != AF_LOCAL,
@@ -1079,9 +1087,8 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
const char *host = mHost.get();
int32_t port = (int32_t) mPort;
- const char *proxyHost = mProxyHost.IsEmpty() ? nullptr : mProxyHost.get();
- int32_t proxyPort = (int32_t) mProxyPort;
uint32_t proxyFlags = 0;
+ nsCOMPtr<nsIProxyInfo> proxy = mProxyInfo;
uint32_t i;
for (i=0; i<mTypeCount; ++i) {
@@ -1102,12 +1109,19 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
if (mConnectionFlags & nsISocketTransport::NO_PERMANENT_STORAGE)
proxyFlags |= nsISocketProvider::NO_PERMANENT_STORAGE;
+
nsCOMPtr<nsISupports> secinfo;
if (i == 0) {
// if this is the first type, we'll want the
// service to allocate a new socket
+ nsCString proxyHost;
+ GetHost(proxyHost);
+ int32_t proxyPort;
+ GetPort(&proxyPort);
rv = provider->NewSocket(mNetAddr.raw.family,
- host, port, proxyHost, proxyPort,
+ mHttpsProxy ? proxyHost.get() : host,
+ mHttpsProxy ? proxyPort : port,
+ proxy,
proxyFlags, &fd,
getter_AddRefs(secinfo));
@@ -1121,7 +1135,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
// so we just want the service to add itself
// to the stack (such as pushing an io layer)
rv = provider->AddToSocket(mNetAddr.raw.family,
- host, port, proxyHost, proxyPort,
+ host, port, proxy,
proxyFlags, fd,
getter_AddRefs(secinfo));
}
@@ -1151,8 +1165,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
(strcmp(mTypes[i], "socks4") == 0)) {
// since socks is transparent, any layers above
// it do not have to worry about proxy stuff
- proxyHost = nullptr;
- proxyPort = -1;
+ proxy = nullptr;
proxyTransparent = true;
}
}
@@ -1211,10 +1224,14 @@ nsSocketTransport::InitiateSocket()
netAddrCString.BeginWriting(),
kIPv6CStrBufSize))
netAddrCString = NS_LITERAL_CSTRING("<IP-to-string failed>");
+ nsCString proxyHost;
+ GetHost(proxyHost);
+ int32_t proxyPort;
+ GetPort(&proxyPort);
SOCKET_LOG(("nsSocketTransport::InitiateSocket skipping "
"speculative connection for host [%s:%d] proxy "
"[%s:%d] with Local IP address [%s]",
- mHost.get(), mPort, mProxyHost.get(), mProxyPort,
+ mHost.get(), mPort, proxyHost.get(), proxyPort,
netAddrCString.get()));
}
#endif
@@ -1363,7 +1380,7 @@ nsSocketTransport::InitiateSocket()
//
OnSocketConnected();
- if (mSecInfo && !mProxyHost.IsEmpty() && proxyTransparent && usingSSL) {
+ if (mSecInfo && mProxyUse && proxyTransparent && usingSSL) {
// if the connection phase is finished, and the ssl layer has
// been pushed, and we were proxying (transparently; ie. nothing
// has to happen in the protocol layer above us), it's time for
@@ -1387,8 +1404,7 @@ nsSocketTransport::InitiateSocket()
// the OS error
//
else if (PR_UNKNOWN_ERROR == code &&
- mProxyTransparent &&
- !mProxyHost.IsEmpty()) {
+ mProxyUse && mProxyTransparent) {
code = PR_GetOSError();
rv = ErrorAccordingToNSPR(code);
}
@@ -1397,7 +1413,7 @@ nsSocketTransport::InitiateSocket()
//
else {
rv = ErrorAccordingToNSPR(code);
- if ((rv == NS_ERROR_CONNECTION_REFUSED) && !mProxyHost.IsEmpty())
+ if (rv == NS_ERROR_CONNECTION_REFUSED && mProxyUse)
rv = NS_ERROR_PROXY_CONNECTION_REFUSED;
}
}
@@ -1709,8 +1725,8 @@ nsSocketTransport::OnSocketEvent(uint32_t type, nsresult status, nsISupports *pa
// For SOCKS proxies (mProxyTransparent == true), the socket
// transport resolves the real host here, so there's no fixup
// (see bug 226943).
- if ((status == NS_ERROR_UNKNOWN_HOST) && !mProxyTransparent &&
- !mProxyHost.IsEmpty())
+ if (status == NS_ERROR_UNKNOWN_HOST && !mProxyTransparent &&
+ mProxyUse)
mCondition = NS_ERROR_UNKNOWN_PROXY_HOST;
else
mCondition = status;
@@ -1835,8 +1851,7 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
// The SOCKS proxy rejected our request. Find out why.
//
else if (PR_UNKNOWN_ERROR == code &&
- mProxyTransparent &&
- !mProxyHost.IsEmpty()) {
+ mProxyUse && mProxyTransparent) {
code = PR_GetOSError();
mCondition = ErrorAccordingToNSPR(code);
}
@@ -1845,7 +1860,7 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
// else, the connection failed...
//
mCondition = ErrorAccordingToNSPR(code);
- if ((mCondition == NS_ERROR_CONNECTION_REFUSED) && !mProxyHost.IsEmpty())
+ if (mCondition == NS_ERROR_CONNECTION_REFUSED && mProxyUse)
mCondition = NS_ERROR_PROXY_CONNECTION_REFUSED;
SOCKET_LOG((" connection failed! [reason=%x]\n", mCondition));
}
@@ -2168,6 +2183,31 @@ nsSocketTransport::GetPort(int32_t *port)
return NS_OK;
}
+const nsCString &
+nsSocketTransport::SocketHost()
+{
+ if (mProxyInfo && !mProxyTransparent) {
+ if (mProxyHostCache.IsEmpty()) {
+ mProxyInfo->GetHost(mProxyHostCache);
+ }
+ return mProxyHostCache;
+ }
+ else
+ return mHost;
+}
+
+uint16_t
+nsSocketTransport::SocketPort()
+{
+ if (mProxyInfo && !mProxyTransparent) {
+ int32_t result;
+ mProxyInfo->GetPort(&result);
+ return (uint16_t) result;
+ }
+ else
+ return mPort;
+}
+
NS_IMETHODIMP
nsSocketTransport::GetPeerAddr(NetAddr *addr)
{
diff --git a/netwerk/base/src/nsSocketTransport2.h b/netwerk/base/src/nsSocketTransport2.h
index 8d822bf..73f750e 100644
--- a/netwerk/base/src/nsSocketTransport2.h
+++ b/netwerk/base/src/nsSocketTransport2.h
@@ -266,15 +266,18 @@ private:
char **mTypes;
uint32_t mTypeCount;
nsCString mHost;
- nsCString mProxyHost;
uint16_t mPort;
- uint16_t mProxyPort;
- bool mProxyTransparent;
- bool mProxyTransparentResolvesHost;
+ bool mHttpsProxy;
+
+ nsCOMPtr<nsIProxyInfo> mProxyInfo;
+ bool mProxyUse;
+ bool mProxyTransparent;
+ bool mProxyTransparentResolvesHost;
uint32_t mConnectionFlags;
- uint16_t SocketPort() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyPort : mPort; }
- const nsCString &SocketHost() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyHost : mHost; }
+ uint16_t SocketPort();
+ const nsCString &SocketHost();
+ nsCString mProxyHostCache; // for SocketHost() only
//-------------------------------------------------------------------------
// members accessible only on the socket transport thread:
diff --git a/netwerk/socket/nsISocketProvider.idl b/netwerk/socket/nsISocketProvider.idl
index 57f6c4d..0dd316c 100644
--- a/netwerk/socket/nsISocketProvider.idl
+++ b/netwerk/socket/nsISocketProvider.idl
@@ -5,12 +5,13 @@
#include "nsISupports.idl"
+interface nsIProxyInfo;
[ptr] native PRFileDescStar(struct PRFileDesc);
/**
* nsISocketProvider
*/
-[scriptable, uuid(00b3df92-e830-11d8-d48e-0004e22243f8)]
+[scriptable, uuid(508d5469-9e1e-4a08-b5b0-7cfebba1e51a)]
interface nsISocketProvider : nsISupports
{
/**
@@ -38,8 +39,7 @@ interface nsISocketProvider : nsISupports
void newSocket(in long aFamily,
in string aHost,
in long aPort,
- in string aProxyHost,
- in long aProxyPort,
+ in nsIProxyInfo aProxy,
in unsigned long aFlags,
out PRFileDescStar aFileDesc,
out nsISupports aSecurityInfo);
@@ -58,8 +58,7 @@ interface nsISocketProvider : nsISupports
void addToSocket(in long aFamily,
in string aHost,
in long aPort,
- in string aProxyHost,
- in long aProxyPort,
+ in nsIProxyInfo aProxy,
in unsigned long aFlags,
in PRFileDescStar aFileDesc,
out nsISupports aSecurityInfo);
diff --git a/netwerk/socket/nsSOCKSIOLayer.cpp b/netwerk/socket/nsSOCKSIOLayer.cpp
index e03b94c..f3250b9 100644
--- a/netwerk/socket/nsSOCKSIOLayer.cpp
+++ b/netwerk/socket/nsSOCKSIOLayer.cpp
@@ -50,6 +50,8 @@ class nsSOCKSSocketInfo : public nsISOCKSSocketInfo
SOCKS4_READ_CONNECT_RESPONSE,
SOCKS5_WRITE_AUTH_REQUEST,
SOCKS5_READ_AUTH_RESPONSE,
+ SOCKS5_WRITE_USERNAME_REQUEST,
+ SOCKS5_READ_USERNAME_RESPONSE,
SOCKS5_WRITE_CONNECT_REQUEST,
SOCKS5_READ_CONNECT_RESPONSE_TOP,
SOCKS5_READ_CONNECT_RESPONSE_BOTTOM,
@@ -57,10 +59,12 @@ class nsSOCKSSocketInfo : public nsISOCKSSocketInfo
SOCKS_FAILED
};
- // A buffer of 262 bytes should be enough for any request and response
+ // A buffer of 520 bytes should be enough for any request and response
// in case of SOCKS4 as well as SOCKS5
- static const uint32_t BUFFER_SIZE = 262;
+ static const uint32_t BUFFER_SIZE = 520;
static const uint32_t MAX_HOSTNAME_LEN = 255;
+ static const uint32_t MAX_USERNAME_LEN = 255;
+ static const uint32_t MAX_PASSWORD_LEN = 255;
public:
nsSOCKSSocketInfo();
@@ -72,8 +76,7 @@ public:
void Init(int32_t version,
int32_t family,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
const char *destinationHost,
uint32_t flags);
@@ -95,6 +98,8 @@ private:
PRStatus ReadV4ConnectResponse();
PRStatus WriteV5AuthRequest();
PRStatus ReadV5AuthResponse();
+ PRStatus WriteV5UsernameRequest();
+ PRStatus ReadV5UsernameResponse();
PRStatus WriteV5ConnectRequest();
PRStatus ReadV5AddrTypeAndLength(uint8_t *type, uint32_t *len);
PRStatus ReadV5ConnectResponseTop();
@@ -130,8 +135,7 @@ private:
PRFileDesc *mFD;
nsCString mDestinationHost;
- nsCString mProxyHost;
- int32_t mProxyPort;
+ nsCOMPtr<nsIProxyInfo> mProxy;
int32_t mVersion; // SOCKS version 4 or 5
int32_t mDestinationFamily;
uint32_t mFlags;
@@ -139,6 +143,7 @@ private:
NetAddr mExternalProxyAddr;
NetAddr mDestinationAddr;
PRIntervalTime mTimeout;
+ nsCString mProxyUsername; // Cache, from mProxy
};
nsSOCKSSocketInfo::nsSOCKSSocketInfo()
@@ -147,7 +152,6 @@ nsSOCKSSocketInfo::nsSOCKSSocketInfo()
, mDataLength(0)
, mReadOffset(0)
, mAmountToRead(0)
- , mProxyPort(-1)
, mVersion(-1)
, mDestinationFamily(AF_INET)
, mFlags(0)
@@ -169,14 +173,14 @@ nsSOCKSSocketInfo::nsSOCKSSocketInfo()
}
void
-nsSOCKSSocketInfo::Init(int32_t version, int32_t family, const char *proxyHost, int32_t proxyPort, const char *host, uint32_t flags)
+nsSOCKSSocketInfo::Init(int32_t version, int32_t family, nsIProxyInfo *proxy, const char *host, uint32_t flags)
{
mVersion = version;
mDestinationFamily = family;
- mProxyHost = proxyHost;
- mProxyPort = proxyPort;
+ mProxy = proxy;
mDestinationHost = host;
mFlags = flags;
+ mProxy->GetUsername(mProxyUsername); // cache
}
NS_IMPL_ISUPPORTS(nsSOCKSSocketInfo, nsISOCKSSocketInfo, nsIDNSListener)
@@ -263,14 +267,17 @@ nsSOCKSSocketInfo::StartDNS(PRFileDesc *fd)
if (!dns)
return PR_FAILURE;
+ nsCString proxyHost;
+ mProxy->GetHost(proxyHost);
+
mFD = fd;
- nsresult rv = dns->AsyncResolve(mProxyHost, 0, this,
+ nsresult rv = dns->AsyncResolve(proxyHost, 0, this,
NS_GetCurrentThread(),
getter_AddRefs(mLookup));
if (NS_FAILED(rv)) {
LOGERROR(("socks: DNS lookup for SOCKS proxy %s failed",
- mProxyHost.get()));
+ proxyHost.get()));
return PR_FAILURE;
}
mState = SOCKS_DNS_IN_PROGRESS;
@@ -315,16 +322,21 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc *fd)
mVersion = 5;
}
+ int32_t proxyPort;
+ mProxy->GetPort(&proxyPort);
+
int32_t addresses = 0;
do {
if (addresses++)
- mDnsRec->ReportUnusable(mProxyPort);
+ mDnsRec->ReportUnusable(proxyPort);
- rv = mDnsRec->GetNextAddr(mProxyPort, &mInternalProxyAddr);
+ rv = mDnsRec->GetNextAddr(proxyPort, &mInternalProxyAddr);
// No more addresses to try? If so, we'll need to bail
if (NS_FAILED(rv)) {
+ nsCString proxyHost;
+ mProxy->GetHost(proxyHost);
LOGERROR(("socks: unable to connect to SOCKS proxy, %s",
- mProxyHost.get()));
+ proxyHost.get()));
return PR_FAILURE;
}
@@ -440,6 +452,12 @@ nsSOCKSSocketInfo::ContinueConnectingToProxy(PRFileDesc *fd, int16_t oflags)
PRStatus
nsSOCKSSocketInfo::WriteV4ConnectRequest()
{
+ if (mProxyUsername.Length() > MAX_USERNAME_LEN) {
+ LOGERROR(("socks username is too long"));
+ HandshakeFinished(PR_UNKNOWN_ERROR);
+ return PR_FAILURE;
+ }
+
NetAddr *addr = &mDestinationAddr;
int32_t proxy_resolve;
@@ -465,7 +483,9 @@ nsSOCKSSocketInfo::WriteV4ConnectRequest()
// 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(htonl(0x00000001)); // Fake IP
- WriteUint8(0x00); // Send an emtpy username
+ WriteString(mProxyUsername); // Send username. May be empty.
+ WriteUint8(0x00); // Null-terminate username
+ // Password not supported by V4.
if (mDestinationHost.Length() > MAX_HOSTNAME_LEN) {
LOGERROR(("socks4: destination host name is too long!"));
HandshakeFinished(PR_BAD_ADDRESS_ERROR);
@@ -475,7 +495,9 @@ nsSOCKSSocketInfo::WriteV4ConnectRequest()
WriteUint8(0x00);
} else if (addr->raw.family == AF_INET) {
WriteNetAddr(addr); // Add the IPv4 address
- WriteUint8(0x00); // Send an emtpy username
+ WriteString(mProxyUsername); // Send username. May be empty.
+ WriteUint8(0x00); // Null-terminate username
+ // Password not supported by V4.
} else if (addr->raw.family == AF_INET6) {
LOGERROR(("socks: SOCKS 4 can't handle IPv6 addresses!"));
HandshakeFinished(PR_BAD_ADDRESS_ERROR);
@@ -490,11 +512,15 @@ 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(("socks4: checking connection reply"));
+ if (mDataLength != 8) {
+ LOGERROR(("SOCKS 4 connection reply must be 8 bytes!"));
+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
+ return PR_FAILURE;
+ }
+
if (ReadUint8() != 0x00) {
LOGERROR(("socks4: wrong connection reply"));
HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
@@ -518,13 +544,18 @@ nsSOCKSSocketInfo::WriteV5AuthRequest()
{
NS_ABORT_IF_FALSE(mVersion == 5, "SOCKS version must be 5!");
+ mDataLength = 0;
mState = SOCKS5_WRITE_AUTH_REQUEST;
// 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
+ WriteUint8(0x01); // # of auth methods -- 1
+ if (mProxyUsername.IsEmpty()) {
+ WriteUint8(0x00); // no authentication
+ } else {
+ WriteUint8(0x02); // username/password
+ }
return PR_SUCCESS;
}
@@ -534,10 +565,12 @@ 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!");
- LOGDEBUG(("socks5: checking auth method reply"));
+ if (mDataLength != 2) {
+ LOGERROR(("SOCKS 5 auth method reply must be 2 bytes"));
+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
+ return PR_FAILURE;
+ }
// Check version number
if (ReadUint8() != 0x05) {
@@ -546,12 +579,82 @@ nsSOCKSSocketInfo::ReadV5AuthResponse()
return PR_FAILURE;
}
- // Make sure our authentication choice was accepted
- if (ReadUint8() != 0x00) {
+ // Make sure our authentication choice was accepted,
+ // and continue accordingly
+ uint8_t authMethod = ReadUint8();
+ if (mProxyUsername.IsEmpty() && authMethod == 0x00) { // no auth
+ LOGDEBUG(("socks5: server allows connection without authentication"));
+ return WriteV5ConnectRequest();
+ } else if (!mProxyUsername.IsEmpty() && authMethod == 0x02) { // username/pw
+ LOGDEBUG(("socks5: auth method accepted by server"));
+ return WriteV5UsernameRequest();
+ } else { // 0xFF signals error
LOGERROR(("socks5: server did not accept our authentication method"));
HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
return PR_FAILURE;
}
+}
+
+PRStatus
+nsSOCKSSocketInfo::WriteV5UsernameRequest()
+{
+ NS_ABORT_IF_FALSE(mVersion == 5, "SOCKS version must be 5!");
+
+ if (mProxyUsername.Length() > MAX_USERNAME_LEN) {
+ LOGERROR(("socks username is too long"));
+ HandshakeFinished(PR_UNKNOWN_ERROR);
+ return PR_FAILURE;
+ }
+
+ nsCString password;
+ mProxy->GetPassword(password);
+ if (password.Length() > MAX_PASSWORD_LEN) {
+ LOGERROR(("socks password is too long"));
+ HandshakeFinished(PR_UNKNOWN_ERROR);
+ return PR_FAILURE;
+ }
+
+ mDataLength = 0;
+ mState = SOCKS5_WRITE_USERNAME_REQUEST;
+
+ LOGDEBUG(("socks5: sending username and password"));
+ // RFC 1929 Username/password auth for SOCKS 5
+ WriteUint8(0x01); // version 1 (not 5)
+ WriteUint8(mProxyUsername.Length()); // username length
+ WriteString(mProxyUsername); // username
+ WriteUint8(password.Length()); // password length
+ WriteString(password); // password. WARNING: Sent unencrypted!
+
+ return PR_SUCCESS;
+}
+
+PRStatus
+nsSOCKSSocketInfo::ReadV5UsernameResponse()
+{
+ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_USERNAME_RESPONSE,
+ "Handling SOCKS 5 username/password reply in wrong state!");
+
+ if (mDataLength != 2) {
+ LOGERROR(("SOCKS 5 username reply must be 2 bytes"));
+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
+ return PR_FAILURE;
+ }
+
+ // Check version number, must be 1 (not 5)
+ if (ReadUint8() != 0x01) {
+ LOGERROR(("socks5: unexpected version in the reply"));
+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
+ return PR_FAILURE;
+ }
+
+ // Check whether username/password were accepted
+ if (ReadUint8() != 0x00) { // 0 = success
+ LOGERROR(("socks5: username/password not accepted"));
+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
+ return PR_FAILURE;
+ }
+
+ LOGDEBUG(("socks5: username/password accepted by server"));
return WriteV5ConnectRequest();
}
@@ -795,6 +898,16 @@ nsSOCKSSocketInfo::DoHandshake(PRFileDesc *fd, int16_t oflags)
if (ReadFromSocket(fd) != PR_SUCCESS)
return PR_FAILURE;
return ReadV5AuthResponse();
+ case SOCKS5_WRITE_USERNAME_REQUEST:
+ if (WriteToSocket(fd) != PR_SUCCESS)
+ return PR_FAILURE;
+ WantRead(2);
+ mState = SOCKS5_READ_USERNAME_RESPONSE;
+ return PR_SUCCESS;
+ case SOCKS5_READ_USERNAME_RESPONSE:
+ if (ReadFromSocket(fd) != PR_SUCCESS)
+ return PR_FAILURE;
+ return ReadV5UsernameResponse();
case SOCKS5_WRITE_CONNECT_REQUEST:
if (WriteToSocket(fd) != PR_SUCCESS)
return PR_FAILURE;
@@ -839,10 +952,12 @@ nsSOCKSSocketInfo::GetPollFlags() const
return PR_POLL_EXCEPT | PR_POLL_WRITE;
case SOCKS4_WRITE_CONNECT_REQUEST:
case SOCKS5_WRITE_AUTH_REQUEST:
+ case SOCKS5_WRITE_USERNAME_REQUEST:
case SOCKS5_WRITE_CONNECT_REQUEST:
return PR_POLL_WRITE;
case SOCKS4_READ_CONNECT_RESPONSE:
case SOCKS5_READ_AUTH_RESPONSE:
+ case SOCKS5_READ_USERNAME_RESPONSE:
case SOCKS5_READ_CONNECT_RESPONSE_TOP:
case SOCKS5_READ_CONNECT_RESPONSE_BOTTOM:
return PR_POLL_READ;
@@ -856,7 +971,7 @@ nsSOCKSSocketInfo::GetPollFlags() const
inline void
nsSOCKSSocketInfo::WriteUint8(uint8_t v)
{
- NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + sizeof(v) <= BUFFER_SIZE,
"Can't write that much data!");
mData[mDataLength] = v;
mDataLength += sizeof(v);
@@ -865,7 +980,7 @@ nsSOCKSSocketInfo::WriteUint8(uint8_t v)
inline void
nsSOCKSSocketInfo::WriteUint16(uint16_t v)
{
- NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + sizeof(v) <= BUFFER_SIZE,
"Can't write that much data!");
memcpy(mData + mDataLength, &v, sizeof(v));
mDataLength += sizeof(v);
@@ -874,7 +989,7 @@ nsSOCKSSocketInfo::WriteUint16(uint16_t v)
inline void
nsSOCKSSocketInfo::WriteUint32(uint32_t v)
{
- NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + sizeof(v) <= BUFFER_SIZE,
"Can't write that much data!");
memcpy(mData + mDataLength, &v, sizeof(v));
mDataLength += sizeof(v);
@@ -894,8 +1009,8 @@ nsSOCKSSocketInfo::WriteNetAddr(const NetAddr *addr)
len = sizeof(addr->inet6.ip.u8);
}
- NS_ABORT_IF_FALSE(ip != nullptr, "Unknown address");
- NS_ABORT_IF_FALSE(mDataLength + len <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(ip != nullptr, "Unknown address");
+ MOZ_RELEASE_ASSERT(mDataLength + len <= BUFFER_SIZE,
"Can't write that much data!");
memcpy(mData + mDataLength, ip, len);
@@ -911,7 +1026,7 @@ nsSOCKSSocketInfo::WriteNetPort(const NetAddr *addr)
void
nsSOCKSSocketInfo::WriteString(const nsACString &str)
{
- NS_ABORT_IF_FALSE(mDataLength + str.Length() <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + str.Length() <= BUFFER_SIZE,
"Can't write that much data!");
memcpy(mData + mDataLength, str.Data(), str.Length());
mDataLength += str.Length();
@@ -921,7 +1036,7 @@ inline uint8_t
nsSOCKSSocketInfo::ReadUint8()
{
uint8_t rv;
- NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + sizeof(rv) <= mDataLength,
"Not enough space to pop a uint8_t!");
rv = mData[mReadOffset];
mReadOffset += sizeof(rv);
@@ -932,7 +1047,7 @@ inline uint16_t
nsSOCKSSocketInfo::ReadUint16()
{
uint16_t rv;
- NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + sizeof(rv) <= mDataLength,
"Not enough space to pop a uint16_t!");
memcpy(&rv, mData + mReadOffset, sizeof(rv));
mReadOffset += sizeof(rv);
@@ -943,7 +1058,7 @@ inline uint32_t
nsSOCKSSocketInfo::ReadUint32()
{
uint32_t rv;
- NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + sizeof(rv) <= mDataLength,
"Not enough space to pop a uint32_t!");
memcpy(&rv, mData + mReadOffset, sizeof(rv));
mReadOffset += sizeof(rv);
@@ -959,12 +1074,12 @@ nsSOCKSSocketInfo::ReadNetAddr(NetAddr *addr, uint16_t fam)
addr->raw.family = fam;
if (fam == AF_INET) {
amt = sizeof(addr->inet.ip);
- NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + amt <= mDataLength,
"Not enough space to pop an ipv4 addr!");
memcpy(&addr->inet.ip, ip, amt);
} else if (fam == AF_INET6) {
amt = sizeof(addr->inet6.ip.u8);
- NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + amt <= mDataLength,
"Not enough space to pop an ipv6 addr!");
memcpy(addr->inet6.ip.u8, ip, amt);
}
@@ -983,7 +1098,7 @@ nsSOCKSSocketInfo::WantRead(uint32_t sz)
{
NS_ABORT_IF_FALSE(mDataIoPtr == nullptr,
"WantRead() called while I/O already in progress!");
- NS_ABORT_IF_FALSE(mDataLength + sz <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + sz <= BUFFER_SIZE,
"Can't read that much data!");
mAmountToRead = sz;
}
@@ -1221,8 +1336,7 @@ nsresult
nsSOCKSIOLayerAddToSocket(int32_t family,
const char *host,
int32_t port,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
int32_t socksVersion,
uint32_t flags,
PRFileDesc *fd,
@@ -1289,7 +1403,7 @@ nsSOCKSIOLayerAddToSocket(int32_t family,
}
NS_ADDREF(infoObject);
- infoObject->Init(socksVersion, family, proxyHost, proxyPort, host, flags);
+ infoObject->Init(socksVersion, family, proxy, host, flags);
layer->secret = (PRFilePrivate*) infoObject;
rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer);
diff --git a/netwerk/socket/nsSOCKSIOLayer.h b/netwerk/socket/nsSOCKSIOLayer.h
index dfe7c0c..54d936e 100644
--- a/netwerk/socket/nsSOCKSIOLayer.h
+++ b/netwerk/socket/nsSOCKSIOLayer.h
@@ -9,12 +9,12 @@
#include "prio.h"
#include "nscore.h"
+#include "nsIProxyInfo.h"
nsresult nsSOCKSIOLayerAddToSocket(int32_t family,
const char *host,
int32_t port,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxyInfo,
int32_t socksVersion,
uint32_t flags,
PRFileDesc *fd,
diff --git a/netwerk/socket/nsSOCKSSocketProvider.cpp b/netwerk/socket/nsSOCKSSocketProvider.cpp
index af7c9b5..c5a5655 100644
--- a/netwerk/socket/nsSOCKSSocketProvider.cpp
+++ b/netwerk/socket/nsSOCKSSocketProvider.cpp
@@ -44,8 +44,7 @@ NS_IMETHODIMP
nsSOCKSSocketProvider::NewSocket(int32_t family,
const char *host,
int32_t port,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
uint32_t flags,
PRFileDesc **result,
nsISupports **socksInfo)
@@ -59,8 +58,7 @@ nsSOCKSSocketProvider::NewSocket(int32_t family,
nsresult rv = nsSOCKSIOLayerAddToSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
mVersion,
flags,
sock,
@@ -77,8 +75,7 @@ NS_IMETHODIMP
nsSOCKSSocketProvider::AddToSocket(int32_t family,
const char *host,
int32_t port,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
uint32_t flags,
PRFileDesc *sock,
nsISupports **socksInfo)
@@ -86,8 +83,7 @@ nsSOCKSSocketProvider::AddToSocket(int32_t family,
nsresult rv = nsSOCKSIOLayerAddToSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
mVersion,
flags,
sock,
diff --git a/netwerk/socket/nsUDPSocketProvider.cpp b/netwerk/socket/nsUDPSocketProvider.cpp
index 4ca7b29..f03b624 100644
--- a/netwerk/socket/nsUDPSocketProvider.cpp
+++ b/netwerk/socket/nsUDPSocketProvider.cpp
@@ -16,8 +16,7 @@ NS_IMETHODIMP
nsUDPSocketProvider::NewSocket(int32_t aFamily,
const char *aHost,
int32_t aPort,
- const char *aProxyHost,
- int32_t aProxyPort,
+ nsIProxyInfo *aProxy,
uint32_t aFlags,
PRFileDesc * *aFileDesc,
nsISupports **aSecurityInfo)
@@ -36,8 +35,7 @@ NS_IMETHODIMP
nsUDPSocketProvider::AddToSocket(int32_t aFamily,
const char *aHost,
int32_t aPort,
- const char *aProxyHost,
- int32_t aProxyPort,
+ nsIProxyInfo *aProxy,
uint32_t aFlags,
struct PRFileDesc * aFileDesc,
nsISupports **aSecurityInfo)
diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp
index 43bb013..a71f265 100644
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -1598,8 +1598,7 @@ nsresult
nsSSLIOLayerNewSocket(int32_t family,
const char* host,
int32_t port,
- const char* proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
PRFileDesc** fd,
nsISupports** info,
bool forSTARTTLS,
@@ -1609,7 +1608,7 @@ nsSSLIOLayerNewSocket(int32_t family,
PRFileDesc* sock = PR_OpenTCPSocket(family);
if (!sock) return NS_ERROR_OUT_OF_MEMORY;
- nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxyHost, proxyPort,
+ nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxy,
sock, info, forSTARTTLS, flags);
if (NS_FAILED(rv)) {
PR_Close(sock);
@@ -2274,11 +2273,11 @@ loser:
static nsresult
nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS,
- const char* proxyHost, const char* host, int32_t port,
+ bool haveProxy, const char* host, int32_t port,
nsNSSSocketInfo* infoObject)
{
nsNSSShutDownPreventionLock locker;
- if (forSTARTTLS || proxyHost) {
+ if (forSTARTTLS || haveProxy) {
if (SECSuccess != SSL_OptionSet(fd, SSL_SECURITY, false)) {
return NS_ERROR_FAILURE;
}
@@ -2350,8 +2349,7 @@ nsresult
nsSSLIOLayerAddToSocket(int32_t family,
const char* host,
int32_t port,
- const char* proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo* proxy,
PRFileDesc* fd,
nsISupports** info,
bool forSTARTTLS,
@@ -2373,6 +2371,13 @@ nsSSLIOLayerAddToSocket(int32_t family,
infoObject->SetHostName(host);
infoObject->SetPort(port);
+ bool haveProxy = false;
+ if (proxy) {
+ nsCString proxyHost;
+ proxy->GetHost(proxyHost);
+ haveProxy = !proxyHost.IsEmpty();
+ }
+
// A plaintext observer shim is inserted so we can observe some protocol
// details without modifying nss
plaintextLayer = PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity,
@@ -2394,7 +2399,7 @@ nsSSLIOLayerAddToSocket(int32_t family,
infoObject->SetFileDescPtr(sslSock);
- rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, proxyHost, host, port,
+ rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, haveProxy, host, port,
infoObject);
if (NS_FAILED(rv))
@@ -2419,7 +2424,7 @@ nsSSLIOLayerAddToSocket(int32_t family,
infoObject->QueryInterface(NS_GET_IID(nsISupports), (void**) (info));
// We are going use a clear connection first //
- if (forSTARTTLS || proxyHost) {
+ if (forSTARTTLS || haveProxy) {
infoObject->SetHandshakeNotPending();
}
diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h
index fca0ce8..6ba745d 100644
--- a/security/manager/ssl/src/nsNSSIOLayer.h
+++ b/security/manager/ssl/src/nsNSSIOLayer.h
@@ -10,6 +10,7 @@
#include "TransportSecurityInfo.h"
#include "nsISSLSocketControl.h"
#include "nsIClientAuthDialogs.h"
+#include "nsIProxyInfo.h"
#include "nsNSSCertificate.h"
#include "nsDataHashtable.h"
#include "nsTHashtable.h"
@@ -202,8 +203,7 @@ private:
nsresult nsSSLIOLayerNewSocket(int32_t family,
const char* host,
int32_t port,
- const char* proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
PRFileDesc** fd,
nsISupports** securityInfo,
bool forSTARTTLS,
@@ -212,8 +212,7 @@ nsresult nsSSLIOLayerNewSocket(int32_t family,
nsresult nsSSLIOLayerAddToSocket(int32_t family,
const char* host,
int32_t port,
- const char* proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
PRFileDesc* fd,
nsISupports** securityInfo,
bool forSTARTTLS,
diff --git a/security/manager/ssl/src/nsSSLSocketProvider.cpp b/security/manager/ssl/src/nsSSLSocketProvider.cpp
index fd37f4c..0666082 100644
--- a/security/manager/ssl/src/nsSSLSocketProvider.cpp
+++ b/security/manager/ssl/src/nsSSLSocketProvider.cpp
@@ -22,8 +22,7 @@ NS_IMETHODIMP
nsSSLSocketProvider::NewSocket(int32_t family,
const char *host,
int32_t port,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
uint32_t flags,
PRFileDesc **_result,
nsISupports **securityInfo)
@@ -31,8 +30,7 @@ nsSSLSocketProvider::NewSocket(int32_t family,
nsresult rv = nsSSLIOLayerNewSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
_result,
securityInfo,
false,
@@ -45,8 +43,7 @@ NS_IMETHODIMP
nsSSLSocketProvider::AddToSocket(int32_t family,
const char *host,
int32_t port,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
uint32_t flags,
PRFileDesc *aSocket,
nsISupports **securityInfo)
@@ -54,8 +51,7 @@ nsSSLSocketProvider::AddToSocket(int32_t family,
nsresult rv = nsSSLIOLayerAddToSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
aSocket,
securityInfo,
false,
diff --git a/security/manager/ssl/src/nsTLSSocketProvider.cpp b/security/manager/ssl/src/nsTLSSocketProvider.cpp
index 029b2c5..09dd2bd 100644
--- a/security/manager/ssl/src/nsTLSSocketProvider.cpp
+++ b/security/manager/ssl/src/nsTLSSocketProvider.cpp
@@ -22,8 +22,7 @@ NS_IMETHODIMP
nsTLSSocketProvider::NewSocket(int32_t family,
const char *host,
int32_t port,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
uint32_t flags,
PRFileDesc **_result,
nsISupports **securityInfo)
@@ -31,8 +30,7 @@ nsTLSSocketProvider::NewSocket(int32_t family,
nsresult rv = nsSSLIOLayerNewSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
_result,
securityInfo,
true,
@@ -46,8 +44,7 @@ NS_IMETHODIMP
nsTLSSocketProvider::AddToSocket(int32_t family,
const char *host,
int32_t port,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
uint32_t flags,
PRFileDesc *aSocket,
nsISupports **securityInfo)
@@ -55,8 +52,7 @@ nsTLSSocketProvider::AddToSocket(int32_t family,
nsresult rv = nsSSLIOLayerAddToSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
aSocket,
securityInfo,
true,
1
0
[tor-browser/tor-browser-31.2.0esr-4.5-1] Revert "fixup! Bug #5926: Allow customization of content JS locale."
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit e007a57d358f1165feb5f8506b4efe5be46224cb
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Thu Oct 30 13:31:11 2014 -0700
Revert "fixup! Bug #5926: Allow customization of content JS locale."
This reverts commit eb0ccdb7ffc70ffa4b4a60100606261882d68129.
I missed that the JS engine was managing its own copy of the returned string.
We do need to strdup it.
---
xpcom/build/nsXPComInit.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xpcom/build/nsXPComInit.cpp b/xpcom/build/nsXPComInit.cpp
index 62f31bf..979e10b 100644
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -493,7 +493,7 @@ void StartWatchingDefaultLocalePref() {
// Store the default JavaScript locale.
JSRuntime* rt = GetRuntime();
if (rt) {
- sJSLocale = JS_GetDefaultLocale(rt);
+ sJSLocale = strdup(JS_GetDefaultLocale(rt));
}
// Now keep the locale updated with the current pref value.
mozilla::Preferences::RegisterCallbackAndCall(DefaultLocaleChangedCallback, DEFAULT_LOCALE_PREF);
1
0
[tor-browser-bundle/master] 64 bit build on Mac for all components. Tor-Browser requires an additional patch, and versions.alpa was not updated to point at the correct tag
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit f1f4a2a85da44820e148c47486363befc1a4bb16
Author: Tom Ritter <tom(a)ritter.vg>
Date: Tue Sep 16 21:46:00 2014 -0500
64 bit build on Mac for all components. Tor-Browser requires an additional patch, and versions.alpa was not updated to point at the correct tag
---
Bundle-Data/mac-tor.sh | 1 -
gitian/descriptors/mac/gitian-bundle.yml | 9 +++-----
gitian/descriptors/mac/gitian-firefox.yml | 3 ---
.../mac/gitian-pluggable-transports.yml | 16 ++++++-------
gitian/descriptors/mac/gitian-tor.yml | 16 ++++++-------
gitian/descriptors/mac/gitian-utils.yml | 16 +++++++------
gitian/mkbundle-mac.sh | 24 ++++++++++----------
7 files changed, 40 insertions(+), 45 deletions(-)
diff --git a/Bundle-Data/mac-tor.sh b/Bundle-Data/mac-tor.sh
index 9a22096..03d6f9d 100755
--- a/Bundle-Data/mac-tor.sh
+++ b/Bundle-Data/mac-tor.sh
@@ -1,7 +1,6 @@
#!/bin/sh
# Compiled Python modules require a compatible Python, which means 32-bit 2.6.
export VERSIONER_PYTHON_VERSION=2.6
-export VERSIONER_PYTHON_PREFER_32_BIT=yes
export DYLD_LIBRARY_PATH=.:$DYLD_LIBRARY_PATH
# Set the current working directory to the directory containing this executable,
# so that pluggable transport executables can be given with relative paths. This
diff --git a/gitian/descriptors/mac/gitian-bundle.yml b/gitian/descriptors/mac/gitian-bundle.yml
index 82b6595..1cf75e9 100644
--- a/gitian/descriptors/mac/gitian-bundle.yml
+++ b/gitian/descriptors/mac/gitian-bundle.yml
@@ -30,9 +30,9 @@ remotes:
"dir": "meek"
files:
# TODO: Can we use an env for this file+version??
-- "tor-browser-mac32-gbuilt.zip"
-- "tor-mac32-gbuilt.zip"
-- "pluggable-transports-mac32-gbuilt.zip"
+- "tor-browser-mac64-gbuilt.zip"
+- "tor-mac64-gbuilt.zip"
+- "pluggable-transports-mac64-gbuilt.zip"
- "torrc-defaults-appendix-mac"
- "bridge_prefs.js"
- "meek-http-helper-user.js"
@@ -75,9 +75,6 @@ script: |
unzip -d ~/build ~/build/mar-tools-mac$GBUILD_BITS.zip
MARTOOLS=~/build/mar-tools
#
- # XXX: Find a better way to tell that we are having a 32bit build
- GBUILD_BITS=32
- #
mkdir -p $OUTDIR/
mkdir -p $TORBROWSER_NAME.app/TorBrowser/Data/Browser/profile.default/extensions/https-everywhere(a)eff.org
mkdir -p $TORBROWSER_NAME.app/TorBrowser/Data/Browser/profile.meek-http-helper/extensions
diff --git a/gitian/descriptors/mac/gitian-firefox.yml b/gitian/descriptors/mac/gitian-firefox.yml
index fc36472..9126f03 100644
--- a/gitian/descriptors/mac/gitian-firefox.yml
+++ b/gitian/descriptors/mac/gitian-firefox.yml
@@ -95,9 +95,6 @@ script: |
zip -r mar-tools-mac${GBUILD_BITS}.zip mar-tools
cp -p mar-tools-mac${GBUILD_BITS}.zip $OUTDIR/
#
- # XXX: Find a better way to tell that we are having a 32bit build
- GBUILD_BITS=32
- #
cd $INSTDIR
# Adjust the Info.plist file
INFO_PLIST=TorBrowser.app/Contents/Info.plist
diff --git a/gitian/descriptors/mac/gitian-pluggable-transports.yml b/gitian/descriptors/mac/gitian-pluggable-transports.yml
index 33df49f..17aef86 100644
--- a/gitian/descriptors/mac/gitian-pluggable-transports.yml
+++ b/gitian/descriptors/mac/gitian-pluggable-transports.yml
@@ -42,8 +42,8 @@ files:
- "apple-uni-sdk-10.6_20110407-0.flosoft1_i386.deb"
- "multiarch-darwin11-cctools127.2-gcc42-5666.3-llvmgcc42-2336.1-Linux-120724.tar.xz"
- "dzip.sh"
-- "gmp-mac32-utils.zip"
-- "openssl-mac32-utils.zip"
+- "gmp-mac64-utils.zip"
+- "openssl-mac64-utils.zip"
script: |
INSTDIR="$HOME/install"
TBDIR="$INSTDIR/TorBrowserBundle.app/TorBrowser"
@@ -61,8 +61,8 @@ script: |
sudo dpkg -i *.deb
tar xaf multiarch-darwin*tar.xz
export PATH="$PATH:$HOME/build/apple-osx/bin/"
- unzip -d $INSTDIR gmp-mac32-utils.zip
- unzip -d $INSTDIR openssl-mac32-utils.zip
+ unzip -d $INSTDIR gmp-mac64-utils.zip
+ unzip -d $INSTDIR openssl-mac64-utils.zip
cp $INSTDIR/gmp/lib/*dylib* $TBDIR/Tor/
#
@@ -72,8 +72,8 @@ script: |
# http://bugs.python.org/issue9437
export LDSHARED="$CC -pthread -shared"
# XXX Clean up these flags?
- export CFLAGS="-I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -F/usr/lib/apple/SDKs/MacOSX10.6.sdk/System/Library/Frameworks -mmacosx-version-min=10.5 -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/i686-apple-darwin10/4.2.1 -I$INSTDIR/gmp/include -L$INSTDIR/gmp/lib"
- export CXXFLAGS="-I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -F/usr/lib/apple/SDKs/MacOSX10.6.sdk/System/Library/Frameworks -mmacosx-version-min=10.5 -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/i686-apple-darwin10/4.2.1 -I$INSTDIR/gmp/include -L$INSTDIR/gmp/lib"
+ export CFLAGS="-m64 -I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -F/usr/lib/apple/SDKs/MacOSX10.6.sdk/System/Library/Frameworks -mmacosx-version-min=10.5 -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/i686-apple-darwin10/4.2.1 -I$INSTDIR/gmp/include -L$INSTDIR/gmp/lib"
+ export CXXFLAGS="-m64 -I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -F/usr/lib/apple/SDKs/MacOSX10.6.sdk/System/Library/Frameworks -mmacosx-version-min=10.5 -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/i686-apple-darwin10/4.2.1 -I$INSTDIR/gmp/include -L$INSTDIR/gmp/lib"
export LDFLAGS="-L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -F/usr/lib/apple/SDKs/MacOSX10.6.sdk/System/Library/Frameworks -mmacosx-version-min=10.5"
# Building go
@@ -247,5 +247,5 @@ script: |
# Grabbing the result
cd $INSTDIR
- ~/build/dzip.sh pluggable-transports-mac$GBUILD_BITS-gbuilt.zip TorBrowserBundle.app
- cp pluggable-transports-mac$GBUILD_BITS-gbuilt.zip $OUTDIR/
+ ~/build/dzip.sh pluggable-transports-mac64-gbuilt.zip TorBrowserBundle.app
+ cp pluggable-transports-mac64-gbuilt.zip $OUTDIR/
diff --git a/gitian/descriptors/mac/gitian-tor.yml b/gitian/descriptors/mac/gitian-tor.yml
index 6022c0b..555440f 100644
--- a/gitian/descriptors/mac/gitian-tor.yml
+++ b/gitian/descriptors/mac/gitian-tor.yml
@@ -26,8 +26,8 @@ files:
- "apple-uni-sdk-10.6_20110407-0.flosoft1_i386.deb"
- "multiarch-darwin11-cctools127.2-gcc42-5666.3-llvmgcc42-2336.1-Linux-120724.tar.xz"
- "dzip.sh"
-- "openssl-mac32-utils.zip"
-- "libevent-mac32-utils.zip"
+- "openssl-mac64-utils.zip"
+- "libevent-mac64-utils.zip"
script: |
INSTDIR="$HOME/install"
TBDIR="$INSTDIR/TorBrowserBundle.app/TorBrowser"
@@ -46,15 +46,15 @@ script: |
sudo dpkg -i *.deb
tar xaf multiarch-darwin*tar.xz
export PATH="$PATH:$HOME/build/apple-osx/bin/"
- unzip -d $INSTDIR openssl-mac32-utils.zip
- unzip -d $INSTDIR libevent-mac32-utils.zip
+ unzip -d $INSTDIR openssl-mac64-utils.zip
+ unzip -d $INSTDIR libevent-mac64-utils.zip
cp $INSTDIR/libevent/lib/libevent-*.dylib $TBDIR/Tor/
LIBEVENT_FILE=`basename $INSTDIR/libevent/lib/libevent-*.dylib`
# Building tor
# XXX Clean up these flags?
- export CFLAGS="-I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -mmacosx-version-min=10.5"
- export LDFLAGS="-L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -mmacosx-version-min=10.5"
+ export CFLAGS="-m64 -I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -mmacosx-version-min=10.5"
+ export LDFLAGS="-m64 -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -mmacosx-version-min=10.5"
cd tor
git update-index --refresh -q
export GIT_COMMITTER_NAME="nobody"
@@ -94,5 +94,5 @@ script: |
# Grabbing the result
cd $INSTDIR
- ~/build/dzip.sh tor-mac32-gbuilt.zip TorBrowserBundle.app
- cp tor-mac32-gbuilt.zip $OUTDIR/
+ ~/build/dzip.sh tor-mac64-gbuilt.zip TorBrowserBundle.app
+ cp tor-mac64-gbuilt.zip $OUTDIR/
diff --git a/gitian/descriptors/mac/gitian-utils.yml b/gitian/descriptors/mac/gitian-utils.yml
index 785d88c..f96b5ec 100644
--- a/gitian/descriptors/mac/gitian-utils.yml
+++ b/gitian/descriptors/mac/gitian-utils.yml
@@ -34,10 +34,12 @@ script: |
export PATH="$PATH:$HOME/build/apple-osx/bin/"
# For OpenSSL
ln -s ~/build/apple-osx/bin/apple-osx-gcc ~/build/apple-osx/bin/i686-apple-darwin11-cc
+ #For gmp, need to trick it so it knows we're doing a 64 bit build
+ for i in ~/build/apple-osx/bin/i686-apple-darwin11-*; do j=`echo $i | sed 's/i686/x86_64/'`; ln -s $i $j; done;
# XXX Clean up these flags?
- export CFLAGS="-I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -mmacosx-version-min=10.5"
- export CXXFLAGS="-I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/i686-apple-darwin10/4.2.1 -mmacosx-version-min=10.5"
+ export CFLAGS="-m64 -I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -mmacosx-version-min=10.5"
+ export CXXFLAGS="-m64 -I/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/include/ -I/usr/lib/gcc/i686-apple-darwin10/4.2.1/include/ -I. -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/i686-apple-darwin10/4.2.1 -mmacosx-version-min=10.5"
export LDFLAGS="-L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/ -L/usr/lib/apple/SDKs/MacOSX10.6.sdk/usr/lib/system/ -mmacosx-version-min=10.5"
# Building Libevent
@@ -54,7 +56,7 @@ script: |
cd openssl-*
find -type f | xargs touch --date="$REFERENCE_DATETIME"
# TODO: Add enable-ec_nistp_64_gcc_128 for 64bit OS X.
- ./Configure --cross-compile-prefix=i686-apple-darwin11- $CFLAGS darwin-i386-cc --prefix=$INSTDIR/openssl
+ ./Configure --cross-compile-prefix=i686-apple-darwin11- $CFLAGS darwin64-x86_64-cc --prefix=$INSTDIR/openssl enable-ec_nistp_64_gcc_128
# Using $MAKEOPTS breaks the build. Might be the issue mentioned on
# http://cblfs.cross-lfs.org/index.php/OpenSSL.
make
@@ -65,15 +67,15 @@ script: |
tar xjf gmp.tar.bz2
cd gmp-*
find -type f | xargs touch --date="$REFERENCE_DATETIME"
- ./configure --host=i686-apple-darwin11 --prefix=$INSTDIR/gmp --disable-static --enable-shared --enable-cxx
+ ./configure --host=x86_64-apple-darwin11 --prefix=$INSTDIR/gmp --disable-static --enable-shared --enable-cxx
make
make install
cd ..
# Grabbing the results
cd $INSTDIR
- ~/build/dzip.sh openssl-$OPENSSL_VER-mac32-utils.zip openssl
- ~/build/dzip.sh libevent-${LIBEVENT_TAG#release-}-mac32-utils.zip libevent
- ~/build/dzip.sh gmp-$GMP_VER-mac32-utils.zip gmp
+ ~/build/dzip.sh openssl-$OPENSSL_VER-mac64-utils.zip openssl
+ ~/build/dzip.sh libevent-${LIBEVENT_TAG#release-}-mac64-utils.zip libevent
+ ~/build/dzip.sh gmp-$GMP_VER-mac64-utils.zip gmp
cp *utils.zip $OUTDIR/
diff --git a/gitian/mkbundle-mac.sh b/gitian/mkbundle-mac.sh
index 9c5d99b..c8830af 100755
--- a/gitian/mkbundle-mac.sh
+++ b/gitian/mkbundle-mac.sh
@@ -103,9 +103,9 @@ fi
cd $GITIAN_DIR
-if [ ! -f inputs/openssl-$OPENSSL_VER-mac32-utils.zip -o \
- ! -f inputs/libevent-${LIBEVENT_TAG_ORIG#release-}-mac32-utils.zip -o \
- ! -f inputs/gmp-$GMP_VER-mac32-utils.zip ];
+if [ ! -f inputs/openssl-$OPENSSL_VER-mac64-utils.zip -o \
+ ! -f inputs/libevent-${LIBEVENT_TAG_ORIG#release-}-mac64-utils.zip -o \
+ ! -f inputs/gmp-$GMP_VER-mac64-utils.zip ];
then
echo
echo "****** Starting Utilities Component of Mac Bundle (1/5 for Mac) ******"
@@ -119,9 +119,9 @@ then
cd inputs
cp -a ../build/out/*-utils.zip .
- ln -sf openssl-$OPENSSL_VER-mac32-utils.zip openssl-mac32-utils.zip
- ln -sf libevent-${LIBEVENT_TAG_ORIG#release-}-mac32-utils.zip libevent-mac32-utils.zip
- ln -sf gmp-$GMP_VER-mac32-utils.zip gmp-mac32-utils.zip
+ ln -sf openssl-$OPENSSL_VER-mac64-utils.zip openssl-mac64-utils.zip
+ ln -sf libevent-${LIBEVENT_TAG_ORIG#release-}-mac64-utils.zip libevent-mac64-utils.zip
+ ln -sf gmp-$GMP_VER-mac64-utils.zip gmp-mac64-utils.zip
cd ..
#cp -a result/utils-mac-res.yml inputs/
else
@@ -132,13 +132,13 @@ else
# We might have built the utilities in the past but maybe the links are
# pointing to the wrong version. Refresh them.
cd inputs
- ln -sf openssl-$OPENSSL_VER-mac32-utils.zip openssl-mac32-utils.zip
- ln -sf libevent-${LIBEVENT_TAG_ORIG#release-}-mac32-utils.zip libevent-mac32-utils.zip
- ln -sf gmp-$GMP_VER-mac32-utils.zip gmp-mac32-utils.zip
+ ln -sf openssl-$OPENSSL_VER-mac64-utils.zip openssl-mac64-utils.zip
+ ln -sf libevent-${LIBEVENT_TAG_ORIG#release-}-mac64-utils.zip libevent-mac64-utils.zip
+ ln -sf gmp-$GMP_VER-mac64-utils.zip gmp-mac64-utils.zip
cd ..
fi
-if [ ! -f inputs/tor-mac32-gbuilt.zip ];
+if [ ! -f inputs/tor-mac64-gbuilt.zip ];
then
echo
echo "****** Starting Tor Component of Mac Bundle (2/5 for Mac) ******"
@@ -159,7 +159,7 @@ else
echo
fi
-if [ ! -f inputs/tor-browser-mac32-gbuilt.zip ];
+if [ ! -f inputs/tor-browser-mac64-gbuilt.zip ];
then
echo
echo "****** Starting TorBrowser Component of Mac Bundle (3/5 for Mac) ******"
@@ -181,7 +181,7 @@ else
echo
fi
-if [ ! -f inputs/pluggable-transports-mac32-gbuilt.zip ];
+if [ ! -f inputs/pluggable-transports-mac64-gbuilt.zip ];
then
echo
echo "****** Starting Pluggable Transports Component of Mac Bundle (4/5 for Mac) ******"
1
0
[tor-browser-bundle/master] Merge remote-tracking branch 'origin/master'
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit ab8da1c4a840f30f37873132258edc3f9711554b
Merge: 912a830 9f0cacb
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Thu Oct 30 13:47:37 2014 -0700
Merge remote-tracking branch 'origin/master'
gitian/versions.alpha | 3 +++
1 file changed, 3 insertions(+)
1
0
[tor-browser-bundle/master] Merge remote-tracking branch 'tjr/tjr-64bit'
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit 912a8305b26ce0b1cbc80c4014b4de3ada898991
Merge: af7bd8e f1f4a2a
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Wed Oct 29 15:14:09 2014 -0700
Merge remote-tracking branch 'tjr/tjr-64bit'
Conflicts:
gitian/descriptors/mac/gitian-pluggable-transports.yml
Bundle-Data/mac-tor.sh | 1 -
gitian/descriptors/mac/gitian-bundle.yml | 9 +++-----
gitian/descriptors/mac/gitian-firefox.yml | 3 ---
.../mac/gitian-pluggable-transports.yml | 16 ++++++-------
gitian/descriptors/mac/gitian-tor.yml | 16 ++++++-------
gitian/descriptors/mac/gitian-utils.yml | 16 +++++++------
gitian/mkbundle-mac.sh | 24 ++++++++++----------
7 files changed, 40 insertions(+), 45 deletions(-)
diff --cc gitian/descriptors/mac/gitian-pluggable-transports.yml
index 4c25f07,17aef86..6201230
--- a/gitian/descriptors/mac/gitian-pluggable-transports.yml
+++ b/gitian/descriptors/mac/gitian-pluggable-transports.yml
@@@ -48,10 -42,8 +48,10 @@@ files
- "apple-uni-sdk-10.6_20110407-0.flosoft1_i386.deb"
- "multiarch-darwin11-cctools127.2-gcc42-5666.3-llvmgcc42-2336.1-Linux-120724.tar.xz"
- "dzip.sh"
- - "gmp-mac32-utils.zip"
- - "openssl-mac32-utils.zip"
+- "go.crypto.tar.bz2"
+- "go.net.tar.bz2"
+ - "gmp-mac64-utils.zip"
+ - "openssl-mac64-utils.zip"
script: |
INSTDIR="$HOME/install"
TBDIR="$INSTDIR/TorBrowserBundle.app/TorBrowser"
@@@ -253,53 -245,7 +253,53 @@@
cp -a README doc/*.1 $TBDIR/Docs/meek
cd ..
+ # Building go ed25519
+ cd ed25519
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/github.com/agl/"
+ ln -sf "$PWD" "$GOPATH/src/github.com/agl/ed25519"
+ go install github.com/agl/ed25519/extra25519
+ cd ..
+
+ # Building go siphash
+ cd siphash
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/github.com/dchest/"
+ ln -sf "$PWD" "$GOPATH/src/github.com/dchest/siphash"
+ go install github.com/dchest/siphash
+ cd ..
+
+ # Building go.crypto
+ tar xjf go.crypto.tar.bz2
+ cd go.crypto
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/code.google.com/p/"
+ ln -sf "$PWD" "$GOPATH/src/code.google.com/p/go.crypto"
+ go install code.google.com/p/go.crypto/curve25519
+ go install code.google.com/p/go.crypto/hkdf
+ go install code.google.com/p/go.crypto/nacl/secretbox
+ cd ..
+
+ # Building go.net
+ tar xjf go.net.tar.bz2
+ cd go.net
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/code.google.com/p/"
+ ln -sf "$PWD" "$GOPATH/src/code.google.com/p/go.net"
+ go install code.google.com/p/go.net/proxy
+ cd ..
+
+ # Building obfs4proxy
+ cd obfs4
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/git.torproject.org/pluggable-transports"
+ ln -sf "$PWD" "$GOPATH/src/git.torproject.org/pluggable-transports/obfs4.git"
+ cd obfs4proxy
+ go build -ldflags '-s'
+ cp -a obfs4proxy $PTDIR
+ cd ../..
+
# Grabbing the result
cd $INSTDIR
- ~/build/dzip.sh pluggable-transports-mac$GBUILD_BITS-gbuilt.zip TorBrowserBundle.app
- cp pluggable-transports-mac$GBUILD_BITS-gbuilt.zip $OUTDIR/
+ ~/build/dzip.sh pluggable-transports-mac64-gbuilt.zip TorBrowserBundle.app
+ cp pluggable-transports-mac64-gbuilt.zip $OUTDIR/
1
0
[tor-browser-bundle/master] Bump obfs4 related tags/commits for 4.5-alpha.
by gk@torproject.org 30 Oct '14
by gk@torproject.org 30 Oct '14
30 Oct '14
commit 9f0cacb1cf6a075e91e4da1a4f56d31cd30b33cf
Author: Georg Koppen <gk(a)torproject.org>
Date: Thu Oct 30 13:56:04 2014 +0000
Bump obfs4 related tags/commits for 4.5-alpha.
---
gitian/versions.alpha | 3 +++
1 file changed, 3 insertions(+)
diff --git a/gitian/versions.alpha b/gitian/versions.alpha
index 6c49137..c4b65c3 100755
--- a/gitian/versions.alpha
+++ b/gitian/versions.alpha
@@ -27,6 +27,9 @@ TXSOCKSX_TAG=216eb0894a1755872f4789f9458aa6cf543b8433 # unsigned habnabit/1.13.0
GOPTLIB_TAG=0.2
MEEK_TAG=0.11
FAKETIME_TAG=70aa6b394d9341522dffe8a5a5cf5929e82cc6b9 # unsigned v0.9.6
+GOED25519_TAG=c4161f4c7483313562781c61b9a20aba73daf9de
+GOSIPHASH_TAG=42ba037e748c9062a75e0924705c43b893edefcd
+OBFS4_TAG=0.0.3
GITIAN_TAG=tor-browser-builder-3.x-7
1
0
[torbutton/master] Bug #5926: Allow spoofing of javascript locale to en-US.
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit da3286e36773c5ed7e0519dbc4956ef15ee407ff
Author: Arthur Edelstein <arthuredelstein(a)gmail.com>
Date: Fri Oct 10 15:41:19 2014 -0700
Bug #5926: Allow spoofing of javascript locale to en-US.
---
src/chrome/content/torbutton.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/chrome/content/torbutton.js b/src/chrome/content/torbutton.js
index 44020ec..7fddf07 100644
--- a/src/chrome/content/torbutton.js
+++ b/src/chrome/content/torbutton.js
@@ -2030,6 +2030,7 @@ function torbutton_update_fingerprinting_prefs() {
m_tb_prefs.setCharPref("intl.accept_languages", "en-us, en");
m_tb_prefs.setCharPref("intl.accept_charsets", "iso-8859-1,*,utf-8");
m_tb_prefs.setCharPref("intl.charsetmenu.browser.cache", "UTF-8");
+ m_tb_prefs.setCharPref("javascript.default_locale", "en-US");
} else {
if(m_tb_prefs.prefHasUserValue("intl.accept_languages"))
m_tb_prefs.clearUserPref("intl.accept_languages");
@@ -2037,6 +2038,8 @@ function torbutton_update_fingerprinting_prefs() {
m_tb_prefs.clearUserPref("intl.charsetmenu.browser.cache");
if(m_tb_prefs.prefHasUserValue("intl.accept_charsets"))
m_tb_prefs.clearUserPref("intl.accept_charsets");
+ if(m_tb_prefs.prefHasUserValue("javascript.default_locale"))
+ m_tb_prefs.clearUserPref("javascript.default_locale");
}
} else {
m_tb_prefs.setIntPref("browser.display.max_font_attempts",-1);
1
0
[tor-browser/tor-browser-31.2.0esr-4.5-1] Bug #11955 Backport certificate pinning
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit cd9887977227df33462e755200ac6f6ade351bea
Author: Camilo Viecco <cviecco(a)mozilla.com>
Date: Thu Jun 20 10:35:43 2013 -0700
Bug #11955 Backport certificate pinning
Includes the following Mozilla patches, some modified for Tor Browser:
Bug 744204 - Allow Key pining part 1 - Built-in Pinning Service. r=keeler
Bug 744204 - Allow Certificate key pinning Part 2 - Certverifier Interface. r=keeler
--HG--
extra : rebase_source : 2f9748ba0b241c697e22b7ff72f2f5a0fad4a2ca
Bug 998057: Add test pinset to the pin generator (r=cviecco)
--HG--
rename : security/manager/ssl/tests/unit/tlsserver/default-ee.der => security/manager/boot/src/default-ee.der
Bug 998057: Add tests for certificate pinning (r=cviecco,dkeeler)
Bug 1002696 - Minimum set of changes to make genHPKPStaticPins.js productionizable. r=cviecco, dkeeler
--HG--
rename : security/manager/boot/src/PreloadedHPKPins.json => security/manager/tools/PreloadedHPKPins.json
rename : security/manager/boot/src/genHPKPStaticPins.js => security/manager/tools/genHPKPStaticPins.js
Bug 951315 - Add telemetry to PK pinning. r=dkeeler
Bug 1006107 - Disable pining by default, setup pinning for *.addons.mozilla.org. r=dkeeler
Tor project: only patching two files:
security/manager/ssl/src/nsNSSComponent.cpp
netwerk/base/public/security-prefs.js
--HG--
extra : rebase_source : 93b1dbd5dc31490424060729a3941deffa8ee1d5
Bug 772756: Implement sha1 support, import Chrome's pinsets wholesale, add test mode (r=cviecco,keeler)
Tor project, we only patch:
security/manager/ssl/tests/unit/test_pinning.js
security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp
security/manager/ssl/tests/unit/tlsserver/default-ee.der
security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
security/manager/ssl/tests/unit/tlsserver/other-test-ca.der
security/manager/ssl/tests/unit/tlsserver/test-ca.der
Bug 1009720: Telemetry for CERT_PINNING_TEST_RESULTS (r=keeler)
Bug 1007844: Implement per-host telemetry for pin violations for AMO and aus4 (r=keeler)
Only patching toolkit/components/telemetry/Histograms.json
Bug 1011269: Add CertVerifier::pinningEnforceTestMode (r=keeler)
Tor project, only commit:
security/certverifier/CertVerifier.cpp
security/certverifier/CertVerifier.h
security/manager/ssl/src/nsNSSComponent.cpp
Bug 1012882: Restrict pinning to desktop (r=keeler)
Tor Bug #11955: Backport certificate pinning
Bring the following files up to date:
security/manager/boot/src/PublicKeyPinningService.cpp
security/manager/boot/src/PublicKeyPinningService.h
security/manager/boot/src/StaticHPKPins.h
security/manager/ssl/tests/unit/test_pinning.js
security/manager/tools/PreloadedHPKPins.json
security/manager/tools/genHPKPStaticPins.js
security/pkix/include/pkix/Time.h
security/pkix/lib/pkixtime.cpp
---
.gitignore | 2 +-
browser/app/profile/firefox.js | 3 +
modules/libpref/src/init/all.js | 3 +
security/apps/AppTrustDomain.h | 2 +
security/certverifier/CertVerifier.cpp | 225 +++-
security/certverifier/CertVerifier.h | 17 +-
security/certverifier/NSSCertDBTrustDomain.cpp | 35 +-
security/certverifier/NSSCertDBTrustDomain.h | 6 +-
security/certverifier/moz.build | 1 +
.../manager/boot/src/PublicKeyPinningService.cpp | 306 ++++++
.../boot/src/PublicKeyPinningService.cpp.rej | 11 +
.../manager/boot/src/PublicKeyPinningService.h | 35 +
security/manager/boot/src/StaticHPKPins.h | 1095 ++++++++++++++++++++
security/manager/boot/src/moz.build | 6 +
.../manager/ssl/src/SSLServerCertVerification.cpp | 5 +-
security/manager/ssl/src/SharedCertVerifier.h | 6 +-
security/manager/ssl/src/nsCMS.cpp | 5 +-
security/manager/ssl/src/nsNSSCertificate.cpp | 13 +-
security/manager/ssl/src/nsNSSCertificateDB.cpp | 19 +-
security/manager/ssl/src/nsNSSComponent.cpp | 12 +-
security/manager/ssl/src/nsUsageArrayHelper.cpp | 5 +-
security/manager/ssl/tests/unit/head_psm.js | 1 +
.../manager/ssl/tests/unit/test_cert_overrides.js | 2 +-
security/manager/ssl/tests/unit/test_pinning.js | 182 ++++
security/manager/ssl/tests/unit/tlsserver/cert8.db | Bin 65536 -> 65536 bytes
.../ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp | 11 +
.../ssl/tests/unit/tlsserver/default-ee.der | Bin 527 -> 639 bytes
.../ssl/tests/unit/tlsserver/generate_certs.sh | 17 +-
security/manager/ssl/tests/unit/tlsserver/key3.db | Bin 49152 -> 57344 bytes
.../ssl/tests/unit/tlsserver/other-test-ca.der | Bin 452 -> 452 bytes
.../manager/ssl/tests/unit/tlsserver/secmod.db | Bin 16384 -> 16384 bytes
.../manager/ssl/tests/unit/tlsserver/test-ca.der | Bin 440 -> 440 bytes
security/manager/ssl/tests/unit/xpcshell.ini | 4 +
security/manager/tools/PreloadedHPKPins.json | 247 +++++
security/manager/tools/genHPKPStaticPins.js | 576 ++++++++++
security/pkix/include/pkix/Result.h | 174 ++++
security/pkix/include/pkix/Time.h | 126 +++
security/pkix/include/pkix/pkixtypes.h | 5 +
security/pkix/lib/pkixbuild.cpp | 24 +
security/pkix/lib/pkixtime.cpp | 70 ++
toolkit/components/telemetry/Histograms.json | 32 +
41 files changed, 3198 insertions(+), 85 deletions(-)
diff --git a/.gitignore b/.gitignore
index 8df1754..6d17511 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,7 +13,7 @@ ID
.*.sw[a-z]
# User files that may appear at the root
-/.mozconfig*
+#/.mozconfig*
/mozconfig
/configure
/config.cache
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 2ec7f9a..b61756d 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1484,6 +1484,9 @@ pref("security.csp.speccompliant", true);
// Block insecure active content on https pages
pref("security.mixed_content.block_active_content", true);
+// 1 = allow MITM for certificate pinning checks.
+pref("security.cert_pinning.enforcement_level", 1);
+
// Override the Gecko-default value of false for Firefox.
pref("plain_text.wrap_long_lines", true);
diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js
index 8efad8f..8a389e3 100644
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1566,6 +1566,9 @@ pref("security.csp.experimentalEnabled", false);
pref("security.mixed_content.block_active_content", false);
pref("security.mixed_content.block_display_content", false);
+// Disable pinning checks by default.
+pref("security.cert_pinning.enforcement_level", 0);
+
// Modifier key prefs: default to Windows settings,
// menu access key = alt, accelerator key = control.
// Use 17 for Ctrl, 18 for Alt, 224 for Meta, 91 for Win, 0 for none. Mac settings in macprefs.js
diff --git a/security/apps/AppTrustDomain.h b/security/apps/AppTrustDomain.h
index 875c1db..d7e4734 100644
--- a/security/apps/AppTrustDomain.h
+++ b/security/apps/AppTrustDomain.h
@@ -35,6 +35,8 @@ public:
/*const*/ CERTCertificate* issuerCertToDup,
PRTime time,
/*optional*/ const SECItem* stapledOCSPresponse);
+ SECStatus IsChainValid(const CERTCertList* certChain) { return SECSuccess; }
+
private:
void* mPinArg; // non-owning!
mozilla::pkix::ScopedCERTCertificate mTrustedRoot;
diff --git a/security/certverifier/CertVerifier.cpp b/security/certverifier/CertVerifier.cpp
index b8b84d7..b2db9fc 100644
--- a/security/certverifier/CertVerifier.cpp
+++ b/security/certverifier/CertVerifier.cpp
@@ -11,9 +11,11 @@
#include "pkix/pkix.h"
#include "ExtendedValidation.h"
#include "NSSCertDBTrustDomain.h"
+#include "PublicKeyPinningService.h"
#include "cert.h"
#include "ocsp.h"
#include "secerr.h"
+#include "pk11pub.h"
#include "prerror.h"
#include "sslerr.h"
@@ -38,7 +40,8 @@ CertVerifier::CertVerifier(implementation_config ic,
#endif
ocsp_download_config odc,
ocsp_strict_config osc,
- ocsp_get_config ogc)
+ ocsp_get_config ogc,
+ pinning_enforcement_config pel)
: mImplementation(ic)
#ifndef NSS_NO_LIBPKIX
, mMissingCertDownloadEnabled(mcdc == missing_cert_download_on)
@@ -47,6 +50,7 @@ CertVerifier::CertVerifier(implementation_config ic,
, mOCSPDownloadEnabled(odc == ocsp_on)
, mOCSPStrict(osc == ocsp_strict)
, mOCSPGETEnabled(ogc == ocsp_get_enabled)
+ , mPinningEnforcementLevel(pel)
{
}
@@ -64,7 +68,6 @@ InitCertVerifierLog()
#endif
}
-#if 0
// Once we migrate to mozilla::pkix or change the overridable error
// logic this will become unnecesary.
static SECStatus
@@ -95,23 +98,102 @@ insertErrorIntoVerifyLog(CERTCertificate* cert, const PRErrorCode err,
return SECSuccess;
}
-#endif
+
+SECStatus
+IsCertBuiltInRoot(CERTCertificate* cert, bool& result) {
+ result = false;
+ ScopedPtr<PK11SlotList, PK11_FreeSlotList> slots;
+ slots = PK11_GetAllSlotsForCert(cert, nullptr);
+ if (!slots) {
+ if (PORT_GetError() == SEC_ERROR_NO_TOKEN) {
+ // no list
+ return SECSuccess;
+ }
+ return SECFailure;
+ }
+ for (PK11SlotListElement* le = slots->head; le; le = le->next) {
+ char* token = PK11_GetTokenName(le->slot);
+ PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
+ ("BuiltInRoot? subject=%s token=%s",cert->subjectName, token));
+ if (strcmp("Builtin Object Token", token) == 0) {
+ result = true;
+ return SECSuccess;
+ }
+ }
+ return SECSuccess;
+}
+
+struct ChainValidationCallbackState
+{
+ const char* hostname;
+ const CertVerifier::pinning_enforcement_config pinningEnforcementLevel;
+ const SECCertificateUsage usage;
+ const PRTime time;
+};
SECStatus chainValidationCallback(void* state, const CERTCertList* certList,
PRBool* chainOK)
{
+ ChainValidationCallbackState* callbackState =
+ reinterpret_cast<ChainValidationCallbackState*>(state);
+
*chainOK = PR_FALSE;
- PR_LOG(gCertVerifierLog, PR_LOG_DEBUG, ("verifycert: Inside the Callback \n"));
+ PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
+ ("verifycert: Inside the Callback \n"));
// On sanity failure we fail closed.
if (!certList) {
- PR_LOG(gCertVerifierLog, PR_LOG_DEBUG, ("verifycert: Short circuit, callback, "
- "sanity check failed \n"));
+ PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
+ ("verifycert: Short circuit, callback, sanity check failed \n"));
+ PR_SetError(PR_INVALID_STATE_ERROR, 0);
+ return SECFailure;
+ }
+ if (!callbackState) {
+ PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
+ ("verifycert: Short circuit, callback, no state! \n"));
PR_SetError(PR_INVALID_STATE_ERROR, 0);
return SECFailure;
}
- *chainOK = PR_TRUE;
+
+ if (callbackState->usage != certificateUsageSSLServer ||
+ callbackState->pinningEnforcementLevel == CertVerifier::pinningDisabled) {
+ PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
+ ("verifycert: Callback shortcut pel=%d \n",
+ callbackState->pinningEnforcementLevel));
+ *chainOK = PR_TRUE;
+ return SECSuccess;
+ }
+
+ for (CERTCertListNode* node = CERT_LIST_HEAD(certList);
+ !CERT_LIST_END(node, certList);
+ node = CERT_LIST_NEXT(node)) {
+ CERTCertificate* currentCert = node->cert;
+ if (CERT_LIST_END(CERT_LIST_NEXT(node), certList)) {
+ bool isBuiltInRoot = false;
+ SECStatus srv = IsCertBuiltInRoot(currentCert, isBuiltInRoot);
+ if (srv != SECSuccess) {
+ PR_LOG(gCertVerifierLog, PR_LOG_DEBUG, ("Is BuiltInRoot failure"));
+ return srv;
+ }
+ // If desired, the user can enable "allow user CA MITM mode", in which
+ // case key pinning is not enforced for certificates that chain to trust
+ // anchors that are not in Mozilla's root program
+ if (!isBuiltInRoot &&
+ (callbackState->pinningEnforcementLevel ==
+ CertVerifier::pinningAllowUserCAMITM)) {
+ *chainOK = PR_TRUE;
+ return SECSuccess;
+ }
+ }
+ }
+
+ const bool enforceTestMode = (callbackState->pinningEnforcementLevel ==
+ CertVerifier::pinningEnforceTestMode);
+ *chainOK = PublicKeyPinningService::
+ ChainHasValidPins(certList, callbackState->hostname, callbackState->time,
+ enforceTestMode);
+
return SECSuccess;
}
@@ -120,42 +202,41 @@ ClassicVerifyCert(CERTCertificate* cert,
const SECCertificateUsage usage,
const PRTime time,
void* pinArg,
+ ChainValidationCallbackState* callbackState,
/*optional out*/ ScopedCERTCertList* validationChain,
/*optional out*/ CERTVerifyLog* verifyLog)
{
SECStatus rv;
SECCertUsage enumUsage;
- if (validationChain) {
- switch(usage){
- case certificateUsageSSLClient:
- enumUsage = certUsageSSLClient;
- break;
- case certificateUsageSSLServer:
- enumUsage = certUsageSSLServer;
- break;
- case certificateUsageSSLCA:
- enumUsage = certUsageSSLCA;
- break;
- case certificateUsageEmailSigner:
- enumUsage = certUsageEmailSigner;
- break;
- case certificateUsageEmailRecipient:
- enumUsage = certUsageEmailRecipient;
- break;
- case certificateUsageObjectSigner:
- enumUsage = certUsageObjectSigner;
- break;
- case certificateUsageVerifyCA:
- enumUsage = certUsageVerifyCA;
- break;
- case certificateUsageStatusResponder:
- enumUsage = certUsageStatusResponder;
- break;
- default:
- PR_NOT_REACHED("unexpected usage");
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
+ switch (usage) {
+ case certificateUsageSSLClient:
+ enumUsage = certUsageSSLClient;
+ break;
+ case certificateUsageSSLServer:
+ enumUsage = certUsageSSLServer;
+ break;
+ case certificateUsageSSLCA:
+ enumUsage = certUsageSSLCA;
+ break;
+ case certificateUsageEmailSigner:
+ enumUsage = certUsageEmailSigner;
+ break;
+ case certificateUsageEmailRecipient:
+ enumUsage = certUsageEmailRecipient;
+ break;
+ case certificateUsageObjectSigner:
+ enumUsage = certUsageObjectSigner;
+ break;
+ case certificateUsageVerifyCA:
+ enumUsage = certUsageVerifyCA;
+ break;
+ case certificateUsageStatusResponder:
+ enumUsage = certUsageStatusResponder;
+ break;
+ default:
+ PR_NOT_REACHED("unexpected usage");
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
if (usage == certificateUsageSSLServer) {
// SSL server cert verification has always used CERT_VerifyCert, so we
@@ -168,13 +249,38 @@ ClassicVerifyCert(CERTCertificate* cert,
rv = CERT_VerifyCertificate(CERT_GetDefaultCertDB(), cert, true,
usage, time, pinArg, verifyLog, nullptr);
}
- if (rv == SECSuccess && validationChain) {
- PR_LOG(gCertVerifierLog, PR_LOG_DEBUG, ("VerifyCert: getting chain in 'classic' \n"));
- *validationChain = CERT_GetCertChainFromCert(cert, time, enumUsage);
- if (!*validationChain) {
- rv = SECFailure;
+
+ if (rv == SECSuccess &&
+ (validationChain || usage == certificateUsageSSLServer)) {
+ PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
+ ("VerifyCert: getting chain in 'classic' \n"));
+ ScopedCERTCertList certChain(CERT_GetCertChainFromCert(cert, time,
+ enumUsage));
+ if (!certChain) {
+ return SECFailure;
+ }
+ if (usage == certificateUsageSSLServer) {
+ PRBool chainOK = PR_FALSE;
+ SECStatus srv = chainValidationCallback(callbackState, certChain.get(),
+ &chainOK);
+ if (srv != SECSuccess) {
+ return srv;
+ }
+ if (chainOK != PR_TRUE) {
+ if (verifyLog) {
+ insertErrorIntoVerifyLog(cert,
+ SEC_ERROR_APPLICATION_CALLBACK_ERROR,
+ verifyLog);
+ }
+ PR_SetError(SEC_ERROR_APPLICATION_CALLBACK_ERROR, 0); // same as libpkix
+ return SECFailure;
+ }
+ }
+ if (rv == SECSuccess && validationChain) {
+ *validationChain = certChain.release();
}
}
+
return rv;
}
@@ -227,6 +333,7 @@ CertVerifier::MozillaPKIXVerifyCert(
const PRTime time,
void* pinArg,
const Flags flags,
+ ChainValidationCallbackState* callbackState,
/*optional*/ const SECItem* stapledOCSPResponse,
/*optional out*/ mozilla::pkix::ScopedCERTCertList* validationChain,
/*optional out*/ SECOidTag* evOidPolicy)
@@ -249,6 +356,10 @@ CertVerifier::MozillaPKIXVerifyCert(
return SECFailure;
}
+ CERTChainVerifyCallback callbackContainer;
+ callbackContainer.isChainValid = chainValidationCallback;
+ callbackContainer.isChainValidArg = callbackState;
+
NSSCertDBTrustDomain::OCSPFetching ocspFetching
= !mOCSPDownloadEnabled ||
(flags & FLAG_LOCAL_ONLY) ? NSSCertDBTrustDomain::NeverFetchOCSP
@@ -295,7 +406,7 @@ CertVerifier::MozillaPKIXVerifyCert(
ocspFetching == NSSCertDBTrustDomain::NeverFetchOCSP
? NSSCertDBTrustDomain::LocalOnlyOCSPForEV
: NSSCertDBTrustDomain::FetchOCSPForEV,
- mOCSPCache, pinArg);
+ mOCSPCache, pinArg, &callbackContainer);
rv = BuildCertChainForOneKeyUsage(trustDomain, cert, time,
KeyUsage::digitalSignature, // ECDHE/DHE
KeyUsage::keyEncipherment, // RSA
@@ -321,7 +432,7 @@ CertVerifier::MozillaPKIXVerifyCert(
// Now try non-EV.
NSSCertDBTrustDomain trustDomain(trustSSL, ocspFetching, mOCSPCache,
- pinArg);
+ pinArg, &callbackContainer);
rv = BuildCertChainForOneKeyUsage(trustDomain, cert, time,
KeyUsage::digitalSignature, // (EC)DHE
KeyUsage::keyEncipherment, // RSA
@@ -443,19 +554,25 @@ CertVerifier::MozillaPKIXVerifyCert(
SECStatus
CertVerifier::VerifyCert(CERTCertificate* cert,
- /*optional*/ const SECItem* stapledOCSPResponse,
const SECCertificateUsage usage,
const PRTime time,
void* pinArg,
+ const char* hostname,
const Flags flags,
+ /*optional in*/ const SECItem* stapledOCSPResponse,
/*optional out*/ ScopedCERTCertList* validationChain,
/*optional out*/ SECOidTag* evOidPolicy,
/*optional out*/ CERTVerifyLog* verifyLog)
{
+ ChainValidationCallbackState callbackState = { hostname,
+ mPinningEnforcementLevel,
+ usage,
+ time };
+
if (mImplementation == mozillapkix) {
return MozillaPKIXVerifyCert(cert, usage, time, pinArg, flags,
- stapledOCSPResponse, validationChain,
- evOidPolicy);
+ &callbackState, stapledOCSPResponse,
+ validationChain, evOidPolicy);
}
if (!cert)
@@ -581,7 +698,7 @@ CertVerifier::VerifyCert(CERTCertificate* cert,
CERTChainVerifyCallback callbackContainer;
if (usage == certificateUsageSSLServer) {
callbackContainer.isChainValid = chainValidationCallback;
- callbackContainer.isChainValidArg = nullptr;
+ callbackContainer.isChainValidArg = &callbackState;
cvin[i].type = cert_pi_chainVerifyCallback;
cvin[i].value.pointer.chainVerifyCallback = &callbackContainer;
++i;
@@ -685,8 +802,8 @@ CertVerifier::VerifyCert(CERTCertificate* cert,
if (mImplementation == classic) {
// XXX: we do not care about the localOnly flag (currently) as the
// caller that wants localOnly should disable and reenable the fetching.
- return ClassicVerifyCert(cert, usage, time, pinArg, validationChain,
- verifyLog);
+ return ClassicVerifyCert(cert, usage, time, pinArg, &callbackState,
+ validationChain, verifyLog);
}
#ifdef NSS_NO_LIBPKIX
@@ -826,9 +943,9 @@ CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert,
// CreateCertErrorRunnable assumes that CERT_VerifyCertName is only called
// if VerifyCert succeeded.
ScopedCERTCertList validationChain;
- SECStatus rv = VerifyCert(peerCert, stapledOCSPResponse,
- certificateUsageSSLServer, time,
- pinarg, 0, &validationChain, evOidPolicy);
+ SECStatus rv = VerifyCert(peerCert, certificateUsageSSLServer, time, pinarg,
+ hostname, 0, stapledOCSPResponse, &validationChain,
+ evOidPolicy, nullptr);
if (rv != SECSuccess) {
return rv;
}
diff --git a/security/certverifier/CertVerifier.h b/security/certverifier/CertVerifier.h
index 09ed4b0..270e9a1 100644
--- a/security/certverifier/CertVerifier.h
+++ b/security/certverifier/CertVerifier.h
@@ -12,6 +12,8 @@
namespace mozilla { namespace psm {
+struct ChainValidationCallbackState;
+
class CertVerifier
{
public:
@@ -24,11 +26,12 @@ public:
// *evOidPolicy == SEC_OID_UNKNOWN means the cert is NOT EV
// Only one usage per verification is supported.
SECStatus VerifyCert(CERTCertificate* cert,
- /*optional*/ const SECItem* stapledOCSPResponse,
const SECCertificateUsage usage,
const PRTime time,
void* pinArg,
+ const char* hostname,
const Flags flags = 0,
+ /*optional in*/ const SECItem* stapledOCSPResponse = nullptr,
/*optional out*/ mozilla::pkix::ScopedCERTCertList* validationChain = nullptr,
/*optional out*/ SECOidTag* evOidPolicy = nullptr ,
/*optional out*/ CERTVerifyLog* verifyLog = nullptr);
@@ -52,6 +55,13 @@ public:
mozillapkix = 2
};
+ enum pinning_enforcement_config {
+ pinningDisabled = 0,
+ pinningAllowUserCAMITM = 1,
+ pinningStrict = 2,
+ pinningEnforceTestMode = 3
+ };
+
enum missing_cert_download_config { missing_cert_download_off = 0, missing_cert_download_on };
enum crl_download_config { crl_local_only = 0, crl_download_allowed };
enum ocsp_download_config { ocsp_off = 0, ocsp_on };
@@ -65,7 +75,8 @@ public:
missing_cert_download_config ac, crl_download_config cdc,
#endif
ocsp_download_config odc, ocsp_strict_config osc,
- ocsp_get_config ogc);
+ ocsp_get_config ogc,
+ pinning_enforcement_config pinningEnforcementLevel);
~CertVerifier();
void ClearOCSPCache() { mOCSPCache.Clear(); }
@@ -78,6 +89,7 @@ public:
const bool mOCSPDownloadEnabled;
const bool mOCSPStrict;
const bool mOCSPGETEnabled;
+ const pinning_enforcement_config mPinningEnforcementLevel;
private:
SECStatus MozillaPKIXVerifyCert(CERTCertificate* cert,
@@ -85,6 +97,7 @@ private:
const PRTime time,
void* pinArg,
const Flags flags,
+ ChainValidationCallbackState* callbackState,
/*optional*/ const SECItem* stapledOCSPResponse,
/*optional out*/ mozilla::pkix::ScopedCERTCertList* validationChain,
/*optional out*/ SECOidTag* evOidPolicy);
diff --git a/security/certverifier/NSSCertDBTrustDomain.cpp b/security/certverifier/NSSCertDBTrustDomain.cpp
index 9bed2ce..fd2e363 100644
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -43,11 +43,13 @@ typedef ScopedPtr<SECMODModule, SECMOD_DestroyModule> ScopedSECMODModule;
NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType,
OCSPFetching ocspFetching,
OCSPCache& ocspCache,
- void* pinArg)
+ void* pinArg,
+ CERTChainVerifyCallback* checkChainCallback)
: mCertDBTrustType(certDBTrustType)
, mOCSPFetching(ocspFetching)
, mOCSPCache(ocspCache)
, mPinArg(pinArg)
+ , mCheckChainCallback(checkChainCallback)
{
}
@@ -475,6 +477,37 @@ NSSCertDBTrustDomain::VerifyAndMaybeCacheEncodedOCSPResponse(
return rv;
}
+SECStatus
+NSSCertDBTrustDomain::IsChainValid(const CERTCertList* certChain) {
+ SECStatus rv = SECFailure;
+
+ PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
+ ("NSSCertDBTrustDomain: Top of IsChainValid mCheckCallback=%p",
+ mCheckChainCallback));
+
+ if (!mCheckChainCallback) {
+ return SECSuccess;
+ }
+ if (!mCheckChainCallback->isChainValid) {
+ PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
+ return SECFailure;
+ }
+ PRBool chainOK;
+ rv = (mCheckChainCallback->isChainValid)(mCheckChainCallback->isChainValidArg,
+ certChain, &chainOK);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ // rv = SECSuccess only implies successful call, now is time
+ // to check the chain check status
+ // we should only return success if the chain is valid
+ if (chainOK) {
+ return SECSuccess;
+ }
+ PR_SetError(SEC_ERROR_APPLICATION_CALLBACK_ERROR, 0);
+ return SECFailure;
+}
+
namespace {
static char*
diff --git a/security/certverifier/NSSCertDBTrustDomain.h b/security/certverifier/NSSCertDBTrustDomain.h
index 979c3e2..c2f211d 100644
--- a/security/certverifier/NSSCertDBTrustDomain.h
+++ b/security/certverifier/NSSCertDBTrustDomain.h
@@ -57,7 +57,8 @@ public:
LocalOnlyOCSPForEV = 4,
};
NSSCertDBTrustDomain(SECTrustType certDBTrustType, OCSPFetching ocspFetching,
- OCSPCache& ocspCache, void* pinArg);
+ OCSPCache& ocspCache, void* pinArg,
+ CERTChainVerifyCallback* checkChainCallback = nullptr);
virtual SECStatus FindPotentialIssuers(
const SECItem* encodedIssuerName,
@@ -78,6 +79,8 @@ public:
PRTime time,
/*optional*/ const SECItem* stapledOCSPResponse);
+ virtual SECStatus IsChainValid(const CERTCertList* certChain);
+
private:
enum EncodedResponseSource {
ResponseIsFromNetwork = 1,
@@ -93,6 +96,7 @@ private:
const OCSPFetching mOCSPFetching;
OCSPCache& mOCSPCache; // non-owning!
void* mPinArg; // non-owning!
+ CERTChainVerifyCallback* mCheckChainCallback; // non-owning!
};
} } // namespace mozilla::psm
diff --git a/security/certverifier/moz.build b/security/certverifier/moz.build
index 5e99b12..434c3cc 100644
--- a/security/certverifier/moz.build
+++ b/security/certverifier/moz.build
@@ -17,6 +17,7 @@ if not CONFIG['NSS_NO_EV_CERTS']:
]
LOCAL_INCLUDES += [
+ '../manager/boot/src',
'../manager/ssl/src',
'../pkix/include',
]
diff --git a/security/manager/boot/src/PublicKeyPinningService.cpp b/security/manager/boot/src/PublicKeyPinningService.cpp
new file mode 100644
index 0000000..82abaaf
--- /dev/null
+++ b/security/manager/boot/src/PublicKeyPinningService.cpp
@@ -0,0 +1,306 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "PublicKeyPinningService.h"
+#include "pkix/nullptr.h"
+#include "StaticHPKPins.h" // autogenerated by genHPKPStaticpins.js
+
+#include "cert.h"
+#include "mozilla/Base64.h"
+#include "mozilla/Telemetry.h"
+#include "nsString.h"
+#include "nssb64.h"
+#include "pkix/pkixtypes.h"
+#include "prlog.h"
+#include "ScopedNSSTypes.h"
+#include "seccomon.h"
+#include "sechash.h"
+
+using namespace mozilla;
+using namespace mozilla::pkix;
+using namespace mozilla::psm;
+
+#if defined(PR_LOGGING)
+PRLogModuleInfo* gPublicKeyPinningLog =
+ PR_NewLogModule("PublicKeyPinningService");
+#endif
+
+/**
+ Computes in the location specified by base64Out the SHA256 digest
+ of the DER Encoded subject Public Key Info for the given cert
+*/
+static SECStatus
+GetBase64HashSPKI(const CERTCertificate* cert, SECOidTag hashType,
+ nsACString& hashSPKIDigest)
+{
+ hashSPKIDigest.Truncate();
+ Digest digest;
+ nsresult rv = digest.DigestBuf(hashType, cert->derPublicKey.data,
+ cert->derPublicKey.len);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return SECFailure;
+ }
+ rv = Base64Encode(nsDependentCSubstring(
+ reinterpret_cast<const char*>(digest.get().data),
+ digest.get().len),
+ hashSPKIDigest);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/*
+ * Returns true if a given cert matches any hashType fingerprints from the
+ * given pinset, false otherwise.
+ */
+static bool
+EvalCertWithHashType(const CERTCertificate* cert, SECOidTag hashType,
+ const StaticFingerprints* fingerprints)
+{
+ if (!fingerprints) {
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: No hashes found for hash type: %d\n", hashType));
+ return false;
+ }
+
+ nsAutoCString base64Out;
+ SECStatus srv = GetBase64HashSPKI(cert, hashType, base64Out);
+ if (srv != SECSuccess) {
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: GetBase64HashSPKI failed!\n"));
+ return false;
+ }
+
+ for (size_t i = 0; i < fingerprints->size; i++) {
+ if (base64Out.Equals(fingerprints->data[i])) {
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: found pin base_64 ='%s'\n", base64Out.get()));
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * Returns true if a given chain matches any hashType fingerprints from the
+ * given pinset, false otherwise.
+ */
+static bool
+EvalChainWithHashType(const CERTCertList* certList, SECOidTag hashType,
+ const StaticPinset* pinset)
+{
+ CERTCertificate* currentCert;
+
+ const StaticFingerprints* fingerprints = nullptr;
+ if (hashType == SEC_OID_SHA256) {
+ fingerprints = pinset->sha256;
+ } else if (hashType == SEC_OID_SHA1) {
+ fingerprints = pinset->sha1;
+ }
+ if (!fingerprints) {
+ return false;
+ }
+
+ CERTCertListNode* node;
+ for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
+ node = CERT_LIST_NEXT(node)) {
+ currentCert = node->cert;
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: certArray subject: '%s'\n",
+ currentCert->subjectName));
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: certArray common_name: '%s'\n",
+ CERT_GetCommonName(&(currentCert->issuer))));
+ if (EvalCertWithHashType(currentCert, hashType, fingerprints)) {
+ return true;
+ }
+ }
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG, ("pkpin: no matches found\n"));
+ return false;
+}
+
+/**
+ * Given a pinset and certlist, return true if one of the certificates on
+ * the list matches a fingerprint in the pinset, false otherwise.
+ */
+static bool
+EvalChainWithPinset(const CERTCertList* certList,
+ const StaticPinset* pinset) {
+ // SHA256 is more trustworthy, try that first.
+ if (EvalChainWithHashType(certList, SEC_OID_SHA256, pinset)) {
+ return true;
+ }
+ return EvalChainWithHashType(certList, SEC_OID_SHA1, pinset);
+}
+
+/**
+ Comparator for the is public key pinned host.
+*/
+static int
+TransportSecurityPreloadCompare(const void *key, const void *entry) {
+ const char *keyStr = reinterpret_cast<const char *>(key);
+ const TransportSecurityPreload *preloadEntry =
+ reinterpret_cast<const TransportSecurityPreload *>(entry);
+
+ return strcmp(keyStr, preloadEntry->mHost);
+}
+
+/**
+ * Check PKPins on the given certlist against the specified hostname
+ */
+static bool
+CheckPinsForHostname(const CERTCertList *certList, const char *hostname,
+ bool enforceTestMode)
+{
+ if (!certList) {
+ return false;
+ }
+ if (!hostname || hostname[0] == 0) {
+ return false;
+ }
+
+ TransportSecurityPreload *foundEntry = nullptr;
+ char *evalHost = const_cast<char*>(hostname);
+ char *evalPart;
+ // Notice how the (xx = strchr) prevents pins for unqualified domain names.
+ while (!foundEntry && (evalPart = strchr(evalHost, '.'))) {
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: Querying pinsets for host: '%s'\n", evalHost));
+ foundEntry = (TransportSecurityPreload *)bsearch(evalHost,
+ kPublicKeyPinningPreloadList,
+ sizeof(kPublicKeyPinningPreloadList) / sizeof(TransportSecurityPreload),
+ sizeof(TransportSecurityPreload),
+ TransportSecurityPreloadCompare);
+ if (foundEntry) {
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: Found pinset for host: '%s'\n", evalHost));
+ if (evalHost != hostname) {
+ if (!foundEntry->mIncludeSubdomains) {
+ // Does not apply to this host, continue iterating
+ foundEntry = nullptr;
+ }
+ }
+ } else {
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: Didn't find pinset for host: '%s'\n", evalHost));
+ }
+ // Add one for '.'
+ evalHost = evalPart + 1;
+ }
+
+ if (foundEntry && foundEntry->pinset) {
+ bool result = EvalChainWithPinset(certList, foundEntry->pinset);
+ bool retval = result;
+ Telemetry::ID histogram = foundEntry->mIsMoz
+ ? Telemetry::CERT_PINNING_MOZ_RESULTS
+ : Telemetry::CERT_PINNING_RESULTS;
+ if (foundEntry->mTestMode) {
+ histogram = foundEntry->mIsMoz
+ ? Telemetry::CERT_PINNING_MOZ_TEST_RESULTS
+ : Telemetry::CERT_PINNING_TEST_RESULTS;
+ if (!enforceTestMode) {
+ retval = true;
+ }
+ }
+ // We can collect per-host pinning violations for this host because it is
+ // operationally critical to Firefox.
+ if (foundEntry->mId != kUnknownId) {
+ int32_t bucket = foundEntry->mId * 2 + (result ? 1 : 0);
+ histogram = foundEntry->mTestMode
+ ? Telemetry::CERT_PINNING_MOZ_TEST_RESULTS_BY_HOST
+ : Telemetry::CERT_PINNING_MOZ_RESULTS_BY_HOST;
+ Telemetry::Accumulate(histogram, bucket);
+ } else {
+ Telemetry::Accumulate(histogram, result ? 1 : 0);
+ }
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: Pin check %s for %s host '%s' (mode=%s)\n",
+ result ? "passed" : "failed",
+ foundEntry->mIsMoz ? "mozilla" : "non-mozilla",
+ hostname, foundEntry->mTestMode ? "test" : "production"));
+ return retval;
+ }
+ return true; // No pinning information for this hostname
+}
+
+/**
+ * Extract all the DNS names for a host (including CN) and evaluate the
+ * certifiate pins against all of them (Currently is an OR so we stop
+ * evaluating at the first OK pin).
+ */
+static bool
+CheckChainAgainstAllNames(const CERTCertList* certList, bool enforceTestMode)
+{
+ PR_LOG(gPublicKeyPinningLog, PR_LOG_DEBUG,
+ ("pkpin: top of checkChainAgainstAllNames"));
+ CERTCertListNode* node = CERT_LIST_HEAD(certList);
+ if (!node) {
+ return false;
+ }
+ CERTCertificate* cert = node->cert;
+ if (!cert) {
+ return false;
+ }
+
+ ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+ if (!arena) {
+ return false;
+ }
+
+ bool hasValidPins = false;
+ CERTGeneralName* nameList;
+ CERTGeneralName* currentName;
+ nameList = CERT_GetConstrainedCertificateNames(cert, arena.get(), PR_TRUE);
+ if (!nameList) {
+ return false;
+ }
+
+ currentName = nameList;
+ do {
+ if (currentName->type == certDNSName
+ && currentName->name.other.data[0] != 0) {
+ // no need to cleaup, as the arena cleanup will do
+ char *hostName = (char *)PORT_ArenaAlloc(arena.get(),
+ currentName->name.other.len + 1);
+ if (!hostName) {
+ break;
+ }
+ // We use a temporary buffer as the hostname as returned might not be
+ // null terminated.
+ hostName[currentName->name.other.len] = 0;
+ memcpy(hostName, currentName->name.other.data,
+ currentName->name.other.len);
+ if (!hostName[0]) {
+ // cannot call CheckPinsForHostname on empty or null hostname
+ break;
+ }
+ if (CheckPinsForHostname(certList, hostName, enforceTestMode)) {
+ hasValidPins = true;
+ break;
+ }
+ }
+ currentName = CERT_GetNextGeneralName(currentName);
+ } while (currentName != nameList);
+
+ return hasValidPins;
+}
+
+bool
+PublicKeyPinningService::ChainHasValidPins(const CERTCertList* certList,
+ const char* hostname,
+ const PRTime time,
+ bool enforceTestMode)
+{
+ if (!certList) {
+ return false;
+ }
+ if (time > kPreloadPKPinsExpirationTime) {
+ return true;
+ }
+ if (!hostname || hostname[0] == 0) {
+ return CheckChainAgainstAllNames(certList, enforceTestMode);
+ }
+ return CheckPinsForHostname(certList, hostname, enforceTestMode);
+}
diff --git a/security/manager/boot/src/PublicKeyPinningService.cpp.rej b/security/manager/boot/src/PublicKeyPinningService.cpp.rej
new file mode 100644
index 0000000..e88f91b
--- /dev/null
+++ b/security/manager/boot/src/PublicKeyPinningService.cpp.rej
@@ -0,0 +1,11 @@
+diff a/security/manager/boot/src/PublicKeyPinningService.cpp b/security/manager/boot/src/PublicKeyPinningService.cpp (rejected hunks)
+@@ -296,7 +296,8 @@ PublicKeyPinningService::ChainHasValidPins(const CERTCertList* certList,
+ if (!certList) {
+ return false;
+ }
+- if (time > TimeFromElapsedSecondsAD(kPreloadPKPinsExpirationTime)) {
++ if (time > TimeFromEpochInSeconds(kPreloadPKPinsExpirationTime /
++ PR_USEC_PER_SEC)) {
+ return true;
+ }
+ if (!hostname || hostname[0] == 0) {
diff --git a/security/manager/boot/src/PublicKeyPinningService.h b/security/manager/boot/src/PublicKeyPinningService.h
new file mode 100644
index 0000000..978c5ec
--- /dev/null
+++ b/security/manager/boot/src/PublicKeyPinningService.h
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef PublicKeyPinningService_h
+#define PublicKeyPinningService_h
+
+#include "cert.h"
+
+namespace mozilla {
+namespace psm {
+
+class PublicKeyPinningService
+{
+public:
+ /**
+ * Returns true if the given (host, certList) passes pinning checks,
+ * false otherwise. If the host is pinned, return true if one of the keys in
+ * the given certificate chain matches the pin set specified by the
+ * hostname. If the hostname is null or empty evaluate against all the
+ * possible names for the EE cert (Common Name (CN) plus all DNS Name:
+ * subject Alt Name entries). The certList's head is the EE cert and the
+ * tail is the trust anchor.
+ * Note: if an alt name is a wildcard, it won't necessarily find a pinset
+ * that would otherwise be valid for it
+ */
+ static bool ChainHasValidPins(const CERTCertList* certList,
+ const char* hostname,
+ const PRTime,
+ bool enforceTestMode);
+};
+
+}} // namespace mozilla::psm
+
+#endif // PublicKeyPinningServiceService_h
diff --git a/security/manager/boot/src/StaticHPKPins.h b/security/manager/boot/src/StaticHPKPins.h
new file mode 100644
index 0000000..4506489
--- /dev/null
+++ b/security/manager/boot/src/StaticHPKPins.h
@@ -0,0 +1,1095 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*****************************************************************************/
+/* This is an automatically generated file. If you're not */
+/* PublicKeyPinningService.cpp, you shouldn't be #including it. */
+/*****************************************************************************/
+#include <stdint.h>
+/* AddTrust External Root */
+static const char kAddTrust_External_RootFingerprint[] =
+ "lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=";
+
+/* AddTrust Low-Value Services Root */
+static const char kAddTrust_Low_Value_Services_RootFingerprint[] =
+ "BStocQfshOhzA4JFLsKidFF0XXSFpX1vRk4Np6G2ryo=";
+
+/* AddTrust Public Services Root */
+static const char kAddTrust_Public_Services_RootFingerprint[] =
+ "OGHXtpYfzbISBFb/b8LrdwSxp0G0vZM6g3b14ZFcppg=";
+
+/* AddTrust Qualified Certificates Root */
+static const char kAddTrust_Qualified_Certificates_RootFingerprint[] =
+ "xzr8Lrp3DQy8HuQfJStS6Kk9ErctzOwDHY2DnL+Bink=";
+
+/* AffirmTrust Commercial */
+static const char kAffirmTrust_CommercialFingerprint[] =
+ "bEZLmlsjOl6HTadlwm8EUBDS3c/0V5TwtMfkqvpQFJU=";
+
+/* AffirmTrust Networking */
+static const char kAffirmTrust_NetworkingFingerprint[] =
+ "lAcq0/WPcPkwmOWl9sBMlscQvYSdgxhJGa6Q64kK5AA=";
+
+/* AffirmTrust Premium */
+static const char kAffirmTrust_PremiumFingerprint[] =
+ "x/Q7TPW3FWgpT4IrU3YmBfbd0Vyt7Oc56eLDy6YenWc=";
+
+/* AffirmTrust Premium ECC */
+static const char kAffirmTrust_Premium_ECCFingerprint[] =
+ "MhmwkRT/SVo+tusAwu/qs0ACrl8KVsdnnqCHo/oDfk8=";
+
+/* America Online Root Certification Authority 1 */
+static const char kAmerica_Online_Root_Certification_Authority_1Fingerprint[] =
+ "I4SdCUkj1EpIgbY6sYXpvhWqyO8sMETZNLx/JuLSzWk=";
+
+/* America Online Root Certification Authority 2 */
+static const char kAmerica_Online_Root_Certification_Authority_2Fingerprint[] =
+ "/PfamDYD6IhiAw2WE32OEwMbrftNVsH9TKzDOfa9uyo=";
+
+/* Baltimore CyberTrust Root */
+static const char kBaltimore_CyberTrust_RootFingerprint[] =
+ "Y9mvm0exBk1JoQ57f9Vm28jKo5lFm/woKcVxrYxu80o=";
+
+/* COMODO Certification Authority */
+static const char kCOMODO_Certification_AuthorityFingerprint[] =
+ "AG1751Vd2CAmRCxPGieoDomhmJy4ezREjtIZTBgZbV4=";
+
+/* COMODO ECC Certification Authority */
+static const char kCOMODO_ECC_Certification_AuthorityFingerprint[] =
+ "58qRu/uxh4gFezqAcERupSkRYBlBAvfcw7mEjGPLnNU=";
+
+/* Comodo AAA Services root */
+static const char kComodo_AAA_Services_rootFingerprint[] =
+ "vRU+17BDT2iGsXvOi76E7TQMcTLXAqj0+jGPdW7L1vM=";
+
+/* Comodo Secure Services root */
+static const char kComodo_Secure_Services_rootFingerprint[] =
+ "RpHL/ehKa2BS3b4VK7DCFq4lqG5XR4E9vA8UfzOFcL4=";
+
+/* Comodo Trusted Services root */
+static const char kComodo_Trusted_Services_rootFingerprint[] =
+ "4tiR77c4ZpEF1TDeXtcuKyrD9KZweLU0mz/ayklvXrg=";
+
+/* Cybertrust Global Root */
+static const char kCybertrust_Global_RootFingerprint[] =
+ "foeCwVDOOVL4AuY2AjpdPpW7XWjjPoWtsroXgSXOvxU=";
+
+/* DigiCert Assured ID Root CA */
+static const char kDigiCert_Assured_ID_Root_CAFingerprint[] =
+ "I/Lt/z7ekCWanjD0Cvj5EqXls2lOaThEA0H2Bg4BT/o=";
+
+/* DigiCert ECC Secure Server CA */
+static const char kDigiCert_ECC_Secure_Server_CAFingerprint[] =
+ "PZXN3lRAy+8tBKk2Ox6F7jIlnzr2Yzmwqc3JnyfXoCw=";
+
+/* DigiCert Global Root CA */
+static const char kDigiCert_Global_Root_CAFingerprint[] =
+ "r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=";
+
+/* DigiCert High Assurance EV Root CA */
+static const char kDigiCert_High_Assurance_EV_Root_CAFingerprint[] =
+ "WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=";
+
+/* End Entity Test Cert */
+static const char kEnd_Entity_Test_CertFingerprint[] =
+ "pVVgLk2kFI2WWRPwDMIX6YmzFhEW4DXQV/U5gP+feGA=";
+
+/* Entrust Root Certification Authority */
+static const char kEntrust_Root_Certification_AuthorityFingerprint[] =
+ "bb+uANN7nNc/j7R95lkXrwDg3d9C286sIMF8AnXuIJU=";
+
+/* Entrust.net Premium 2048 Secure Server CA */
+static const char kEntrust_net_Premium_2048_Secure_Server_CAFingerprint[] =
+ "HqPF5D7WbC2imDpCpKebHpBnhs6fG1hiFBmgBGOofTg=";
+
+/* Equifax Secure CA */
+static const char kEquifax_Secure_CAFingerprint[] =
+ "/1aAzXOlcD2gSBegdf1GJQanNQbEuBoVg+9UlHjSZHY=";
+
+/* Equifax Secure Global eBusiness CA */
+static const char kEquifax_Secure_Global_eBusiness_CAFingerprint[] =
+ "pvH5v4oKndwID7SbHvw9GhwsMtwOE2pbAMlzFvKj3BE=";
+
+/* Equifax Secure eBusiness CA 1 */
+static const char kEquifax_Secure_eBusiness_CA_1Fingerprint[] =
+ "JsGNxu6m9jL2drzrodjCtINS8pwtX82oeOCdy4Mt1uU=";
+
+/* GOOGLE_PIN_AlphaSSL_G2 */
+static const char kGOOGLE_PIN_AlphaSSL_G2Fingerprint[] =
+ "yxgiWGK++SFB9ySwt3M3qpn5HO0ZLFY5D+h+G/vcT/c=";
+
+/* GOOGLE_PIN_CryptoCat1 */
+static const char kGOOGLE_PIN_CryptoCat1Fingerprint[] =
+ "vKaqtTLWmVuXPVJE+0OqN5sRc4VCcSQHI/W3XTDVR24=";
+
+/* GOOGLE_PIN_EntrustRootEC1 */
+static const char kGOOGLE_PIN_EntrustRootEC1Fingerprint[] =
+ "/qK31kX7pz11PB7Jp4cMQOH3sMVh6Se5hb9xGGbjbyI=";
+
+/* GOOGLE_PIN_Entrust_G2 */
+static const char kGOOGLE_PIN_Entrust_G2Fingerprint[] =
+ "du6FkDdMcVQ3u8prumAo6t3i3G27uMP2EOhR8R0at/U=";
+
+/* GOOGLE_PIN_Entrust_SSL */
+static const char kGOOGLE_PIN_Entrust_SSLFingerprint[] =
+ "nsxRNo6G40YPZsKV5JQt1TCA8nseQQr/LRqp1Oa8fnw=";
+
+/* GOOGLE_PIN_GoDaddySecure */
+static const char kGOOGLE_PIN_GoDaddySecureFingerprint[] =
+ "MrZLZnJ6IGPkBm87lYywqu5Xal7O/ZUzmbuIdHMdlYc=";
+
+/* GOOGLE_PIN_Libertylavabitcom */
+static const char kGOOGLE_PIN_LibertylavabitcomFingerprint[] =
+ "WnKzsDXgqPtS1KvtImrhQPqcxfpmfssuI2cSJt4LMks=";
+
+/* GOOGLE_PIN_RapidSSL */
+static const char kGOOGLE_PIN_RapidSSLFingerprint[] =
+ "lT09gPUeQfbYrlxRtpsHrjDblj9Rpz+u7ajfCrg4qDM=";
+
+/* GOOGLE_PIN_Tor2web */
+static const char kGOOGLE_PIN_Tor2webFingerprint[] =
+ "99ogQzjMuUTBkG1ZP7FME0K4kvBEti8Buzu4nZjRItM=";
+
+/* GTE CyberTrust Global Root */
+static const char kGTE_CyberTrust_Global_RootFingerprint[] =
+ "EGn6R6CqT4z3ERscrqNl7q7RC//zJmDe9uBhS/rnCHU=";
+
+/* GeoTrust Global CA */
+static const char kGeoTrust_Global_CAFingerprint[] =
+ "h6801m+z8v3zbgkRHpq6L29Esgfzhj89C1SyUCOQmqU=";
+
+/* GeoTrust Global CA 2 */
+static const char kGeoTrust_Global_CA_2Fingerprint[] =
+ "F3VaXClfPS1y5vAxofB/QAxYi55YKyLxfq4xoVkNEYU=";
+
+/* GeoTrust Primary Certification Authority */
+static const char kGeoTrust_Primary_Certification_AuthorityFingerprint[] =
+ "SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=";
+
+/* GeoTrust Primary Certification Authority - G2 */
+static const char kGeoTrust_Primary_Certification_Authority___G2Fingerprint[] =
+ "vPtEqrmtAhAVcGtBIep2HIHJ6IlnWQ9vlK50TciLePs=";
+
+/* GeoTrust Primary Certification Authority - G3 */
+static const char kGeoTrust_Primary_Certification_Authority___G3Fingerprint[] =
+ "q5hJUnat8eyv8o81xTBIeB5cFxjaucjmelBPT2pRMo8=";
+
+/* GeoTrust Universal CA */
+static const char kGeoTrust_Universal_CAFingerprint[] =
+ "lpkiXF3lLlbN0y3y6W0c/qWqPKC7Us2JM8I7XCdEOCA=";
+
+/* GeoTrust Universal CA 2 */
+static const char kGeoTrust_Universal_CA_2Fingerprint[] =
+ "fKoDRlEkWQxgHlZ+UhSOlSwM/+iQAFMP4NlbbVDqrkE=";
+
+/* GlobalSign Root CA */
+static const char kGlobalSign_Root_CAFingerprint[] =
+ "K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q=";
+
+/* GlobalSign Root CA - R2 */
+static const char kGlobalSign_Root_CA___R2Fingerprint[] =
+ "iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0=";
+
+/* GlobalSign Root CA - R3 */
+static const char kGlobalSign_Root_CA___R3Fingerprint[] =
+ "cGuxAXyFXFkWm61cF4HPWX8S0srS9j0aSqN0k4AP+4A=";
+
+/* Go Daddy Class 2 CA */
+static const char kGo_Daddy_Class_2_CAFingerprint[] =
+ "VjLZe/p3W/PJnd6lL8JVNBCGQBZynFLdZSTIqcO0SJ8=";
+
+/* Go Daddy Root Certificate Authority - G2 */
+static const char kGo_Daddy_Root_Certificate_Authority___G2Fingerprint[] =
+ "Ko8tivDrEjiY90yGasP6ZpBU4jwXvHqVvQI0GS3GNdA=";
+
+/* GoogleBackup2048 */
+static const char kGoogleBackup2048Fingerprint[] =
+ "vq7OyjSnqOco9nyMCDGdy77eijM=";
+
+/* GoogleG2 */
+static const char kGoogleG2Fingerprint[] =
+ "Q9rWMO5T+KmAym79hfRqo3mQ4Oo=";
+
+/* Network Solutions Certificate Authority */
+static const char kNetwork_Solutions_Certificate_AuthorityFingerprint[] =
+ "MtGA7THJNVieydu7ciEjuIO1/C3BD5/KOpXXfhv8tTQ=";
+
+/* Starfield Class 2 CA */
+static const char kStarfield_Class_2_CAFingerprint[] =
+ "FfFKxFycfaIz00eRZOgTf+Ne4POK6FgYPwhBDqgqxLQ=";
+
+/* Starfield Root Certificate Authority - G2 */
+static const char kStarfield_Root_Certificate_Authority___G2Fingerprint[] =
+ "gI1os/q0iEpflxrOfRBVDXqVoWN3Tz7Dav/7IT++THQ=";
+
+/* Starfield Services Root Certificate Authority - G2 */
+static const char kStarfield_Services_Root_Certificate_Authority___G2Fingerprint[] =
+ "KwccWaCgrnaw6tsrrSO61FgLacNgG2MMLq8GE6+oP5I=";
+
+/* StartCom Certification Authority */
+static const char kStartCom_Certification_AuthorityFingerprint[] =
+ "5C8kvU039KouVrl52D0eZSGf4Onjo4Khs8tmyTlV3nU=";
+
+/* StartCom Certification Authority G2 */
+static const char kStartCom_Certification_Authority_G2Fingerprint[] =
+ "FSg5faISiQqDCwuVpZlozvI0dzd531GBzxD6ZHU0u2U=";
+
+/* TC TrustCenter Class 2 CA II */
+static const char kTC_TrustCenter_Class_2_CA_IIFingerprint[] =
+ "rPZeHWLLWKK6/W/6tA+4hpnEc5fPXLSD1C1pytNM1Is=";
+
+/* TC TrustCenter Class 3 CA II */
+static const char kTC_TrustCenter_Class_3_CA_IIFingerprint[] =
+ "k5KuIUmSSt435kXbof9L3dzaKykbYJdmnSr6XHo3Jhk=";
+
+/* TC TrustCenter Universal CA I */
+static const char kTC_TrustCenter_Universal_CA_IFingerprint[] =
+ "st71NirT+s0EvSkEekOET3ZwNOpIkvgOVr7mkCQ+JQI=";
+
+/* TC TrustCenter Universal CA III */
+static const char kTC_TrustCenter_Universal_CA_IIIFingerprint[] =
+ "q1zbM1Y5c1bW5pGXPCW4YYtl12qQSG6nqKXBd2f0Zzo=";
+
+/* TestSPKI */
+static const char kTestSPKIFingerprint[] =
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAA=";
+
+/* Thawte Premium Server CA */
+static const char kThawte_Premium_Server_CAFingerprint[] =
+ "9TwiBZgX3Zb0AGUWOdL4V+IQcKWavtkHlADZ9pVQaQA=";
+
+/* Thawte Server CA */
+static const char kThawte_Server_CAFingerprint[] =
+ "nG9qEjy6pO402+zu4kyX1ziHjLQj88InOQNCT10fbdU=";
+
+/* Tor1 */
+static const char kTor1Fingerprint[] =
+ "juNxSTv9UANmpC9kF5GKpmWNx3Y=";
+
+/* Tor2 */
+static const char kTor2Fingerprint[] =
+ "lia43lPolzSPVIq34Dw57uYcLD8=";
+
+/* Tor3 */
+static const char kTor3Fingerprint[] =
+ "rzEyQIKOh77j87n5bjWUNguXF8Y=";
+
+/* Twitter1 */
+static const char kTwitter1Fingerprint[] =
+ "Vv7zwhR9TtOIN/29MFI4cgHld40=";
+
+/* UTN DATACorp SGC Root CA */
+static const char kUTN_DATACorp_SGC_Root_CAFingerprint[] =
+ "QAL80xHQczFWfnG82XHkYEjI3OjRZZcRdTs9qiommvo=";
+
+/* UTN USERFirst Email Root CA */
+static const char kUTN_USERFirst_Email_Root_CAFingerprint[] =
+ "Laj56jRU0hFGRko/nQKNxMf7tXscUsc8KwVyovWZotM=";
+
+/* UTN USERFirst Hardware Root CA */
+static const char kUTN_USERFirst_Hardware_Root_CAFingerprint[] =
+ "TUDnr0MEoJ3of7+YliBMBVFB4/gJsv5zO7IxD9+YoWI=";
+
+/* UTN USERFirst Object Root CA */
+static const char kUTN_USERFirst_Object_Root_CAFingerprint[] =
+ "D+FMJksXu28NZT56cOs2Pb9UvhWAOe3a5cJXEd9IwQM=";
+
+/* VeriSign Class 3 Public Primary Certification Authority - G4 */
+static const char kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint[] =
+ "UZJDjsNp1+4M5x9cbbdflB779y5YRBcV6Z6rBMLIrO4=";
+
+/* VeriSign Class 3 Public Primary Certification Authority - G5 */
+static const char kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint[] =
+ "JbQbUG5JMJUoI6brnx0x3vZF6jilxsapbXGVfjhN8Fg=";
+
+/* VeriSign Universal Root Certification Authority */
+static const char kVeriSign_Universal_Root_Certification_AuthorityFingerprint[] =
+ "lnsM2T/O9/J84sJFdnrpsFp3awZJ+ZZbYpCWhGloaHI=";
+
+/* Verisign Class 1 Public Primary Certification Authority */
+static const char kVerisign_Class_1_Public_Primary_Certification_AuthorityFingerprint[] =
+ "LclHC+Y+9KzxvYKGCUArt7h72ZY4pkOTTohoLRvowwg=";
+
+/* Verisign Class 1 Public Primary Certification Authority - G3 */
+static const char kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint[] =
+ "IgduWu9Eu5pBaii30cRDItcFn2D+/6XK9sW+hEeJEwM=";
+
+/* Verisign Class 2 Public Primary Certification Authority - G2 */
+static const char kVerisign_Class_2_Public_Primary_Certification_Authority___G2Fingerprint[] =
+ "2oALgLKofTmeZvoZ1y/fSZg7R9jPMix8eVA6DH4o/q8=";
+
+/* Verisign Class 2 Public Primary Certification Authority - G3 */
+static const char kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint[] =
+ "cAajgxHlj7GTSEIzIYIQxmEloOSoJq7VOaxWHfv72QM=";
+
+/* Verisign Class 3 Public Primary Certification Authority */
+static const char kVerisign_Class_3_Public_Primary_Certification_AuthorityFingerprint[] =
+ "sRJBQqWhpaKIGcc1NA7/jJ4vgWj+47oYfyU7waOS1+I=";
+
+/* Verisign Class 3 Public Primary Certification Authority - G2 */
+static const char kVerisign_Class_3_Public_Primary_Certification_Authority___G2Fingerprint[] =
+ "AjyBzOjnxk+pQtPBUEhwfTXZu1uH9PVExb8bxWQ68vo=";
+
+/* Verisign Class 3 Public Primary Certification Authority - G3 */
+static const char kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint[] =
+ "SVqWumuteCQHvVIaALrOZXuzVVVeS7f4FGxxu6V+es4=";
+
+/* Verisign Class 4 Public Primary Certification Authority - G3 */
+static const char kVerisign_Class_4_Public_Primary_Certification_Authority___G3Fingerprint[] =
+ "VnuCEf0g09KD7gzXzgZyy52ZvFtIeljJ1U7Gf3fUqPU=";
+
+/* XRamp Global CA Root */
+static const char kXRamp_Global_CA_RootFingerprint[] =
+ "BRz5+pXkDpuD7a7aaWH2Fox4ecRmAXJHnN1RqwPOpis=";
+
+/* thawte Primary Root CA */
+static const char kthawte_Primary_Root_CAFingerprint[] =
+ "HXXQgxueCIU5TTLHob/bPbwcKOKw6DkfsTWYHbxbqTY=";
+
+/* thawte Primary Root CA - G2 */
+static const char kthawte_Primary_Root_CA___G2Fingerprint[] =
+ "Z9xPMvoQ59AaeaBzqgyeAhLsL/w9d54Kp/nA8OHCyJM=";
+
+/* thawte Primary Root CA - G3 */
+static const char kthawte_Primary_Root_CA___G3Fingerprint[] =
+ "GQbGEk27Q4V40A4GbVBUxsN/D6YCjAVUXgmU7drshik=";
+
+/* Pinsets are each an ordered list by the actual value of the fingerprint */
+struct StaticFingerprints {
+ const size_t size;
+ const char* const* data;
+};
+
+struct StaticPinset {
+ const StaticFingerprints* sha1;
+ const StaticFingerprints* sha256;
+};
+
+/* PreloadedHPKPins.json pinsets */
+static const char* kPinset_facebook_sha256_Data[] = {
+ kDigiCert_ECC_Secure_Server_CAFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_High_Assurance_EV_Root_CAFingerprint,
+};
+static const StaticFingerprints kPinset_facebook_sha256 = {
+ sizeof(kPinset_facebook_sha256_Data) / sizeof(const char*),
+ kPinset_facebook_sha256_Data
+};
+
+static const StaticPinset kPinset_facebook = {
+ nullptr,
+ &kPinset_facebook_sha256
+};
+
+static const char* kPinset_google_root_pems_sha256_Data[] = {
+ kEquifax_Secure_CAFingerprint,
+ kAmerica_Online_Root_Certification_Authority_2Fingerprint,
+ kComodo_Trusted_Services_rootFingerprint,
+ kCOMODO_ECC_Certification_AuthorityFingerprint,
+ kStartCom_Certification_AuthorityFingerprint,
+ kStartCom_Certification_AuthorityFingerprint,
+ kThawte_Premium_Server_CAFingerprint,
+ kCOMODO_Certification_AuthorityFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_Authority___G2Fingerprint,
+ kXRamp_Global_CA_RootFingerprint,
+ kAddTrust_Low_Value_Services_RootFingerprint,
+ kGeoTrust_Global_CA_2Fingerprint,
+ kStartCom_Certification_Authority_G2Fingerprint,
+ kStarfield_Class_2_CAFingerprint,
+ kthawte_Primary_Root_CA___G3Fingerprint,
+ kthawte_Primary_Root_CAFingerprint,
+ kEntrust_net_Premium_2048_Secure_Server_CAFingerprint,
+ kDigiCert_Assured_ID_Root_CAFingerprint,
+ kAmerica_Online_Root_Certification_Authority_1Fingerprint,
+ kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
+ kEquifax_Secure_eBusiness_CA_1Fingerprint,
+ kGlobalSign_Root_CAFingerprint,
+ kGo_Daddy_Root_Certificate_Authority___G2Fingerprint,
+ kStarfield_Services_Root_Certificate_Authority___G2Fingerprint,
+ kAffirmTrust_Premium_ECCFingerprint,
+ kNetwork_Solutions_Certificate_AuthorityFingerprint,
+ kAddTrust_Public_Services_RootFingerprint,
+ kUTN_DATACorp_SGC_Root_CAFingerprint,
+ kComodo_Secure_Services_rootFingerprint,
+ kGeoTrust_Primary_Certification_AuthorityFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
+ kUTN_USERFirst_Hardware_Root_CAFingerprint,
+ kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
+ kGo_Daddy_Class_2_CAFingerprint,
+ kVerisign_Class_4_Public_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_High_Assurance_EV_Root_CAFingerprint,
+ kBaltimore_CyberTrust_RootFingerprint,
+ kthawte_Primary_Root_CA___G2Fingerprint,
+ kAffirmTrust_CommercialFingerprint,
+ kEntrust_Root_Certification_AuthorityFingerprint,
+ kGlobalSign_Root_CA___R3Fingerprint,
+ kGeoTrust_Universal_CA_2Fingerprint,
+ kCybertrust_Global_RootFingerprint,
+ kStarfield_Root_Certificate_Authority___G2Fingerprint,
+ kGeoTrust_Global_CAFingerprint,
+ kGlobalSign_Root_CA___R2Fingerprint,
+ kTC_TrustCenter_Class_3_CA_IIFingerprint,
+ kAffirmTrust_NetworkingFingerprint,
+ kAddTrust_External_RootFingerprint,
+ kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
+ kGeoTrust_Universal_CAFingerprint,
+ kThawte_Server_CAFingerprint,
+ kEquifax_Secure_Global_eBusiness_CAFingerprint,
+ kTC_TrustCenter_Universal_CA_IIIFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_Global_Root_CAFingerprint,
+ kTC_TrustCenter_Class_2_CA_IIFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_AuthorityFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_AuthorityFingerprint,
+ kTC_TrustCenter_Universal_CA_IFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
+ kComodo_AAA_Services_rootFingerprint,
+ kAffirmTrust_PremiumFingerprint,
+ kAddTrust_Qualified_Certificates_RootFingerprint,
+};
+static const StaticFingerprints kPinset_google_root_pems_sha256 = {
+ sizeof(kPinset_google_root_pems_sha256_Data) / sizeof(const char*),
+ kPinset_google_root_pems_sha256_Data
+};
+
+static const StaticPinset kPinset_google_root_pems = {
+ nullptr,
+ &kPinset_google_root_pems_sha256
+};
+
+static const char* kPinset_mozilla_sha256_Data[] = {
+ kGeoTrust_Global_CA_2Fingerprint,
+ kthawte_Primary_Root_CA___G3Fingerprint,
+ kthawte_Primary_Root_CAFingerprint,
+ kDigiCert_Assured_ID_Root_CAFingerprint,
+ kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint,
+ kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
+ kGeoTrust_Primary_Certification_AuthorityFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
+ kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
+ kVerisign_Class_4_Public_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_High_Assurance_EV_Root_CAFingerprint,
+ kBaltimore_CyberTrust_RootFingerprint,
+ kthawte_Primary_Root_CA___G2Fingerprint,
+ kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint,
+ kGeoTrust_Universal_CA_2Fingerprint,
+ kGeoTrust_Global_CAFingerprint,
+ kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
+ kGeoTrust_Universal_CAFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_Global_Root_CAFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
+};
+static const StaticFingerprints kPinset_mozilla_sha256 = {
+ sizeof(kPinset_mozilla_sha256_Data) / sizeof(const char*),
+ kPinset_mozilla_sha256_Data
+};
+
+static const StaticPinset kPinset_mozilla = {
+ nullptr,
+ &kPinset_mozilla_sha256
+};
+
+static const char* kPinset_mozilla_services_sha256_Data[] = {
+ kDigiCert_Global_Root_CAFingerprint,
+};
+static const StaticFingerprints kPinset_mozilla_services_sha256 = {
+ sizeof(kPinset_mozilla_services_sha256_Data) / sizeof(const char*),
+ kPinset_mozilla_services_sha256_Data
+};
+
+static const StaticPinset kPinset_mozilla_services = {
+ nullptr,
+ &kPinset_mozilla_services_sha256
+};
+
+static const char* kPinset_mozilla_test_sha256_Data[] = {
+ kEnd_Entity_Test_CertFingerprint,
+};
+static const StaticFingerprints kPinset_mozilla_test_sha256 = {
+ sizeof(kPinset_mozilla_test_sha256_Data) / sizeof(const char*),
+ kPinset_mozilla_test_sha256_Data
+};
+
+static const StaticPinset kPinset_mozilla_test = {
+ nullptr,
+ &kPinset_mozilla_test_sha256
+};
+
+/* Chrome static pinsets */
+static const char* kPinset_test_sha1_Data[] = {
+ kTestSPKIFingerprint,
+};
+static const StaticFingerprints kPinset_test_sha1 = {
+ sizeof(kPinset_test_sha1_Data) / sizeof(const char*),
+ kPinset_test_sha1_Data
+};
+
+static const StaticPinset kPinset_test = {
+ &kPinset_test_sha1,
+ nullptr
+};
+
+static const char* kPinset_google_sha1_Data[] = {
+ kGoogleG2Fingerprint,
+ kGoogleBackup2048Fingerprint,
+};
+static const StaticFingerprints kPinset_google_sha1 = {
+ sizeof(kPinset_google_sha1_Data) / sizeof(const char*),
+ kPinset_google_sha1_Data
+};
+
+static const StaticPinset kPinset_google = {
+ &kPinset_google_sha1,
+ nullptr
+};
+
+static const char* kPinset_tor_sha1_Data[] = {
+ kTor1Fingerprint,
+ kTor2Fingerprint,
+ kTor3Fingerprint,
+};
+static const StaticFingerprints kPinset_tor_sha1 = {
+ sizeof(kPinset_tor_sha1_Data) / sizeof(const char*),
+ kPinset_tor_sha1_Data
+};
+
+static const char* kPinset_tor_sha256_Data[] = {
+ kDigiCert_High_Assurance_EV_Root_CAFingerprint,
+ kGOOGLE_PIN_RapidSSLFingerprint,
+};
+static const StaticFingerprints kPinset_tor_sha256 = {
+ sizeof(kPinset_tor_sha256_Data) / sizeof(const char*),
+ kPinset_tor_sha256_Data
+};
+
+static const StaticPinset kPinset_tor = {
+ &kPinset_tor_sha1,
+ &kPinset_tor_sha256
+};
+
+static const char* kPinset_twitterCom_sha1_Data[] = {
+ kTwitter1Fingerprint,
+};
+static const StaticFingerprints kPinset_twitterCom_sha1 = {
+ sizeof(kPinset_twitterCom_sha1_Data) / sizeof(const char*),
+ kPinset_twitterCom_sha1_Data
+};
+
+static const char* kPinset_twitterCom_sha256_Data[] = {
+ kVerisign_Class_2_Public_Primary_Certification_Authority___G2Fingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_Authority___G2Fingerprint,
+ kGeoTrust_Global_CA_2Fingerprint,
+ kDigiCert_Assured_ID_Root_CAFingerprint,
+ kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint,
+ kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
+ kVerisign_Class_1_Public_Primary_Certification_AuthorityFingerprint,
+ kGeoTrust_Primary_Certification_AuthorityFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
+ kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
+ kVerisign_Class_4_Public_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_High_Assurance_EV_Root_CAFingerprint,
+ kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint,
+ kGeoTrust_Universal_CA_2Fingerprint,
+ kGeoTrust_Global_CAFingerprint,
+ kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
+ kGeoTrust_Universal_CAFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_Global_Root_CAFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_AuthorityFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
+};
+static const StaticFingerprints kPinset_twitterCom_sha256 = {
+ sizeof(kPinset_twitterCom_sha256_Data) / sizeof(const char*),
+ kPinset_twitterCom_sha256_Data
+};
+
+static const StaticPinset kPinset_twitterCom = {
+ &kPinset_twitterCom_sha1,
+ &kPinset_twitterCom_sha256
+};
+
+static const char* kPinset_twitterCDN_sha1_Data[] = {
+ kTwitter1Fingerprint,
+};
+static const StaticFingerprints kPinset_twitterCDN_sha1 = {
+ sizeof(kPinset_twitterCDN_sha1_Data) / sizeof(const char*),
+ kPinset_twitterCDN_sha1_Data
+};
+
+static const char* kPinset_twitterCDN_sha256_Data[] = {
+ kVerisign_Class_2_Public_Primary_Certification_Authority___G2Fingerprint,
+ kComodo_Trusted_Services_rootFingerprint,
+ kCOMODO_Certification_AuthorityFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_Authority___G2Fingerprint,
+ kAddTrust_Low_Value_Services_RootFingerprint,
+ kUTN_USERFirst_Object_Root_CAFingerprint,
+ kGTE_CyberTrust_Global_RootFingerprint,
+ kGeoTrust_Global_CA_2Fingerprint,
+ kEntrust_net_Premium_2048_Secure_Server_CAFingerprint,
+ kDigiCert_Assured_ID_Root_CAFingerprint,
+ kVerisign_Class_1_Public_Primary_Certification_Authority___G3Fingerprint,
+ kVeriSign_Class_3_Public_Primary_Certification_Authority___G5Fingerprint,
+ kGlobalSign_Root_CAFingerprint,
+ kUTN_USERFirst_Email_Root_CAFingerprint,
+ kVerisign_Class_1_Public_Primary_Certification_AuthorityFingerprint,
+ kAddTrust_Public_Services_RootFingerprint,
+ kUTN_DATACorp_SGC_Root_CAFingerprint,
+ kComodo_Secure_Services_rootFingerprint,
+ kGeoTrust_Primary_Certification_AuthorityFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_Authority___G3Fingerprint,
+ kUTN_USERFirst_Hardware_Root_CAFingerprint,
+ kVeriSign_Class_3_Public_Primary_Certification_Authority___G4Fingerprint,
+ kVerisign_Class_4_Public_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_High_Assurance_EV_Root_CAFingerprint,
+ kBaltimore_CyberTrust_RootFingerprint,
+ kEntrust_Root_Certification_AuthorityFingerprint,
+ kVerisign_Class_2_Public_Primary_Certification_Authority___G3Fingerprint,
+ kGlobalSign_Root_CA___R3Fingerprint,
+ kGOOGLE_PIN_Entrust_G2Fingerprint,
+ kGeoTrust_Universal_CA_2Fingerprint,
+ kGeoTrust_Global_CAFingerprint,
+ kGlobalSign_Root_CA___R2Fingerprint,
+ kAddTrust_External_RootFingerprint,
+ kVeriSign_Universal_Root_Certification_AuthorityFingerprint,
+ kGeoTrust_Universal_CAFingerprint,
+ kGOOGLE_PIN_Entrust_SSLFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_Global_Root_CAFingerprint,
+ kVerisign_Class_3_Public_Primary_Certification_AuthorityFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
+ kComodo_AAA_Services_rootFingerprint,
+ kAddTrust_Qualified_Certificates_RootFingerprint,
+};
+static const StaticFingerprints kPinset_twitterCDN_sha256 = {
+ sizeof(kPinset_twitterCDN_sha256_Data) / sizeof(const char*),
+ kPinset_twitterCDN_sha256_Data
+};
+
+static const StaticPinset kPinset_twitterCDN = {
+ &kPinset_twitterCDN_sha1,
+ &kPinset_twitterCDN_sha256
+};
+
+static const char* kPinset_tor2web_sha256_Data[] = {
+ kGOOGLE_PIN_Tor2webFingerprint,
+ kGOOGLE_PIN_AlphaSSL_G2Fingerprint,
+};
+static const StaticFingerprints kPinset_tor2web_sha256 = {
+ sizeof(kPinset_tor2web_sha256_Data) / sizeof(const char*),
+ kPinset_tor2web_sha256_Data
+};
+
+static const StaticPinset kPinset_tor2web = {
+ nullptr,
+ &kPinset_tor2web_sha256
+};
+
+static const char* kPinset_cryptoCat_sha256_Data[] = {
+ kDigiCert_High_Assurance_EV_Root_CAFingerprint,
+ kGOOGLE_PIN_CryptoCat1Fingerprint,
+};
+static const StaticFingerprints kPinset_cryptoCat_sha256 = {
+ sizeof(kPinset_cryptoCat_sha256_Data) / sizeof(const char*),
+ kPinset_cryptoCat_sha256_Data
+};
+
+static const StaticPinset kPinset_cryptoCat = {
+ nullptr,
+ &kPinset_cryptoCat_sha256
+};
+
+static const char* kPinset_lavabit_sha256_Data[] = {
+ kGOOGLE_PIN_LibertylavabitcomFingerprint,
+};
+static const StaticFingerprints kPinset_lavabit_sha256 = {
+ sizeof(kPinset_lavabit_sha256_Data) / sizeof(const char*),
+ kPinset_lavabit_sha256_Data
+};
+
+static const StaticPinset kPinset_lavabit = {
+ nullptr,
+ &kPinset_lavabit_sha256
+};
+
+static const char* kPinset_dropbox_sha256_Data[] = {
+ kGOOGLE_PIN_EntrustRootEC1Fingerprint,
+ kThawte_Premium_Server_CAFingerprint,
+ kthawte_Primary_Root_CA___G3Fingerprint,
+ kthawte_Primary_Root_CAFingerprint,
+ kEntrust_net_Premium_2048_Secure_Server_CAFingerprint,
+ kDigiCert_Assured_ID_Root_CAFingerprint,
+ kGo_Daddy_Root_Certificate_Authority___G2Fingerprint,
+ kGOOGLE_PIN_GoDaddySecureFingerprint,
+ kGeoTrust_Primary_Certification_AuthorityFingerprint,
+ kGo_Daddy_Class_2_CAFingerprint,
+ kDigiCert_High_Assurance_EV_Root_CAFingerprint,
+ kthawte_Primary_Root_CA___G2Fingerprint,
+ kEntrust_Root_Certification_AuthorityFingerprint,
+ kGOOGLE_PIN_Entrust_G2Fingerprint,
+ kGeoTrust_Global_CAFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
+ kDigiCert_Global_Root_CAFingerprint,
+ kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
+};
+static const StaticFingerprints kPinset_dropbox_sha256 = {
+ sizeof(kPinset_dropbox_sha256_Data) / sizeof(const char*),
+ kPinset_dropbox_sha256_Data
+};
+
+static const StaticPinset kPinset_dropbox = {
+ nullptr,
+ &kPinset_dropbox_sha256
+};
+
+/* Domainlist */
+struct TransportSecurityPreload {
+ const char* mHost;
+ const bool mIncludeSubdomains;
+ const bool mTestMode;
+ const bool mIsMoz;
+ const int32_t mId;
+ const StaticPinset *pinset;
+};
+
+/* Sort hostnames for binary search. */
+static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
+ { "2mdn.net", true, false, false, -1, &kPinset_google_root_pems },
+ { "accounts.firefox.com", true, false, false, 4, &kPinset_mozilla_services },
+ { "accounts.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "addons.mozilla.net", true, false, true, 2, &kPinset_mozilla },
+ { "addons.mozilla.org", true, false, true, 1, &kPinset_mozilla },
+ { "admin.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "android.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "api.accounts.firefox.com", true, false, false, 5, &kPinset_mozilla_services },
+ { "api.twitter.com", true, false, false, -1, &kPinset_twitterCDN },
+ { "apis.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "appengine.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "aus4.mozilla.org", true, true, true, 3, &kPinset_mozilla },
+ { "blog.torproject.org", true, false, false, -1, &kPinset_tor },
+ { "business.twitter.com", true, false, false, -1, &kPinset_twitterCom },
+ { "cdn.mozilla.net", true, false, true, -1, &kPinset_mozilla },
+ { "cdn.mozilla.org", true, false, true, -1, &kPinset_mozilla },
+ { "chart.apis.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "check.torproject.org", true, false, false, -1, &kPinset_tor },
+ { "checkout.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "chrome-devtools-frontend.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "chrome.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "chromiumcodereview.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "cloud.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "code.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "codereview.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "codereview.chromium.org", true, false, false, -1, &kPinset_google_root_pems },
+ { "crypto.cat", false, true, false, -1, &kPinset_cryptoCat },
+ { "dev.twitter.com", true, false, false, -1, &kPinset_twitterCom },
+ { "dist.torproject.org", true, false, false, -1, &kPinset_tor },
+ { "dl.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "docs.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "domains.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "doubleclick.net", true, false, false, -1, &kPinset_google_root_pems },
+ { "drive.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "dropbox.com", false, false, false, -1, &kPinset_dropbox },
+ { "encrypted.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "exclude-subdomains.pinning.example.com", false, false, false, 0, &kPinset_mozilla_test },
+ { "facebook.com", true, true, false, -1, &kPinset_facebook },
+ { "g.co", true, false, false, -1, &kPinset_google_root_pems },
+ { "glass.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "gmail.com", false, false, false, -1, &kPinset_google_root_pems },
+ { "goo.gl", true, false, false, -1, &kPinset_google_root_pems },
+ { "google-analytics.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ac", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ad", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ae", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.af", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ag", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.am", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.as", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.at", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.az", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ba", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.be", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.bf", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.bg", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.bi", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.bj", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.bs", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.by", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ca", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cat", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cc", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cd", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cf", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cg", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ch", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ci", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cl", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cm", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.ao", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.bw", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.ck", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.cr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.hu", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.id", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.il", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.im", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.in", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.je", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.jp", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.ke", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.kr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.ls", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.ma", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.mz", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.nz", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.th", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.tz", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.ug", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.uk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.uz", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.ve", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.vi", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.za", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.zm", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.co.zw", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.af", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ag", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ai", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ar", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.au", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.bd", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.bh", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.bn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.bo", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.br", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.by", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.bz", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.cn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.co", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.cu", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.cy", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.do", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ec", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.eg", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.et", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.fj", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ge", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.gh", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.gi", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.gr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.gt", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.hk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.iq", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.jm", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.jo", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.kh", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.kw", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.lb", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ly", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.mt", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.mx", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.my", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.na", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.nf", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ng", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ni", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.np", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.nr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.om", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.pa", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.pe", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ph", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.pk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.pl", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.pr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.py", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.qa", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ru", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.sa", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.sb", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.sg", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.sl", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.sv", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.tj", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.tn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.tr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.tw", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ua", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.uy", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.vc", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.ve", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.com.vn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cv", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.cz", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.de", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.dj", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.dk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.dm", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.dz", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ee", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.es", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.fi", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.fm", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.fr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ga", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ge", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.gg", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.gl", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.gm", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.gp", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.gr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.gy", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.hk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.hn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.hr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ht", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.hu", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ie", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.im", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.info", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.iq", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.is", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.it", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.it.ao", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.je", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.jo", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.jobs", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.jp", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.kg", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ki", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.kz", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.la", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.li", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.lk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.lt", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.lu", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.lv", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.md", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.me", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.mg", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.mk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ml", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.mn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ms", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.mu", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.mv", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.mw", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ne", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ne.jp", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.net", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.nl", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.no", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.nr", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.nu", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.off.ai", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.pk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.pl", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.pn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ps", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.pt", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ro", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.rs", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ru", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.rw", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.sc", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.se", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.sh", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.si", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.sk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.sm", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.sn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.so", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.st", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.td", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.tg", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.tk", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.tl", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.tm", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.tn", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.to", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.tt", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.us", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.uz", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.vg", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.vu", true, false, false, -1, &kPinset_google_root_pems },
+ { "google.ws", true, false, false, -1, &kPinset_google_root_pems },
+ { "googleadservices.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "googleapis.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "googlecode.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "googlecommerce.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "googlegroups.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "googlemail.com", false, false, false, -1, &kPinset_google_root_pems },
+ { "googleplex.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "googlesyndication.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "googletagmanager.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "googletagservices.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "googleusercontent.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "goto.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "groups.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "gstatic.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "history.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "hostedtalkgadget.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "include-subdomains.pinning.example.com", true, false, false, -1, &kPinset_mozilla_test },
+ { "liberty.lavabit.com", true, true, false, -1, &kPinset_lavabit },
+ { "login.corp.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "mail.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "market.android.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "media.mozilla.com", true, false, true, -1, &kPinset_mozilla },
+ { "mobile.twitter.com", true, false, false, -1, &kPinset_twitterCom },
+ { "oauth.twitter.com", true, false, false, -1, &kPinset_twitterCom },
+ { "pinningtest.appspot.com", true, false, false, -1, &kPinset_test },
+ { "platform.twitter.com", true, false, false, -1, &kPinset_twitterCDN },
+ { "play.google.com", false, false, false, -1, &kPinset_google_root_pems },
+ { "plus.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "plus.sandbox.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "profiles.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "script.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "security.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "services.mozilla.com", true, true, false, -1, &kPinset_mozilla_services },
+ { "sites.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "spreadsheets.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "ssl.google-analytics.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "talk.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "talkgadget.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "test-mode.pinning.example.com", true, true, false, -1, &kPinset_mozilla_test },
+ { "tor2web.org", true, true, false, -1, &kPinset_tor2web },
+ { "torproject.org", false, false, false, -1, &kPinset_tor },
+ { "translate.googleapis.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "twimg.com", true, false, false, -1, &kPinset_twitterCDN },
+ { "twitter.com", true, false, false, -1, &kPinset_twitterCDN },
+ { "urchin.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "w-spotlight.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wallet.google.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "webfilings-eu-mirror.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "webfilings-eu.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "webfilings-mirror-hrd.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "webfilings.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wf-bigsky-master.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wf-demo-eu.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wf-demo-hrd.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wf-dogfood-hrd.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wf-pentest.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wf-staging-hr.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wf-training-hrd.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wf-training-master.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "wf-trial-hrd.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "www.dropbox.com", true, false, false, -1, &kPinset_dropbox },
+ { "www.gmail.com", false, false, false, -1, &kPinset_google_root_pems },
+ { "www.googlemail.com", false, false, false, -1, &kPinset_google_root_pems },
+ { "www.torproject.org", true, false, false, -1, &kPinset_tor },
+ { "www.twitter.com", true, false, false, -1, &kPinset_twitterCom },
+ { "xbrlsuccess.appspot.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "youtu.be", true, false, false, -1, &kPinset_google_root_pems },
+ { "youtube-nocookie.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "youtube.com", true, false, false, -1, &kPinset_google_root_pems },
+ { "ytimg.com", true, false, false, -1, &kPinset_google_root_pems },
+};
+
+// Pinning Preload List Length = 331;
+
+static const int32_t kUnknownId = -1;
+
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1419674828470000);
diff --git a/security/manager/boot/src/moz.build b/security/manager/boot/src/moz.build
index b3d2127..50a345b 100644
--- a/security/manager/boot/src/moz.build
+++ b/security/manager/boot/src/moz.build
@@ -10,6 +10,7 @@ UNIFIED_SOURCES += [
'nsSecurityHeaderParser.cpp',
'nsSecurityWarningDialogs.cpp',
'nsSiteSecurityService.cpp',
+ 'PublicKeyPinningService.cpp',
]
# nsSecureBrowserUIImpl.cpp cannot be built in unified mode because it forces NSPR logging.
@@ -17,6 +18,11 @@ SOURCES += [
'nsSecureBrowserUIImpl.cpp',
]
+
+LOCAL_INCLUDES += [
+ '../../../pkix/include',
+]
+
FAIL_ON_WARNINGS = True
MSVC_ENABLE_PGO = True
diff --git a/security/manager/ssl/src/SSLServerCertVerification.cpp b/security/manager/ssl/src/SSLServerCertVerification.cpp
index cf15586..18d9f55 100644
--- a/security/manager/ssl/src/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/src/SSLServerCertVerification.cpp
@@ -637,8 +637,9 @@ NSSDetermineCertOverrideErrors(CertVerifier& certVerifier,
// possible failure.
// XXX TODO: convert to VerifySSLServerCert
// XXX TODO: get rid of error log
- certVerifier.VerifyCert(cert, stapledOCSPResponse, certificateUsageSSLServer,
- now, infoObject, 0, nullptr, nullptr, verify_log);
+ certVerifier.VerifyCert(cert, certificateUsageSSLServer,
+ now, infoObject, infoObject->GetHostNameRaw(),
+ 0, stapledOCSPResponse, nullptr, nullptr, verify_log);
// Check the name field against the desired hostname.
if (CERT_VerifyCertName(cert, infoObject->GetHostNameRaw()) != SECSuccess) {
diff --git a/security/manager/ssl/src/SharedCertVerifier.h b/security/manager/ssl/src/SharedCertVerifier.h
index 32a92a3..c7c1936 100644
--- a/security/manager/ssl/src/SharedCertVerifier.h
+++ b/security/manager/ssl/src/SharedCertVerifier.h
@@ -24,12 +24,14 @@ public:
missing_cert_download_config ac, crl_download_config cdc,
#endif
ocsp_download_config odc, ocsp_strict_config osc,
- ocsp_get_config ogc)
+ ocsp_get_config ogc,
+ pinning_enforcement_config pinningEnforcementLevel)
: mozilla::psm::CertVerifier(ic,
#ifndef NSS_NO_LIBPKIX
ac, cdc,
#endif
- odc, osc, ogc)
+ odc, osc, ogc,
+ pinningEnforcementLevel)
{
}
};
diff --git a/security/manager/ssl/src/nsCMS.cpp b/security/manager/ssl/src/nsCMS.cpp
index 70a3c49..ee76c07 100644
--- a/security/manager/ssl/src/nsCMS.cpp
+++ b/security/manager/ssl/src/nsCMS.cpp
@@ -264,9 +264,10 @@ nsresult nsCMSMessage::CommonVerifySignature(unsigned char* aDigestData, uint32_
NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
{
- SECStatus srv = certVerifier->VerifyCert(si->cert, nullptr,
+ SECStatus srv = certVerifier->VerifyCert(si->cert,
certificateUsageEmailSigner,
- PR_Now(), nullptr /*XXX pinarg*/);
+ PR_Now(), nullptr /*XXX pinarg*/,
+ nullptr /*hostname*/);
if (srv != SECSuccess) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("nsCMSMessage::CommonVerifySignature - signing cert not trusted now\n"));
diff --git a/security/manager/ssl/src/nsNSSCertificate.cpp b/security/manager/ssl/src/nsNSSCertificate.cpp
index 88fb8ed..70b9c89 100644
--- a/security/manager/ssl/src/nsNSSCertificate.cpp
+++ b/security/manager/ssl/src/nsNSSCertificate.cpp
@@ -829,10 +829,12 @@ nsNSSCertificate::GetChain(nsIArray** _rvChain)
// We want to test all usages, but we start with server because most of the
// time Firefox users care about server certs.
- certVerifier->VerifyCert(mCert.get(), nullptr,
+ certVerifier->VerifyCert(mCert.get(),
certificateUsageSSLServer, PR_Now(),
nullptr, /*XXX fixme*/
+ nullptr, /* hostname */
CertVerifier::FLAG_LOCAL_ONLY,
+ nullptr, /* stapledOCSPResponse */
&nssChain);
// This is the whitelist of all non-SSLServer usages that are supported by
// verifycert.
@@ -851,10 +853,12 @@ nsNSSCertificate::GetChain(nsIArray** _rvChain)
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("pipnss: PKIX attempting chain(%d) for '%s'\n",
usage, mCert->nickname));
- certVerifier->VerifyCert(mCert.get(), nullptr,
+ certVerifier->VerifyCert(mCert.get(),
usage, PR_Now(),
nullptr, /*XXX fixme*/
+ nullptr, /*hostname*/
CertVerifier::FLAG_LOCAL_ONLY,
+ nullptr, /* stapledOCSPResponse */
&nssChain);
}
@@ -1467,10 +1471,11 @@ nsNSSCertificate::hasValidEVOidTag(SECOidTag& resultOidTag, bool& validEV)
uint32_t flags = mozilla::psm::CertVerifier::FLAG_LOCAL_ONLY |
mozilla::psm::CertVerifier::FLAG_MUST_BE_EV;
- SECStatus rv = certVerifier->VerifyCert(mCert.get(), nullptr,
+ SECStatus rv = certVerifier->VerifyCert(mCert.get(),
certificateUsageSSLServer, PR_Now(),
nullptr /* XXX pinarg */,
- flags, nullptr, &resultOidTag);
+ nullptr /* hostname */,
+ flags, nullptr /* stapledOCSPResponse */ , nullptr, &resultOidTag);
if (rv != SECSuccess) {
resultOidTag = SEC_OID_UNKNOWN;
diff --git a/security/manager/ssl/src/nsNSSCertificateDB.cpp b/security/manager/ssl/src/nsNSSCertificateDB.cpp
index 40b03c1..c9fd8ba 100644
--- a/security/manager/ssl/src/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/src/nsNSSCertificateDB.cpp
@@ -634,9 +634,10 @@ nsNSSCertificateDB::ImportEmailCertificate(uint8_t * data, uint32_t length,
mozilla::pkix::ScopedCERTCertList certChain;
- SECStatus rv = certVerifier->VerifyCert(node->cert, nullptr,
+ SECStatus rv = certVerifier->VerifyCert(node->cert,
certificateUsageEmailRecipient,
- now, ctx, 0, &certChain);
+ now, ctx, nullptr, 0,
+ nullptr, &certChain);
if (rv != SECSuccess) {
nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
@@ -801,9 +802,10 @@ nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfac
!CERT_LIST_END(node,certList);
node = CERT_LIST_NEXT(node)) {
mozilla::pkix::ScopedCERTCertList certChain;
- SECStatus rv = certVerifier->VerifyCert(node->cert, nullptr,
+ SECStatus rv = certVerifier->VerifyCert(node->cert,
certificateUsageVerifyCA,
- PR_Now(), ctx, 0, &certChain);
+ PR_Now(), ctx, nullptr, 0, nullptr,
+ &certChain);
if (rv != SECSuccess) {
nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow, proofOfLock);
@@ -1381,9 +1383,10 @@ nsNSSCertificateDB::FindCertByEmailAddress(nsISupports *aToken, const char *aEma
!CERT_LIST_END(node, certlist);
node = CERT_LIST_NEXT(node)) {
- SECStatus srv = certVerifier->VerifyCert(node->cert, nullptr,
+ SECStatus srv = certVerifier->VerifyCert(node->cert,
certificateUsageEmailRecipient,
- PR_Now(), nullptr /*XXX pinarg*/);
+ PR_Now(), nullptr /*XXX pinarg*/,
+ nullptr /*hostname*/);
if (srv == SECSuccess) {
break;
}
@@ -1772,10 +1775,12 @@ nsNSSCertificateDB::VerifyCertNow(nsIX509Cert* aCert,
SECOidTag evOidPolicy;
SECStatus srv;
- srv = certVerifier->VerifyCert(nssCert, nullptr,
+ srv = certVerifier->VerifyCert(nssCert,
aUsage, PR_Now(),
nullptr, // Assume no context
+ nullptr, // hostname
aFlags,
+ nullptr, // stapledOCSPResponse
&resultChain,
&evOidPolicy);
diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp
index 44b3808..c4bd566 100644
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -996,6 +996,13 @@ void nsNSSComponent::setValidationOptions(bool isInitialSetting,
}
}
+ // Default pinning enforcement level is disabled.
+ CertVerifier::pinning_enforcement_config
+ pinningEnforcementLevel =
+ static_cast<CertVerifier::pinning_enforcement_config>
+ (Preferences::GetInt("security.cert_pinning.enforcement_level",
+ CertVerifier::pinningDisabled));
+
CertVerifier::ocsp_download_config odc;
CertVerifier::ocsp_strict_config osc;
CertVerifier::ocsp_get_config ogc;
@@ -1009,7 +1016,7 @@ void nsNSSComponent::setValidationOptions(bool isInitialSetting,
crlDownloading ?
CertVerifier::crl_download_allowed : CertVerifier::crl_local_only,
#endif
- odc, osc, ogc);
+ odc, osc, ogc, pinningEnforcementLevel);
// mozilla::pkix has its own OCSP cache, so disable the NSS cache
// if appropriate.
@@ -1644,7 +1651,8 @@ nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
|| prefName.Equals("security.OCSP.GET.enabled")
|| prefName.Equals("security.ssl.enable_ocsp_stapling")
|| prefName.Equals("security.use_mozillapkix_verification")
- || prefName.Equals("security.use_libpkix_verification")) {
+ || prefName.Equals("security.use_libpkix_verification")
+ || prefName.Equals("security.cert_pinning.enforcement_level")) {
MutexAutoLock lock(mutex);
setValidationOptions(false, lock);
} else if (prefName.Equals("network.ntlm.send-lm-response")) {
diff --git a/security/manager/ssl/src/nsUsageArrayHelper.cpp b/security/manager/ssl/src/nsUsageArrayHelper.cpp
index 7f7249f..dd65ae5 100644
--- a/security/manager/ssl/src/nsUsageArrayHelper.cpp
+++ b/security/manager/ssl/src/nsUsageArrayHelper.cpp
@@ -105,8 +105,9 @@ nsUsageArrayHelper::check(uint32_t previousCheckResult,
MOZ_CRASH("unknown cert usage passed to check()");
}
- SECStatus rv = certVerifier->VerifyCert(mCert, nullptr, aCertUsage,
- time, nullptr /*XXX:wincx*/, flags);
+ SECStatus rv = certVerifier->VerifyCert(mCert, aCertUsage, time,
+ nullptr /*XXX:wincx*/,
+ nullptr /*hostname*/, flags);
if (rv == SECSuccess) {
typestr.Append(suffix);
diff --git a/security/manager/ssl/tests/unit/head_psm.js b/security/manager/ssl/tests/unit/head_psm.js
index 58e838b..ae25ea9e 100644
--- a/security/manager/ssl/tests/unit/head_psm.js
+++ b/security/manager/ssl/tests/unit/head_psm.js
@@ -52,6 +52,7 @@ const SEC_ERROR_OCSP_INVALID_SIGNING_CERT = SEC_ERROR_BASE + 144;
const SEC_ERROR_POLICY_VALIDATION_FAILED = SEC_ERROR_BASE + 160; // -8032
const SEC_ERROR_OCSP_BAD_SIGNATURE = SEC_ERROR_BASE + 157;
const SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = SEC_ERROR_BASE + 176;
+const SEC_ERROR_APPLICATION_CALLBACK_ERROR = SEC_ERROR_BASE + 178;
const SSL_ERROR_BAD_CERT_DOMAIN = SSL_ERROR_BASE + 12;
diff --git a/security/manager/ssl/tests/unit/test_cert_overrides.js b/security/manager/ssl/tests/unit/test_cert_overrides.js
index 11e14f3b..91fc77eb 100644
--- a/security/manager/ssl/tests/unit/test_cert_overrides.js
+++ b/security/manager/ssl/tests/unit/test_cert_overrides.js
@@ -232,7 +232,7 @@ function add_distrust_override_test(certFileName, hostName,
let certToDistrust = constructCertFromFile(certFileName);
add_test(function () {
- // "pu" means the cert is actively distrusted.
+ // Add an entry to the NSS certDB that says to distrust the cert
setCertTrust(certToDistrust, "pu,,");
clearSessionCache();
run_next_test();
diff --git a/security/manager/ssl/tests/unit/test_pinning.js b/security/manager/ssl/tests/unit/test_pinning.js
new file mode 100644
index 0000000..dc779dd
--- /dev/null
+++ b/security/manager/ssl/tests/unit/test_pinning.js
@@ -0,0 +1,182 @@
+// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+// For all cases, the acceptable pinset includes only certificates pinned to
+// Test End Entity Cert (signed by issuer testCA). Other certificates
+// are issued by otherCA, which is never in the pinset but is a user-specified
+// trust anchor. This test covers multiple cases:
+//
+// Pinned domain include-subdomains.pinning.example.com includes subdomains
+// - PASS: include-subdomains.pinning.example.com serves a correct cert
+// - PASS: good.include-subdomains.pinning.example.com serves a correct cert
+// - FAIL (strict): bad.include-subdomains.pinning.example.com serves a cert
+// not in the pinset
+// - PASS (mitm): bad.include-subdomains.pinning.example.com serves a cert not
+// in the pinset, but issued by a user-specified trust domain
+//
+// Pinned domain exclude-subdomains.pinning.example.com excludes subdomains
+// - PASS: exclude-subdomains.pinning.example.com serves a correct cert
+// - FAIL: exclude-subdomains.pinning.example.com services an incorrect cert
+// (TODO: test using verifyCertnow)
+// - PASS: sub.exclude-subdomains.pinning.example.com serves an incorrect cert
+
+"use strict";
+
+do_get_profile(); // must be called before getting nsIX509CertDB
+const certdb = Cc["@mozilla.org/security/x509certdb;1"]
+ .getService(Ci.nsIX509CertDB);
+
+function test_strict() {
+ // In strict mode, we always evaluate pinning data, regardless of whether the
+ // issuer is a built-in trust anchor. We only enforce pins that are not in
+ // test mode.
+ add_test(function() {
+ Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2);
+ run_next_test();
+ });
+
+ // If a host should be pinned but other errors (particularly overridable
+ // errors) like 'unknown issuer' are encountered, the pinning error takes
+ // precedence. This prevents overrides for such hosts.
+ add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
+ getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
+
+ // Issued by otherCA, which is not in the pinset for pinning.example.com.
+ add_connection_test("bad.include-subdomains.pinning.example.com",
+ getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
+
+ // These domains serve certs that match the pinset.
+ add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
+
+ // This domain serves a cert that doesn't match the pinset, but subdomains
+ // are excluded.
+ add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
+
+ // This domain's pinset is exactly the same as
+ // include-subdomains.pinning.example.com, serves the same cert as
+ // bad.include-subdomains.pinning.example.com, but it should pass because
+ // it's in test_mode.
+ add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
+}
+
+function test_mitm() {
+ // In MITM mode, we allow pinning to pass if the chain resolves to any
+ // user-specified trust anchor, even if it is not in the pinset.
+ add_test(function() {
+ Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 1);
+ run_next_test();
+ });
+
+ add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
+
+ add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
+ getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
+
+ // In this case, even though otherCA is not in the pinset, it is a
+ // user-specified trust anchor and the pinning check succeeds.
+ add_connection_test("bad.include-subdomains.pinning.example.com", Cr.NS_OK);
+
+ add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
+};
+
+function test_disabled() {
+ // Disable pinning.
+ add_test(function() {
+ Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 0);
+ run_next_test();
+ });
+
+ add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("bad.include-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
+
+ add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
+ getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
+}
+
+function test_enforce_test_mode() {
+ // In enforce test mode, we always enforce all pins, even test pins.
+ add_test(function() {
+ Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 3);
+ run_next_test();
+ });
+
+ add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
+ getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
+
+ // Issued by otherCA, which is not in the pinset for pinning.example.com.
+ add_connection_test("bad.include-subdomains.pinning.example.com",
+ getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
+
+ // These domains serve certs that match the pinset.
+ add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
+ add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
+
+ // This domain serves a cert that doesn't match the pinset, but subdomains
+ // are excluded.
+ add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
+
+ // This domain's pinset is exactly the same as
+ // include-subdomains.pinning.example.com, serves the same cert as
+ // bad.include-subdomains.pinning.example.com, is in test-mode, but we are
+ // enforcing test mode pins.
+ add_connection_test("test-mode.pinning.example.com",
+ getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
+}
+
+function check_pinning_telemetry() {
+ let service = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
+ let prod_histogram = service.getHistogramById("CERT_PINNING_RESULTS")
+ .snapshot();
+ let test_histogram = service.getHistogramById("CERT_PINNING_TEST_RESULTS")
+ .snapshot();
+ // Because all of our test domains are pinned to user-specified trust
+ // anchors, effectively only strict mode and enforce test-mode get evaluated
+ do_check_eq(prod_histogram.counts[0], 4); // Failure count
+ do_check_eq(prod_histogram.counts[1], 4); // Success count
+ do_check_eq(test_histogram.counts[0], 2); // Failure count
+ do_check_eq(test_histogram.counts[1], 0); // Success count
+
+ let moz_prod_histogram = service.getHistogramById("CERT_PINNING_MOZ_RESULTS")
+ .snapshot();
+ let moz_test_histogram =
+ service.getHistogramById("CERT_PINNING_MOZ_TEST_RESULTS").snapshot();
+ do_check_eq(moz_prod_histogram.counts[0], 0); // Failure count
+ do_check_eq(moz_prod_histogram.counts[1], 0); // Success count
+ do_check_eq(moz_test_histogram.counts[0], 0); // Failure count
+ do_check_eq(moz_test_histogram.counts[1], 0); // Success count
+
+ let per_host_histogram =
+ service.getHistogramById("CERT_PINNING_MOZ_RESULTS_BY_HOST").snapshot();
+ do_check_eq(per_host_histogram.counts[0], 0); // Failure count
+ do_check_eq(per_host_histogram.counts[1], 2); // Success count
+ run_next_test();
+}
+
+function run_test() {
+ add_tls_server_setup("BadCertServer");
+
+ // Add a user-specified trust anchor.
+ addCertFromFile(certdb, "tlsserver/other-test-ca.der", "CTu,u,u");
+
+ test_strict();
+ test_mitm();
+ test_disabled();
+ test_enforce_test_mode();
+
+ add_test(function () {
+ check_pinning_telemetry();
+ });
+ run_next_test();
+}
diff --git a/security/manager/ssl/tests/unit/tlsserver/cert8.db b/security/manager/ssl/tests/unit/tlsserver/cert8.db
index 13c101f..7da5d7f 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/cert8.db and b/security/manager/ssl/tests/unit/tlsserver/cert8.db differ
diff --git a/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp b/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp
index a4c59a4..5df134a 100644
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp
@@ -24,6 +24,7 @@ struct BadCertHost
const char *mCertName;
};
+// Hostname, cert nickname pairs.
const BadCertHost sBadCertHosts[] =
{
{ "expired.example.com", "expired" },
@@ -42,6 +43,16 @@ const BadCertHost sBadCertHosts[] =
{ "inadequatekeyusage.example.com", "inadequatekeyusage" },
{ "selfsigned-inadequateEKU.example.com", "selfsigned-inadequateEKU" },
{ "self-signed-end-entity-with-cA-true.example.com", "self-signed-EE-with-cA-true" },
+ // All of include-subdomains.pinning.example.com is pinned to End Entity
+ // Test Cert with nick localhostAndExampleCom. Any other nick will only
+ // pass pinning when security.cert_pinning.enforcement.level != strict and
+ // otherCA is added as a user-specified trust anchor. See StaticHPKPins.h.
+ { "include-subdomains.pinning.example.com", "localhostAndExampleCom" },
+ { "good.include-subdomains.pinning.example.com", "localhostAndExampleCom" },
+ { "bad.include-subdomains.pinning.example.com", "otherIssuerEE" },
+ { "exclude-subdomains.pinning.example.com", "localhostAndExampleCom" },
+ { "sub.exclude-subdomains.pinning.example.com", "otherIssuerEE" },
+ { "test-mode.pinning.example.com", "otherIssuerEE" },
{ nullptr, nullptr }
};
diff --git a/security/manager/ssl/tests/unit/tlsserver/default-ee.der b/security/manager/ssl/tests/unit/tlsserver/default-ee.der
index ac98037..9b2359d 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/default-ee.der and b/security/manager/ssl/tests/unit/tlsserver/default-ee.der differ
diff --git a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh b/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
index ef388bb..6075a5c 100755
--- a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
+++ b/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
@@ -12,7 +12,10 @@
#
# NB: This will cause the following files to be overwritten if they are in
# the output directory:
-# cert8.db, key3.db, secmod.db, ocsp-ca.der, ocsp-other-ca.der
+# cert8.db, key3.db, secmod.db, ocsp-ca.der, ocsp-other-ca.der, default-ee.der
+# NB: You must run genHPKPStaticPins.js after running this file, since its
+# output (StaticHPKPins.h) depends on default-ee.der
+
set -x
set -e
@@ -25,11 +28,13 @@ OBJDIR=${1}
OUTPUT_DIR=${2}
RUN_MOZILLA="$OBJDIR/dist/bin/run-mozilla.sh"
CERTUTIL="$OBJDIR/dist/bin/certutil"
+# On BSD, mktemp requires either a template or a prefix.
+MKTEMP="mktemp temp.XXXX"
-NOISE_FILE=`mktemp`
+NOISE_FILE=`$MKTEMP`
# Make a good effort at putting something unique in the noise file.
date +%s%N > "$NOISE_FILE"
-PASSWORD_FILE=`mktemp`
+PASSWORD_FILE=`$MKTEMP`
function cleanup {
rm -f "$NOISE_FILE" "$PASSWORD_FILE"
@@ -134,7 +139,11 @@ function make_delegated {
make_CA testCA 'CN=Test CA' test-ca.der
make_CA otherCA 'CN=Other test CA' other-test-ca.der
-make_EE localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com"
+
+make_EE localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com,*.pinning.example.com,*.include-subdomains.pinning.…"
+# Make an EE cert issued by otherCA
+make_EE otherIssuerEE 'CN=Wrong CA Pin Test End-Entity' otherCA "*.include-subdomains.pinning.example.com,*.exclude-subdomains.pinning.example.com,*.pinning.example.com"
+
$RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -L -n localhostAndExampleCom -r > $OUTPUT_DIR/default-ee.der
# A cert that is like localhostAndExampleCom, but with a different serial number for
# testing the "OCSP response is from the right issuer, but it is for the wrong cert"
diff --git a/security/manager/ssl/tests/unit/tlsserver/key3.db b/security/manager/ssl/tests/unit/tlsserver/key3.db
index 283e8fb..2d4dd29 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/key3.db and b/security/manager/ssl/tests/unit/tlsserver/key3.db differ
diff --git a/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der b/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der
index 794fb9c..742bb86 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der and b/security/manager/ssl/tests/unit/tlsserver/other-test-ca.der differ
diff --git a/security/manager/ssl/tests/unit/tlsserver/secmod.db b/security/manager/ssl/tests/unit/tlsserver/secmod.db
index a5f2f60..7a0e2b5 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/secmod.db and b/security/manager/ssl/tests/unit/tlsserver/secmod.db differ
diff --git a/security/manager/ssl/tests/unit/tlsserver/test-ca.der b/security/manager/ssl/tests/unit/tlsserver/test-ca.der
index f4c4863..356de5b 100644
Binary files a/security/manager/ssl/tests/unit/tlsserver/test-ca.der and b/security/manager/ssl/tests/unit/tlsserver/test-ca.der differ
diff --git a/security/manager/ssl/tests/unit/xpcshell.ini b/security/manager/ssl/tests/unit/xpcshell.ini
index 7935c2d..24b0ffc 100644
--- a/security/manager/ssl/tests/unit/xpcshell.ini
+++ b/security/manager/ssl/tests/unit/xpcshell.ini
@@ -78,3 +78,7 @@ requesttimeoutfactor = 4
run-sequentially = hardcoded ports
# Bug 676972: this test times out on Android and B2G
skip-if = os == "android" || buildapp == "b2g"
+[test_pinning.js]
+run-sequentially = hardcoded ports
+# Bug 676972: test fails consistently on Android and B2G
+fail-if = os == "android" || buildapp == "b2g"
\ No newline at end of file
diff --git a/security/manager/tools/PreloadedHPKPins.json b/security/manager/tools/PreloadedHPKPins.json
new file mode 100644
index 0000000..ed3b9b7
--- /dev/null
+++ b/security/manager/tools/PreloadedHPKPins.json
@@ -0,0 +1,247 @@
+// -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// The top-level element is a dictionary with two keys: "pinsets" maps details
+// of certificate pinning to a name and "entries" contains the HPKP details for
+// each host.
+//
+// "pinsets" is a list of objects. Each object has the following members:
+// name: (string) the name of the pinset
+// sha256_hashes: (list of strings) the set of allowed SPKIs hashes
+//
+// For a given pinset, a certificate is accepted if at least one of the
+// Subject Public Key Infos (SPKIs) is found in the chain. SPKIs are specified
+// as names, which must match up with the name given in the Mozilla root store.
+//
+// "entries" is a list of objects. Each object has the following members:
+// name: (string) the DNS name of the host in question
+// include_subdomains: (optional bool) whether subdomains of |name| are also covered
+// pins: (string) the |name| member of an object in |pinsets|
+//
+// "extra_certs" is a list of base64-encoded certificates. These are used in
+// pinsets that reference certificates not in our root program (for example,
+// Facebook).
+
+// equifax -> aus3
+// Geotrust Primary -> www.mozilla.org
+// Geotrust Global -> *. addons.mozilla.org
+{
+ "chromium_data" : {
+ "cert_file_url": "https://src.chromium.org/chrome/trunk/src/net/http/transport_security_state…",
+ "json_file_url": "https://src.chromium.org/chrome/trunk/src/net/http/transport_security_state…",
+ "substitute_pinsets": {
+ // Use the larger google_root_pems pinset instead of google
+ "google": "google_root_pems"
+ },
+ "production_pinsets": [
+ "google_root_pems"
+ ],
+ "production_domains": [
+ // Chrome's test domain.
+ "pinningtest.appspot.com",
+ // Dropbox
+ "dropbox.com",
+ "www.dropbox.com",
+ // Twitter
+ "api.twitter.com",
+ "business.twitter.com",
+ "dev.twitter.com",
+ "mobile.twitter.com",
+ "oauth.twitter.com",
+ "platform.twitter.com",
+ "twimg.com",
+ "www.twitter.com",
+ // Tor
+ "torproject.org",
+ "blog.torproject.org",
+ "check.torproject.org",
+ "dist.torproject.org",
+ "www.torproject.org"
+ ],
+ "exclude_domains" : [
+ // Chrome's entry for twitter.com doesn't include subdomains, so replace
+ // it with our own entry below which also uses an expanded pinset.
+ "twitter.com"
+ ]
+ },
+ "pinsets": [
+ {
+ // From bug 772756, mozilla uses GeoTrust, Digicert and Thawte. Our
+ // cdn sites use Verisign and Baltimore. We exclude 1024-bit root certs
+ // from all providers. geotrust ca info:
+ // http://www.geotrust.com/resources/root-certificates/index.html
+ "name": "mozilla",
+ "sha256_hashes": [
+ "Baltimore CyberTrust Root",
+ "DigiCert Assured ID Root CA",
+ "DigiCert Global Root CA",
+ "DigiCert High Assurance EV Root CA",
+ "GeoTrust Global CA",
+ "GeoTrust Global CA 2",
+ "GeoTrust Primary Certification Authority",
+ "GeoTrust Primary Certification Authority - G2",
+ "GeoTrust Primary Certification Authority - G3",
+ "GeoTrust Universal CA",
+ "GeoTrust Universal CA 2",
+ "thawte Primary Root CA",
+ "thawte Primary Root CA - G2",
+ "thawte Primary Root CA - G3",
+ "Verisign Class 1 Public Primary Certification Authority - G3",
+ "Verisign Class 2 Public Primary Certification Authority - G3",
+ "Verisign Class 3 Public Primary Certification Authority - G3",
+ "VeriSign Class 3 Public Primary Certification Authority - G4",
+ "VeriSign Class 3 Public Primary Certification Authority - G5",
+ "Verisign Class 4 Public Primary Certification Authority - G3",
+ "VeriSign Universal Root Certification Authority"
+ ]
+ },
+ {
+ "name": "mozilla_services",
+ "sha256_hashes": [
+ "DigiCert Global Root CA"
+ ]
+ },
+ // For pinning tests on pinning.example.com, the certificate must be 'End
+ // Entity Test Cert'
+ {
+ "name": "mozilla_test",
+ "sha256_hashes": [
+ "End Entity Test Cert"
+ ]
+ },
+ // Google's root PEMs. Chrome pins only to their intermediate certs, but
+ // they'd like us to be more liberal. For the initial list, we are using
+ // the certs from http://pki.google.com/roots.pem.
+ // We have no built-in for commented out CAs.
+ {
+ "name": "google_root_pems",
+ "sha256_hashes": [
+ "AddTrust External Root",
+ "AddTrust Low-Value Services Root",
+ "AddTrust Public Services Root",
+ "AddTrust Qualified Certificates Root",
+ "AffirmTrust Commercial",
+ "AffirmTrust Networking",
+ "AffirmTrust Premium",
+ "AffirmTrust Premium ECC",
+ "America Online Root Certification Authority 1",
+ "America Online Root Certification Authority 2",
+ "Baltimore CyberTrust Root",
+ "Comodo AAA Services root",
+ "COMODO Certification Authority",
+ "COMODO ECC Certification Authority",
+ "Comodo Secure Services root",
+ "Comodo Trusted Services root",
+ "Cybertrust Global Root",
+ "DigiCert Assured ID Root CA",
+ "DigiCert Global Root CA",
+ "DigiCert High Assurance EV Root CA",
+ "Entrust.net Premium 2048 Secure Server CA",
+ // "Entrust.net Secure Server CA",
+ "Entrust Root Certification Authority",
+ "Equifax Secure CA",
+ "Equifax Secure eBusiness CA 1",
+ // "Equifax Secure eBusiness CA 2",
+ "Equifax Secure Global eBusiness CA",
+ "GeoTrust Global CA",
+ "GeoTrust Global CA 2",
+ "GeoTrust Primary Certification Authority",
+ "GeoTrust Primary Certification Authority - G2",
+ "GeoTrust Primary Certification Authority - G3",
+ "GeoTrust Universal CA",
+ "GeoTrust Universal CA 2",
+ "GlobalSign Root CA",
+ "GlobalSign Root CA - R2",
+ "GlobalSign Root CA - R3",
+ "Go Daddy Class 2 CA",
+ "Go Daddy Root Certificate Authority - G2",
+ // "GTE CyberTrust Global Root",
+ "Network Solutions Certificate Authority",
+ // "RSA Root Certificate 1",
+ "Starfield Class 2 CA",
+ "Starfield Root Certificate Authority - G2",
+ "Starfield Services Root Certificate Authority - G2",
+ "StartCom Certification Authority",
+ "StartCom Certification Authority",
+ "StartCom Certification Authority G2",
+ "TC TrustCenter Class 2 CA II",
+ "TC TrustCenter Class 3 CA II",
+ "TC TrustCenter Universal CA I",
+ "TC TrustCenter Universal CA III",
+ "Thawte Premium Server CA",
+ "thawte Primary Root CA",
+ "thawte Primary Root CA - G2",
+ "thawte Primary Root CA - G3",
+ "Thawte Server CA",
+ "UTN DATACorp SGC Root CA",
+ "UTN USERFirst Hardware Root CA",
+ // "ValiCert Class 1 VA",
+ // "ValiCert Class 2 VA",
+ "Verisign Class 3 Public Primary Certification Authority",
+ "Verisign Class 3 Public Primary Certification Authority",
+ "Verisign Class 3 Public Primary Certification Authority - G2",
+ "Verisign Class 3 Public Primary Certification Authority - G3",
+ "VeriSign Class 3 Public Primary Certification Authority - G4",
+ "VeriSign Class 3 Public Primary Certification Authority - G5",
+ "Verisign Class 4 Public Primary Certification Authority - G3",
+ "VeriSign Universal Root Certification Authority",
+ "XRamp Global CA Root"
+ ]
+ },
+ {
+ "name": "facebook",
+ "sha256_hashes": [
+ "Verisign Class 3 Public Primary Certification Authority - G3",
+ "DigiCert High Assurance EV Root CA",
+ "DigiCert ECC Secure Server CA"
+ ]
+ }
+ ],
+
+ "entries": [
+ // Only domains that are operationally crucial to Firefox can have per-host
+ // telemetry reporting (the "id") field
+ { "name": "addons.mozilla.org", "include_subdomains": true,
+ "pins": "mozilla", "test_mode": false, "id": 1 },
+ { "name": "addons.mozilla.net", "include_subdomains": true,
+ "pins": "mozilla", "test_mode": false, "id": 2 },
+ { "name": "aus4.mozilla.org", "include_subdomains": true,
+ "pins": "mozilla", "test_mode": true, "id": 3 },
+ { "name": "accounts.firefox.com", "include_subdomains": true,
+ "pins": "mozilla_services", "test_mode": false, "id": 4 },
+ { "name": "api.accounts.firefox.com", "include_subdomains": true,
+ "pins": "mozilla_services", "test_mode": false, "id": 5 },
+ { "name": "cdn.mozilla.net", "include_subdomains": true,
+ "pins": "mozilla", "test_mode": false },
+ { "name": "cdn.mozilla.org", "include_subdomains": true,
+ "pins": "mozilla", "test_mode": false },
+ { "name": "media.mozilla.com", "include_subdomains": true,
+ "pins": "mozilla", "test_mode": false },
+ { "name": "services.mozilla.com", "include_subdomains": true,
+ "pins": "mozilla_services", "test_mode": true },
+ { "name": "include-subdomains.pinning.example.com",
+ "include_subdomains": true, "pins": "mozilla_test",
+ "test_mode": false },
+ // Example domain to collect per-host stats for telemetry tests.
+ { "name": "exclude-subdomains.pinning.example.com",
+ "include_subdomains": false, "pins": "mozilla_test",
+ "test_mode": false, "id": 0 },
+ { "name": "test-mode.pinning.example.com", "include_subdomains": true,
+ "pins": "mozilla_test", "test_mode": true },
+ // Expand twitter's pinset to include all of *.twitter.com and use
+ // twitterCDN. More specific rules take precedence because we search for
+ // exact domain name first.
+ { "name": "twitter.com", "include_subdomains": true,
+ "pins": "twitterCDN", "test_mode": false },
+ // Facebook (not pinned by Chrome)
+ { "name": "facebook.com", "include_subdomains": true,
+ "pins": "facebook", "test_mode": true }
+ ],
+
+ "extra_certificates": [
+ // DigiCert ECC Secure Server CA (for Facebook)
+ "MIIDrDCCApSgAwIBAgIQCssoukZe5TkIdnRw883GEjANBgkqhkiG9w0BAQwFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0xMzAzMDgxMjAwMDBaFw0yMzAzMDgxMjAwMDBaMEwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxJjAkBgNVBAMTHURpZ2lDZXJ0IEVDQyBTZWN1cmUgU2VydmVyIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE4ghC6nfYJN6gLGSkE85AnCNyqQIKDjc/ITa4jVMU9tWRlUvzlgKNcR7E2Munn17voOZ/WpIRllNv68DLP679Wz9HJOeaBy6Wvqgvu1cYr3GkvXg6HuhbPGtkESvMNCuMo4IBITCCAR0wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUo53mH/naOU/AbuiRy5Wl2jHiCp8wHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEMBQADggEBAMeKoENL7HTJxavVHzA1Nm6YVntIrAVjrnuaVyRXzG/63qttnMe2uuzO58pzZNvfBDcKAEmzP58
mrZGMIOgfiA4q+2Y3yDDo0sIkp0VILeoBUEoxlBPfjV/aKrtJPGHzecicZpIalir0ezZYoyxBEHQa0+1IttK7igZFcTMQMHp6mCHdJLnsnLWSB62DxsRq+HfmNb4TDydkskO/g+l3VtsIh5RHFPVfKK+jaEyDj2D3loB5hWp2Jp2VDCADjT7ueihlZGak2YPqmXTNbk19HOuNssWvFhtOyPNV6og4ETQdEa8/B6hPatJ0ES8q/HO3X8IVQwVs1n3aAr0im0/T+Xc="
+ ]
+}
diff --git a/security/manager/tools/genHPKPStaticPins.js b/security/manager/tools/genHPKPStaticPins.js
new file mode 100644
index 0000000..d16d017
--- /dev/null
+++ b/security/manager/tools/genHPKPStaticPins.js
@@ -0,0 +1,576 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// How to run this file:
+// 1. [obtain firefox source code]
+// 2. [build/obtain firefox binaries]
+// 3. run `[path to]/run-mozilla.sh [path to]/xpcshell \
+// [path to]/genHPKPStaticpins.js \
+// [absolute path to]/PreloadedHPKPins.json \
+// [absolute path to]/default-ee.der \
+// [absolute path to]/StaticHPKPins.h
+
+if (arguments.length != 3) {
+ throw "Usage: genHPKPStaticPins.js " +
+ "<absolute path to PreloadedHPKPins.json> " +
+ "<absolute path to default-ee.der> " +
+ "<absolute path to StaticHPKPins.h>";
+}
+
+const { 'classes': Cc, 'interfaces': Ci, 'utils': Cu, 'results': Cr } = Components;
+
+let { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
+let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
+let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
+
+let gCertDB = Cc["@mozilla.org/security/x509certdb;1"]
+ .getService(Ci.nsIX509CertDB);
+
+const BUILT_IN_NICK_PREFIX = "Builtin Object Token:";
+const SHA1_PREFIX = "sha1/";
+const SHA256_PREFIX = "sha256/";
+const GOOGLE_PIN_PREFIX = "GOOGLE_PIN_";
+
+// Pins expire in 14 weeks (6 weeks on Beta + 8 weeks on stable)
+const PINNING_MINIMUM_REQUIRED_MAX_AGE = 60 * 60 * 24 * 7 * 14;
+
+const FILE_HEADER = "/* This Source Code Form is subject to the terms of the Mozilla Public\n" +
+" * License, v. 2.0. If a copy of the MPL was not distributed with this\n" +
+" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n" +
+"\n" +
+"/*****************************************************************************/\n" +
+"/* This is an automatically generated file. If you're not */\n" +
+"/* PublicKeyPinningService.cpp, you shouldn't be #including it. */\n" +
+"/*****************************************************************************/\n" +
+"#include <stdint.h>" +
+"\n";
+
+const DOMAINHEADER = "/* Domainlist */\n" +
+ "struct TransportSecurityPreload {\n" +
+ " const char* mHost;\n" +
+ " const bool mIncludeSubdomains;\n" +
+ " const bool mTestMode;\n" +
+ " const bool mIsMoz;\n" +
+ " const int32_t mId;\n" +
+ " const StaticPinset *pinset;\n" +
+ "};\n\n";
+
+const PINSETDEF = "/* Pinsets are each an ordered list by the actual value of the fingerprint */\n" +
+ "struct StaticFingerprints {\n" +
+ " const size_t size;\n" +
+ " const char* const* data;\n" +
+ "};\n\n" +
+ "struct StaticPinset {\n" +
+ " const StaticFingerprints* sha1;\n" +
+ " const StaticFingerprints* sha256;\n" +
+ "};\n\n";
+
+// Command-line arguments
+var gStaticPins = parseJson(arguments[0]);
+var gTestCertFile = arguments[1];
+
+// Open the output file.
+let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+file.initWithPath(arguments[2]);
+let gFileOutputStream = FileUtils.openSafeFileOutputStream(file);
+
+function writeString(string) {
+ gFileOutputStream.write(string, string.length);
+}
+
+function readFileToString(filename) {
+ let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+ file.initWithPath(filename);
+ let stream = Cc["@mozilla.org/network/file-input-stream;1"]
+ .createInstance(Ci.nsIFileInputStream);
+ stream.init(file, -1, 0, 0);
+ let buf = NetUtil.readInputStreamToString(stream, stream.available());
+ return buf;
+}
+
+function stripComments(buf) {
+ var lines = buf.split("\n");
+ let entryRegex = /^\s*\/\//;
+ let data = "";
+ for (let i = 0; i < lines.length; ++i) {
+ let match = entryRegex.exec(lines[i]);
+ if (!match) {
+ data = data + lines[i];
+ }
+ }
+ return data;
+}
+
+function isBuiltinToken(tokenName) {
+ return tokenName == "Builtin Object Token";
+}
+
+function isCertBuiltIn(cert) {
+ let tokenNames = cert.getAllTokenNames({});
+ if (!tokenNames) {
+ return false;
+ }
+ if (tokenNames.some(isBuiltinToken)) {
+ return true;
+ }
+ return false;
+}
+
+function download(filename) {
+ var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
+ .createInstance(Ci.nsIXMLHttpRequest);
+ req.open("GET", filename, false); // doing the request synchronously
+ try {
+ req.send();
+ }
+ catch (e) {
+ throw "ERROR: problem downloading '" + filename + "': " + e;
+ }
+
+ if (req.status != 200) {
+ throw("ERROR: problem downloading '" + filename + "': status " +
+ req.status);
+ }
+ return req.responseText;
+}
+
+function downloadAsJson(filename) {
+ // we have to filter out '//' comments
+ var result = download(filename).replace(/\/\/[^\n]*\n/g, "");
+ var data = null;
+ try {
+ data = JSON.parse(result);
+ }
+ catch (e) {
+ throw "ERROR: could not parse data from '" + filename + "': " + e;
+ }
+ return data;
+}
+
+// Returns a Subject Public Key Digest from the given pem, if it exists.
+function getSKDFromPem(pem) {
+ let cert = gCertDB.constructX509FromBase64(pem, pem.length);
+ return cert.sha256SubjectPublicKeyInfoDigest;
+}
+
+// Downloads the static certs file and tries to map Google Chrome nicknames
+// to Mozilla nicknames, as well as storing any hashes for pins for which we
+// don't have root PEMs. Each entry consists of a line containing the name of
+// the pin followed either by a hash in the format "sha1/" + base64(hash), or
+// a PEM encoded certificate. For certificates that we have in our database,
+// return a map of Google's nickname to ours. For ones that aren't return a
+// map of Google's nickname to sha1 values. This code is modeled after agl's
+// https://github.com/agl/transport-security-state-generate, which doesn't
+// live in the Chromium repo because go is not an official language in
+// Chromium.
+// For all of the entries in this file:
+// - If the entry has a hash format, find the Mozilla pin name (cert nickname)
+// and stick the hash into certSKDToName
+// - If the entry has a PEM format, parse the PEM, find the Mozilla pin name
+// and stick the hash in certSKDToName
+// We MUST be able to find a corresponding cert nickname for the Chrome names,
+// otherwise we skip all pinsets referring to that Chrome name.
+function downloadAndParseChromeCerts(filename, certSKDToName) {
+ // Prefixes that we care about.
+ const BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
+ const END_CERT = "-----END CERTIFICATE-----";
+
+ // Parsing states.
+ const PRE_NAME = 0;
+ const POST_NAME = 1;
+ const IN_CERT = 2;
+ let state = PRE_NAME;
+
+ let lines = download(filename).split("\n");
+ let name = "";
+ let pemCert = "";
+ let hash = "";
+ let chromeNameToHash = {};
+ let chromeNameToMozName = {}
+ for (let i = 0; i < lines.length; ++i) {
+ let line = lines[i];
+ // Skip comments and newlines.
+ if (line.length == 0 || line[0] == '#') {
+ continue;
+ }
+ switch(state) {
+ case PRE_NAME:
+ chromeName = line;
+ state = POST_NAME;
+ break;
+ case POST_NAME:
+ if (line.startsWith(SHA1_PREFIX) ||
+ line.startsWith(SHA256_PREFIX)) {
+ if (line.startsWith(SHA1_PREFIX)) {
+ hash = line.substring(SHA1_PREFIX.length);
+ } else if (line.startsWith(SHA256_PREFIX)) {
+ hash = line.substring(SHA256_PREFIX);
+ }
+ // Store the entire prefixed hash, so we can disambiguate sha1 from
+ // sha256 later.
+ chromeNameToHash[chromeName] = line;
+ certNameToSKD[chromeName] = hash;
+ certSKDToName[hash] = chromeName;
+ state = PRE_NAME;
+ } else if (line.startsWith(BEGIN_CERT)) {
+ state = IN_CERT;
+ } else {
+ throw "ERROR: couldn't parse Chrome certificate file " + line;
+ }
+ break;
+ case IN_CERT:
+ if (line.startsWith(END_CERT)) {
+ state = PRE_NAME;
+ hash = getSKDFromPem(pemCert);
+ pemCert = "";
+ if (hash in certSKDToName) {
+ mozName = certSKDToName[hash];
+ } else {
+ // Not one of our built-in certs. Prefix the name with
+ // GOOGLE_PIN_.
+ mozName = GOOGLE_PIN_PREFIX + chromeName;
+ dump("Can't find hash in builtin certs for Chrome nickname " +
+ chromeName + ", inserting " + mozName + "\n");
+ certSKDToName[hash] = mozName;
+ certNameToSKD[mozName] = hash;
+ }
+ chromeNameToMozName[chromeName] = mozName;
+ } else {
+ pemCert += line;
+ }
+ break;
+ default:
+ throw "ERROR: couldn't parse Chrome certificate file " + line;
+ }
+ }
+ return [ chromeNameToHash, chromeNameToMozName ];
+}
+
+// We can only import pinsets from chrome if for every name in the pinset:
+// - We have a hash from Chrome's static certificate file
+// - We have a builtin cert
+// If the pinset meets these requirements, we store a map array of pinset
+// objects:
+// {
+// pinset_name : {
+// // Array of names with entries in certNameToSKD
+// sha1_hashes: [],
+// sha256_hashes: []
+// }
+// }
+// and an array of imported pinset entries:
+// { name: string, include_subdomains: boolean, test_mode: boolean,
+// pins: pinset_name }
+function downloadAndParseChromePins(filename,
+ chromeNameToHash,
+ chromeNameToMozName,
+ certNameToSKD,
+ certSKDToName) {
+ let chromePreloads = downloadAsJson(filename);
+ let chromePins = chromePreloads.pinsets;
+ let chromeImportedPinsets = {};
+ let chromeImportedEntries = [];
+
+ chromePins.forEach(function(pin) {
+ let valid = true;
+ let pinset = { name: pin.name, sha1_hashes: [], sha256_hashes: [] };
+ // Translate the Chrome pinset format to ours
+ pin.static_spki_hashes.forEach(function(name) {
+ if (name in chromeNameToHash) {
+ let hash = chromeNameToHash[name];
+ if (hash.startsWith(SHA1_PREFIX)) {
+ hash = hash.substring(SHA1_PREFIX.length);
+ pinset.sha1_hashes.push(certSKDToName[hash]);
+ } else if (hash.startsWith(SHA256_PREFIX)) {
+ hash = hash.substring(SHA256_PREFIX.length);
+ pinset.sha256_hashes.push(certSKDToName[hash]);
+ } else {
+ throw("Unsupported hash type: " + chromeNameToHash[name]);
+ }
+ // We should have already added hashes for all of these when we
+ // imported the certificate file.
+ if (!certNameToSKD[name]) {
+ throw("No hash for name: " + name);
+ }
+ } else if (name in chromeNameToMozName) {
+ pinset.sha256_hashes.push(chromeNameToMozName[name]);
+ } else {
+ dump("Skipping Chrome pinset " + pinset.name + ", couldn't find " +
+ "builtin " + name + " from cert file\n");
+ valid = false;
+ }
+ });
+ if (valid) {
+ chromeImportedPinsets[pinset.name] = pinset;
+ }
+ });
+
+ // Grab the domain entry lists. Chrome's entry format is similar to
+ // ours, except theirs includes a HSTS mode.
+ const cData = gStaticPins.chromium_data;
+ let entries = chromePreloads.entries;
+ entries.forEach(function(entry) {
+ let pinsetName = cData.substitute_pinsets[entry.pins];
+ if (!pinsetName) {
+ pinsetName = entry.pins;
+ }
+ let isProductionDomain =
+ (cData.production_domains.indexOf(entry.name) != -1);
+ let isProductionPinset =
+ (cData.production_pinsets.indexOf(pinsetName) != -1);
+ let excludeDomain =
+ (cData.exclude_domains.indexOf(entry.name) != -1);
+ let isTestMode = !isProductionPinset && !isProductionDomain;
+ if (entry.pins && !excludeDomain && chromeImportedPinsets[entry.pins]) {
+ chromeImportedEntries.push({
+ name: entry.name,
+ include_subdomains: entry.include_subdomains,
+ test_mode: isTestMode,
+ is_moz: false,
+ pins: pinsetName });
+ }
+ });
+ return [ chromeImportedPinsets, chromeImportedEntries ];
+}
+
+// Returns a pair of maps [certNameToSKD, certSKDToName] between cert
+// nicknames and digests of the SPKInfo for the mozilla trust store
+function loadNSSCertinfo(derTestFile, extraCertificates) {
+ let allCerts = gCertDB.getCerts();
+ let enumerator = allCerts.getEnumerator();
+ let certNameToSKD = {};
+ let certSKDToName = {};
+ while (enumerator.hasMoreElements()) {
+ let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+ if (!isCertBuiltIn(cert)) {
+ continue;
+ }
+ let name = cert.nickname.substr(BUILT_IN_NICK_PREFIX.length);
+ let SKD = cert.sha256SubjectPublicKeyInfoDigest;
+ certNameToSKD[name] = SKD;
+ certSKDToName[SKD] = name;
+ }
+
+ for (let cert of extraCertificates) {
+ let name = cert.commonName;
+ let SKD = cert.sha256SubjectPublicKeyInfoDigest;
+ certNameToSKD[name] = SKD;
+ certSKDToName[SKD] = name;
+ }
+
+ {
+ // A certificate for *.example.com.
+ let der = readFileToString(derTestFile);
+ let testCert = gCertDB.constructX509(der, der.length);
+ // We can't include this cert in the previous loop, because it skips
+ // non-builtin certs and the nickname is not built-in to the cert.
+ let name = "End Entity Test Cert";
+ let SKD = testCert.sha256SubjectPublicKeyInfoDigest;
+ certNameToSKD[name] = SKD;
+ certSKDToName[SKD] = name;
+ }
+ return [certNameToSKD, certSKDToName];
+}
+
+function parseJson(filename) {
+ let json = stripComments(readFileToString(filename));
+ return JSON.parse(json);
+}
+
+function nameToAlias(certName) {
+ // change the name to a string valid as a c identifier
+ // remove non-ascii characters
+ certName = certName.replace( /[^[:ascii:]]/g, "_");
+ // replace non word characters
+ certName = certName.replace(/[^A-Za-z0-9]/g ,"_");
+
+ return "k" + certName + "Fingerprint";
+}
+
+function compareByName (a, b) {
+ return a.name.localeCompare(b.name);
+}
+
+function genExpirationTime() {
+ let now = new Date();
+ let nowMillis = now.getTime();
+ let expirationMillis = nowMillis + (PINNING_MINIMUM_REQUIRED_MAX_AGE * 1000);
+ let expirationMicros = expirationMillis * 1000;
+ return "static const PRTime kPreloadPKPinsExpirationTime = INT64_C(" +
+ expirationMicros +");\n";
+}
+
+function writeFullPinset(certNameToSKD, certSKDToName, pinset) {
+ // We aren't guaranteed to have sha1 hashes in our own imported pins.
+ let prefix = "kPinset_" + pinset.name;
+ let sha1Name = "nullptr";
+ let sha256Name = "nullptr";
+ if (pinset.sha1_hashes && pinset.sha1_hashes.length > 0) {
+ writeFingerprints(certNameToSKD, certSKDToName, pinset.name,
+ pinset.sha1_hashes, "sha1");
+ sha1Name = "&" + prefix + "_sha1";
+ }
+ if (pinset.sha256_hashes && pinset.sha256_hashes.length > 0) {
+ writeFingerprints(certNameToSKD, certSKDToName, pinset.name,
+ pinset.sha256_hashes, "sha256");
+ sha256Name = "&" + prefix + "_sha256";
+ }
+ writeString("static const StaticPinset " + prefix + " = {\n" +
+ " " + sha1Name + ",\n " + sha256Name + "\n};\n\n");
+}
+
+function writeFingerprints(certNameToSKD, certSKDToName, name, hashes, type) {
+ let varPrefix = "kPinset_" + name + "_" + type;
+ writeString("static const char* " + varPrefix + "_Data[] = {\n");
+ let SKDList = [];
+ for (let certName of hashes) {
+ if (!(certName in certNameToSKD)) {
+ throw "Can't find " + certName + " in certNameToSKD";
+ }
+ SKDList.push(certNameToSKD[certName]);
+ }
+ for (let skd of SKDList.sort()) {
+ writeString(" " + nameToAlias(certSKDToName[skd]) + ",\n");
+ }
+ if (hashes.length == 0) {
+ // ANSI C requires that an initialiser list be non-empty.
+ writeString(" 0\n");
+ }
+ writeString("};\n");
+ writeString("static const StaticFingerprints " + varPrefix + " = {\n " +
+ "sizeof(" + varPrefix + "_Data) / sizeof(const char*),\n " + varPrefix +
+ "_Data\n};\n\n");
+}
+
+function writeEntry(entry) {
+ let printVal = " { \"" + entry.name + "\",\ ";
+ if (entry.include_subdomains) {
+ printVal += "true, ";
+ } else {
+ printVal += "false, ";
+ }
+ // Default to test mode if not specified.
+ let testMode = true;
+ if (entry.hasOwnProperty("test_mode")) {
+ testMode = entry.test_mode;
+ }
+ if (testMode) {
+ printVal += "true, ";
+ } else {
+ printVal += "false, ";
+ }
+ if (entry.is_moz || (entry.pins == "mozilla")) {
+ printVal += "true, ";
+ } else {
+ printVal += "false, ";
+ }
+ if (entry.id >= 256) {
+ throw("Not enough buckets in histogram");
+ }
+ if (entry.id >= 0) {
+ printVal += entry.id + ", ";
+ } else {
+ printVal += "-1, ";
+ }
+ printVal += "&kPinset_" + entry.pins;
+ printVal += " },\n";
+ writeString(printVal);
+}
+
+function writeDomainList(chromeImportedEntries) {
+ writeString("/* Sort hostnames for binary search. */\n");
+ writeString("static const TransportSecurityPreload " +
+ "kPublicKeyPinningPreloadList[] = {\n");
+ let count = 0;
+ let sortedEntries = gStaticPins.entries;
+ sortedEntries.push.apply(sortedEntries, chromeImportedEntries);
+ for (let entry of sortedEntries.sort(compareByName)) {
+ count++;
+ writeEntry(entry);
+ }
+ writeString("};\n");
+
+ writeString("\n// Pinning Preload List Length = " + count + ";\n");
+ writeString("\nstatic const int32_t kUnknownId = -1;\n");
+}
+
+function writeFile(certNameToSKD, certSKDToName,
+ chromeImportedPinsets, chromeImportedEntries) {
+ // Compute used pins from both Chrome's and our pinsets, so we can output
+ // them later.
+ usedFingerprints = {};
+ gStaticPins.pinsets.forEach(function(pinset) {
+ // We aren't guaranteed to have sha1_hashes in our own JSON.
+ if (pinset.sha1_hashes) {
+ pinset.sha1_hashes.forEach(function(name) {
+ usedFingerprints[name] = true;
+ });
+ }
+ if (pinset.sha256_hashes) {
+ pinset.sha256_hashes.forEach(function(name) {
+ usedFingerprints[name] = true;
+ });
+ }
+ });
+ for (let key in chromeImportedPinsets) {
+ let pinset = chromeImportedPinsets[key];
+ pinset.sha1_hashes.forEach(function(name) {
+ usedFingerprints[name] = true;
+ });
+ pinset.sha256_hashes.forEach(function(name) {
+ usedFingerprints[name] = true;
+ });
+ }
+
+ writeString(FILE_HEADER);
+
+ // Write actual fingerprints.
+ Object.keys(usedFingerprints).sort().forEach(function(certName) {
+ if (certName) {
+ writeString("/* " + certName + " */\n");
+ writeString("static const char " + nameToAlias(certName) + "[] =\n");
+ writeString(" \"" + certNameToSKD[certName] + "\";\n");
+ writeString("\n");
+ }
+ });
+
+ // Write the pinsets
+ writeString(PINSETDEF);
+ writeString("/* PreloadedHPKPins.json pinsets */\n");
+ gStaticPins.pinsets.sort(compareByName).forEach(function(pinset) {
+ writeFullPinset(certNameToSKD, certSKDToName, pinset);
+ });
+ writeString("/* Chrome static pinsets */\n");
+ for (let key in chromeImportedPinsets) {
+ writeFullPinset(certNameToSKD, certSKDToName, chromeImportedPinsets[key]);
+ }
+
+ // Write the domainlist entries.
+ writeString(DOMAINHEADER);
+ writeDomainList(chromeImportedEntries);
+ writeString("\n");
+ writeString(genExpirationTime());
+}
+
+function loadExtraCertificates(certStringList) {
+ let constructedCerts = [];
+ for (let certString of certStringList) {
+ constructedCerts.push(gCertDB.constructX509FromBase64(certString));
+ }
+ return constructedCerts;
+}
+
+let extraCertificates = loadExtraCertificates(gStaticPins.extra_certificates);
+let [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(gTestCertFile,
+ extraCertificates);
+let [ chromeNameToHash, chromeNameToMozName ] = downloadAndParseChromeCerts(
+ gStaticPins.chromium_data.cert_file_url, certSKDToName);
+let [ chromeImportedPinsets, chromeImportedEntries ] =
+ downloadAndParseChromePins(gStaticPins.chromium_data.json_file_url,
+ chromeNameToHash, chromeNameToMozName, certNameToSKD, certSKDToName);
+
+writeFile(certNameToSKD, certSKDToName, chromeImportedPinsets,
+ chromeImportedEntries);
+
+FileUtils.closeSafeFileOutputStream(gFileOutputStream);
diff --git a/security/pkix/include/pkix/Result.h b/security/pkix/include/pkix/Result.h
new file mode 100644
index 0000000..e82e6428
--- /dev/null
+++ b/security/pkix/include/pkix/Result.h
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+/* Copyright 2013 Mozilla Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef mozilla_pkix__Result_h
+#define mozilla_pkix__Result_h
+
+#include <cassert>
+
+#include "pkix/enumclass.h"
+
+namespace mozilla { namespace pkix {
+
+static const unsigned int FATAL_ERROR_FLAG = 0x800;
+
+// The first argument to MOZILLA_PKIX_MAP() is used for building the mapping
+// from error code to error name in MapResultToName.
+//
+// The second argument is for defining the value for the enum literal in the
+// Result enum class.
+//
+// The third argument to MOZILLA_PKIX_MAP() is used, along with the first
+// argument, for maintaining the mapping of mozilla::pkix error codes to
+// NSS/NSPR error codes in pkixnss.cpp.
+#define MOZILLA_PKIX_MAP_LIST \
+ MOZILLA_PKIX_MAP(Success, 0, 0) \
+ MOZILLA_PKIX_MAP(ERROR_BAD_DER, 1, \
+ SEC_ERROR_BAD_DER) \
+ MOZILLA_PKIX_MAP(ERROR_CA_CERT_INVALID, 2, \
+ SEC_ERROR_CA_CERT_INVALID) \
+ MOZILLA_PKIX_MAP(ERROR_BAD_SIGNATURE, 3, \
+ SEC_ERROR_BAD_SIGNATURE) \
+ MOZILLA_PKIX_MAP(ERROR_CERT_BAD_ACCESS_LOCATION, 4, \
+ SEC_ERROR_CERT_BAD_ACCESS_LOCATION) \
+ MOZILLA_PKIX_MAP(ERROR_CERT_NOT_IN_NAME_SPACE, 5, \
+ SEC_ERROR_CERT_NOT_IN_NAME_SPACE) \
+ MOZILLA_PKIX_MAP(ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, 6, \
+ SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) \
+ MOZILLA_PKIX_MAP(ERROR_CONNECT_REFUSED, 7, \
+ PR_CONNECT_REFUSED_ERROR) \
+ MOZILLA_PKIX_MAP(ERROR_EXPIRED_CERTIFICATE, 8, \
+ SEC_ERROR_EXPIRED_CERTIFICATE) \
+ MOZILLA_PKIX_MAP(ERROR_EXTENSION_VALUE_INVALID, 9, \
+ SEC_ERROR_EXTENSION_VALUE_INVALID) \
+ MOZILLA_PKIX_MAP(ERROR_INADEQUATE_CERT_TYPE, 10, \
+ SEC_ERROR_INADEQUATE_CERT_TYPE) \
+ MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_USAGE, 11, \
+ SEC_ERROR_INADEQUATE_KEY_USAGE) \
+ MOZILLA_PKIX_MAP(ERROR_INVALID_ALGORITHM, 12, \
+ SEC_ERROR_INVALID_ALGORITHM) \
+ MOZILLA_PKIX_MAP(ERROR_INVALID_TIME, 13, \
+ SEC_ERROR_INVALID_TIME) \
+ MOZILLA_PKIX_MAP(ERROR_KEY_PINNING_FAILURE, 14, \
+ MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE) \
+ MOZILLA_PKIX_MAP(ERROR_PATH_LEN_CONSTRAINT_INVALID, 15, \
+ SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID) \
+ MOZILLA_PKIX_MAP(ERROR_POLICY_VALIDATION_FAILED, 16, \
+ SEC_ERROR_POLICY_VALIDATION_FAILED) \
+ MOZILLA_PKIX_MAP(ERROR_REVOKED_CERTIFICATE, 17, \
+ SEC_ERROR_REVOKED_CERTIFICATE) \
+ MOZILLA_PKIX_MAP(ERROR_UNKNOWN_CRITICAL_EXTENSION, 18, \
+ SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION) \
+ MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ERROR, 19, \
+ PR_UNKNOWN_ERROR) \
+ MOZILLA_PKIX_MAP(ERROR_UNKNOWN_ISSUER, 20, \
+ SEC_ERROR_UNKNOWN_ISSUER) \
+ MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_CERT, 21, \
+ SEC_ERROR_UNTRUSTED_CERT) \
+ MOZILLA_PKIX_MAP(ERROR_UNTRUSTED_ISSUER, 22, \
+ SEC_ERROR_UNTRUSTED_ISSUER) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_BAD_SIGNATURE, 23, \
+ SEC_ERROR_OCSP_BAD_SIGNATURE) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_INVALID_SIGNING_CERT, 24, \
+ SEC_ERROR_OCSP_INVALID_SIGNING_CERT) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_REQUEST, 25, \
+ SEC_ERROR_OCSP_MALFORMED_REQUEST) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_MALFORMED_RESPONSE, 26, \
+ SEC_ERROR_OCSP_MALFORMED_RESPONSE) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_OLD_RESPONSE, 27, \
+ SEC_ERROR_OCSP_OLD_RESPONSE) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_REQUEST_NEEDS_SIG, 28, \
+ SEC_ERROR_OCSP_REQUEST_NEEDS_SIG) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_RESPONDER_CERT_INVALID, 29, \
+ SEC_ERROR_OCSP_RESPONDER_CERT_INVALID) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_SERVER_ERROR, 30, \
+ SEC_ERROR_OCSP_SERVER_ERROR) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_TRY_SERVER_LATER, 31, \
+ SEC_ERROR_OCSP_TRY_SERVER_LATER) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_UNAUTHORIZED_REQUEST, 32, \
+ SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, 33, \
+ SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_UNKNOWN_CERT, 34, \
+ SEC_ERROR_OCSP_UNKNOWN_CERT) \
+ MOZILLA_PKIX_MAP(ERROR_OCSP_FUTURE_RESPONSE, 35, \
+ SEC_ERROR_OCSP_FUTURE_RESPONSE) \
+ MOZILLA_PKIX_MAP(ERROR_INVALID_KEY, 36, \
+ SEC_ERROR_INVALID_KEY) \
+ MOZILLA_PKIX_MAP(ERROR_UNSUPPORTED_KEYALG, 37, \
+ SEC_ERROR_UNSUPPORTED_KEYALG) \
+ MOZILLA_PKIX_MAP(ERROR_EXPIRED_ISSUER_CERTIFICATE, 38, \
+ SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE) \
+ MOZILLA_PKIX_MAP(ERROR_CA_CERT_USED_AS_END_ENTITY, 39, \
+ MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY) \
+ MOZILLA_PKIX_MAP(ERROR_INADEQUATE_KEY_SIZE, 40, \
+ MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE) \
+ MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_ARGS, FATAL_ERROR_FLAG | 1, \
+ SEC_ERROR_INVALID_ARGS) \
+ MOZILLA_PKIX_MAP(FATAL_ERROR_INVALID_STATE, FATAL_ERROR_FLAG | 2, \
+ PR_INVALID_STATE_ERROR) \
+ MOZILLA_PKIX_MAP(FATAL_ERROR_LIBRARY_FAILURE, FATAL_ERROR_FLAG | 3, \
+ SEC_ERROR_LIBRARY_FAILURE) \
+ MOZILLA_PKIX_MAP(FATAL_ERROR_NO_MEMORY, FATAL_ERROR_FLAG | 4, \
+ SEC_ERROR_NO_MEMORY) \
+ /* nothing here */
+
+MOZILLA_PKIX_ENUM_CLASS Result
+{
+#define MOZILLA_PKIX_MAP(name, value, nss_name) name = value,
+ MOZILLA_PKIX_MAP_LIST
+#undef MOZILLA_PKIX_MAP
+};
+
+// Returns the stringified name of the given result, e.g. "Result::Success",
+// or nullptr if result is unknown (invalid).
+const char* MapResultToName(Result result);
+
+// We write many comparisons as (x != Success), and this shortened name makes
+// those comparisons clearer, especially because the shortened name often
+// results in less line wrapping.
+//
+// Visual Studio before VS2013 does not support "enum class," so
+// Result::Success will already be visible in this scope, and compilation will
+// fail if we try to define a variable with that name here.
+#if !defined(_MSC_VER) || (_MSC_VER >= 1700)
+static const Result Success = Result::Success;
+#endif
+
+inline bool
+IsFatalError(Result rv)
+{
+ return (static_cast<unsigned int>(rv) & FATAL_ERROR_FLAG) != 0;
+}
+
+inline Result
+NotReached(const char* /*explanation*/, Result result)
+{
+ assert(false);
+ return result;
+}
+
+} } // namespace mozilla::pkix
+
+#endif // mozilla_pkix__Result_h
diff --git a/security/pkix/include/pkix/Time.h b/security/pkix/include/pkix/Time.h
new file mode 100644
index 0000000..b8d6ee9
--- /dev/null
+++ b/security/pkix/include/pkix/Time.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+/* Copyright 2014 Mozilla Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef mozilla_pkix__Time_h
+#define mozilla_pkix__Time_h
+
+#include <ctime>
+#include <limits>
+#include <stdint.h>
+
+#include "pkix/Result.h"
+
+namespace mozilla { namespace pkix {
+
+// Time with a range from the first second of year 0 (AD) through at least the
+// last second of year 9999, which is the range of legal times in X.509 and
+// OCSP. This type has second-level precision. The time zone is always UTC.
+//
+// Pass by value, not by reference.
+class Time
+{
+public:
+ // Construct an uninitilized instance.
+ //
+ // This will fail to compile because there is no default constructor:
+ // Time x;
+ //
+ // This will succeed, leaving the time uninitialized:
+ // Time x(Time::uninitialized);
+ enum Uninitialized { uninitialized };
+ explicit Time(Uninitialized) { }
+
+ bool operator==(const Time& other) const
+ {
+ return elapsedSecondsAD == other.elapsedSecondsAD;
+ }
+ bool operator>(const Time& other) const
+ {
+ return elapsedSecondsAD > other.elapsedSecondsAD;
+ }
+ bool operator>=(const Time& other) const
+ {
+ return elapsedSecondsAD >= other.elapsedSecondsAD;
+ }
+ bool operator<(const Time& other) const
+ {
+ return elapsedSecondsAD < other.elapsedSecondsAD;
+ }
+ bool operator<=(const Time& other) const
+ {
+ return elapsedSecondsAD <= other.elapsedSecondsAD;
+ }
+
+ Result AddSeconds(uint64_t seconds)
+ {
+ if (std::numeric_limits<uint64_t>::max() - elapsedSecondsAD
+ < seconds) {
+ return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
+ }
+ elapsedSecondsAD += seconds;
+ return Success;
+ }
+
+ Result SubtractSeconds(uint64_t seconds)
+ {
+ if (seconds > elapsedSecondsAD) {
+ return Result::FATAL_ERROR_INVALID_ARGS; // integer overflow
+ }
+ elapsedSecondsAD -= seconds;
+ return Success;
+ }
+
+ static const uint64_t ONE_DAY_IN_SECONDS
+ = UINT64_C(24) * UINT64_C(60) * UINT64_C(60);
+
+private:
+ // This constructor is hidden to prevent accidents like this:
+ //
+ // Time foo(time_t t)
+ // {
+ // // WRONG! 1970-01-01-00:00:00 == time_t(0), but not Time(0)!
+ // return Time(t);
+ // }
+ explicit Time(uint64_t elapsedSecondsAD)
+ : elapsedSecondsAD(elapsedSecondsAD)
+ {
+ }
+ friend Time TimeFromElapsedSecondsAD(uint64_t);
+
+ uint64_t elapsedSecondsAD;
+};
+
+inline Time TimeFromElapsedSecondsAD(uint64_t elapsedSecondsAD)
+{
+ return Time(elapsedSecondsAD);
+}
+
+Time Now();
+
+// Note the epoch is the unix epoch (ie 00:00:00 UTC, 1 January 1970)
+Time TimeFromEpochInSeconds(uint64_t secondsSinceEpoch);
+
+} } // namespace mozilla::pkix
+
+#endif // mozilla_pkix__Time_h
diff --git a/security/pkix/include/pkix/pkixtypes.h b/security/pkix/include/pkix/pkixtypes.h
index 0a64b9d..d38603b 100644
--- a/security/pkix/include/pkix/pkixtypes.h
+++ b/security/pkix/include/pkix/pkixtypes.h
@@ -120,6 +120,11 @@ public:
PRTime time,
/*optional*/ const SECItem* stapledOCSPresponse) = 0;
+ // Called as soon as we think we have a valid chain but before revocation
+ // checks are done. Called to compute additional chain level checks, by the
+ // TrustDomain.
+ virtual SECStatus IsChainValid(const CERTCertList* certChain) = 0;
+
protected:
TrustDomain() { }
diff --git a/security/pkix/lib/pkixbuild.cpp b/security/pkix/lib/pkixbuild.cpp
index 22e3f61..c078eda 100644
--- a/security/pkix/lib/pkixbuild.cpp
+++ b/security/pkix/lib/pkixbuild.cpp
@@ -225,6 +225,30 @@ BuildForward(TrustDomain& trustDomain,
}
if (trustLevel == TrustDomain::TrustAnchor) {
+ ScopedCERTCertList certChain(CERT_NewCertList());
+ if (!certChain) {
+ PR_SetError(SEC_ERROR_NO_MEMORY, 0);
+ return MapSECStatus(SECFailure);
+ }
+
+ rv = subject.PrependNSSCertToList(certChain.get());
+ if (rv != Success) {
+ return rv;
+ }
+ BackCert* child = subject.childCert;
+ while (child) {
+ rv = child->PrependNSSCertToList(certChain.get());
+ if (rv != Success) {
+ return rv;
+ }
+ child = child->childCert;
+ }
+
+ SECStatus srv = trustDomain.IsChainValid(certChain.get());
+ if (srv != SECSuccess) {
+ return MapSECStatus(srv);
+ }
+
// End of the recursion. Create the result list and add the trust anchor to
// it.
results = CERT_NewCertList();
diff --git a/security/pkix/lib/pkixtime.cpp b/security/pkix/lib/pkixtime.cpp
new file mode 100644
index 0000000..499784e
--- /dev/null
+++ b/security/pkix/lib/pkixtime.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+/* Copyright 2014 Mozilla Contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pkix/Time.h"
+#include "pkixutil.h"
+#ifdef WIN32
+#include "windows.h"
+#else
+#include "sys/time.h"
+#endif
+
+namespace mozilla { namespace pkix {
+
+Time
+Now()
+{
+ uint64_t seconds;
+
+#ifdef WIN32
+ // "Contains a 64-bit value representing the number of 100-nanosecond
+ // intervals since January 1, 1601 (UTC)."
+ // - http://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).a…
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ uint64_t ft64 = (static_cast<uint64_t>(ft.dwHighDateTime) << 32) |
+ ft.dwLowDateTime;
+ seconds = (DaysBeforeYear(1601) * Time::ONE_DAY_IN_SECONDS) +
+ ft64 / (1000u * 1000u * 1000u / 100u);
+#else
+ // "The gettimeofday() function shall obtain the current time, expressed as
+ // seconds and microseconds since the Epoch."
+ // - http://pubs.opengroup.org/onlinepubs/009695399/functions/gettimeofday.html
+ timeval tv;
+ (void) gettimeofday(&tv, nullptr);
+ seconds = (DaysBeforeYear(1970) * Time::ONE_DAY_IN_SECONDS) + tv.tv_sec;
+#endif
+
+ return TimeFromElapsedSecondsAD(seconds);
+}
+
+Time
+TimeFromEpochInSeconds(uint64_t secondsSinceEpoch)
+{
+ uint64_t seconds = (DaysBeforeYear(1970) * Time::ONE_DAY_IN_SECONDS) +
+ secondsSinceEpoch;
+ return TimeFromElapsedSecondsAD(seconds);
+}
+
+} } // namespace mozilla::pkix
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index 01a27a1..bf96ccd 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -5929,5 +5929,37 @@
"high": "5000",
"n_buckets": 10,
"extended_statistics_ok": true
+ },
+ "CERT_PINNING_RESULTS": {
+ "expires_in_version": "never",
+ "kind": "boolean",
+ "description": "Certificate pinning results (0 = failure, 1 = success)"
+ },
+ "CERT_PINNING_TEST_RESULTS": {
+ "expires_in_version": "never",
+ "kind": "boolean",
+ "description": "Certificate pinning test results (0 = failure, 1 = success)"
+ },
+ "CERT_PINNING_MOZ_RESULTS": {
+ "expires_in_version": "never",
+ "kind": "boolean",
+ "description": "Certificate pinning results for Mozilla sites (0 = failure, 1 = success)"
+ },
+ "CERT_PINNING_MOZ_TEST_RESULTS": {
+ "expires_in_version": "never",
+ "kind": "boolean",
+ "description": "Certificate pinning test results for Mozilla sites (0 = failure, 1 = success)"
+ },
+ "CERT_PINNING_MOZ_RESULTS_BY_HOST": {
+ "expires_in_version": "never",
+ "kind": "enumerated",
+ "n_values": 512,
+ "description": "Certificate pinning results by host for Mozilla operational sites"
+ },
+ "CERT_PINNING_MOZ_TEST_RESULTS_BY_HOST": {
+ "expires_in_version": "never",
+ "kind": "enumerated",
+ "n_values": 512,
+ "description": "Certificate pinning test results by host for Mozilla operational sites"
}
}
1
0
[tor-browser/tor-browser-31.2.0esr-4.5-1] fixup! TB3: Tor Browser's official .mozconfigs.
by mikeperry@torproject.org 30 Oct '14
by mikeperry@torproject.org 30 Oct '14
30 Oct '14
commit 672d66cc8b67815fb506ab78c231468098f8462c
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Wed Oct 29 15:19:19 2014 -0700
fixup! TB3: Tor Browser's official .mozconfigs.
Re-enable ICU.
---
.mozconfig-mac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.mozconfig-mac b/.mozconfig-mac
index 4abcc7c..9a38951 100644
--- a/.mozconfig-mac
+++ b/.mozconfig-mac
@@ -42,7 +42,7 @@ ac_add_options --enable-update-packaging
ac_add_options --disable-verify-mar
# ICU seems still to have cross-compiling issues:
-ac_add_options --without-intl-api
+#ac_add_options --without-intl-api
ac_add_options --disable-crashreporter
ac_add_options --disable-maintenance-service
ac_add_options --disable-webrtc
1
0
commit af7bd8eba8f6c442a3a628c0a957ec089409a464
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Tue Oct 28 17:54:15 2014 -0700
Remove old patches.
---
gitian/patches/bug10297.patch | 55 ----
gitian/patches/bug11069.patch | 209 --------------
gitian/patches/bug11156.patch | 275 -------------------
gitian/patches/bug11200-hang-0.2.5.patch | 81 ------
gitian/patches/bug11200.patch | 39 ---
gitian/patches/bug5018.patch | 225 ---------------
gitian/patches/bug8402.patch | 437 ------------------------------
gitian/patches/bug9665.patch | 108 --------
8 files changed, 1429 deletions(-)
diff --git a/gitian/patches/bug10297.patch b/gitian/patches/bug10297.patch
deleted file mode 100644
index 58dfdc2..0000000
--- a/gitian/patches/bug10297.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-From ad47e1a52072c2a4528e421a6a3bf9c7029f4501 Mon Sep 17 00:00:00 2001
-From: David Fifield <david(a)bamsoftware.com>
-Date: Thu, 5 Dec 2013 04:56:28 +0000
-Subject: [PATCH] Set CREATE_NO_WINDOW in tor_spawn_background.
-
-This flag prevents the creation of a console window popup on Windows. We
-need it for pluggable transport executables--otherwise you get blank
-console windows when you launch the 3.x browser bundle with transports
-enabled.
-
-http://msdn.microsoft.com/en-us/library/ms684863.aspx#CREATE_NO_WINDOW
-
-The browser bundles that used Vidalia used to set this flag when
-launching tor itself; it was apparently inherited by the pluggable
-transports launched by tor. In the 3.x bundles, tor is launched by some
-JavaScript code, which doesn't have the ability to set CREATE_NO_WINDOW.
-tor itself is now being compiled with the -mwindows option, so that it
-is a GUI application, not a console application, and doesn't show a
-console window in any case. This workaround doesn't work for pluggable
-transports, because they need to be able to write control messages to
-stdout.
-
-https://trac.torproject.org/projects/tor/ticket/9444#comment:30
----
- changes/bug10297 | 4 ++++
- src/common/util.c | 2 +-
- 2 files changed, 5 insertions(+), 1 deletion(-)
- create mode 100644 changes/bug10297
-
-diff --git a/changes/bug10297 b/changes/bug10297
-new file mode 100644
-index 0000000..4cdd80f
---- /dev/null
-+++ b/changes/bug10297
-@@ -0,0 +1,4 @@
-+ o Minor features:
-+ - Spawn background processes using the CREATE_NO_WINDOW flag on
-+ Windows, in order to prevent a console window from appearing.
-+ Resolves ticket 10297.
-diff --git a/src/common/util.c b/src/common/util.c
-index 5eb0f9a..252f6af 100644
---- a/src/common/util.c
-+++ b/src/common/util.c
-@@ -3685,7 +3685,7 @@ tor_spawn_background(const char *const filename, const char **argv,
- TRUE, // handles are inherited
- /*(TODO: set CREATE_NEW CONSOLE/PROCESS_GROUP to make GetExitCodeProcess()
- * work?) */
-- 0, // creation flags
-+ CREATE_NO_WINDOW, // creation flags
- (env==NULL) ? NULL : env->windows_environment_block,
- NULL, // use parent's current directory
- &siStartInfo, // STARTUPINFO pointer
---
-1.7.9.5
-
diff --git a/gitian/patches/bug11069.patch b/gitian/patches/bug11069.patch
deleted file mode 100644
index b6032e9..0000000
--- a/gitian/patches/bug11069.patch
+++ /dev/null
@@ -1,209 +0,0 @@
-From 67c70b2566fc9bef4527fb8a0c24ce7d8c4d0647 Mon Sep 17 00:00:00 2001
-From: George Kadianakis <desnacked(a)riseup.net>
-Date: Mon, 10 Mar 2014 22:52:07 +0000
-Subject: [PATCH] Throw control port warning if we failed to connect to all our
- bridges.
-
-Conflicts:
- src/or/connection.c
- src/or/control.c
- src/or/control.h
- src/test/test_extorport.c
----
- changes/bug11069 | 4 ++++
- src/or/connection.c | 25 +++++++++++++++++++++++++
- src/or/connection.h | 2 ++
- src/or/connection_or.c | 8 +++++---
- src/or/control.c | 13 ++++++++-----
- src/or/control.h | 3 ++-
- src/or/entrynodes.c | 21 ---------------------
- src/or/entrynodes.h | 1 -
- 8 files changed, 46 insertions(+), 31 deletions(-)
- create mode 100644 changes/bug11069
-
-diff --git a/changes/bug11069 b/changes/bug11069
-new file mode 100644
-index 0000000..5aa3085
---- /dev/null
-+++ b/changes/bug11069
-@@ -0,0 +1,4 @@
-+ o Minor bugfixes (clients):
-+ - Fix tor so that it raises a control port warning when we fail to
-+ connect to all of our bridges. Fixes bug 11069; bugfix on
-+ tor-0.2.1.2-alpha.
-diff --git a/src/or/connection.c b/src/or/connection.c
-index 4f74a1d..ba28d81 100644
---- a/src/or/connection.c
-+++ b/src/or/connection.c
-@@ -3846,6 +3846,31 @@ connection_get_by_type_purpose(int type, int purpose)
- return NULL;
- }
-
-+/** Return 1 if there are any active OR connections apart from
-+ * <b>this_conn</b>.
-+ *
-+ * We use this to guess if we should tell the controller that we
-+ * didn't manage to connect to any of our bridges. */
-+int
-+any_other_active_or_conns(const or_connection_t *this_conn)
-+{
-+ smartlist_t *conns = get_connection_array();
-+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
-+ if (conn == TO_CONN(this_conn)) { /* don't consider this conn */
-+ continue;
-+ }
-+
-+ if (conn->type == CONN_TYPE_OR &&
-+ !conn->marked_for_close) {
-+ log_debug(LD_DIR, "%s: Found an OR connection: %s",
-+ __func__, conn->address);
-+ return 1;
-+ }
-+ } SMARTLIST_FOREACH_END(conn);
-+
-+ return 0;
-+}
-+
- /** Return 1 if <b>conn</b> is a listener conn, else return 0. */
- int
- connection_is_listener(connection_t *conn)
-diff --git a/src/or/connection.h b/src/or/connection.h
-index c78fe6e..9bd5f88 100644
---- a/src/or/connection.h
-+++ b/src/or/connection.h
-@@ -180,6 +180,8 @@ connection_t *connection_get_by_type_state_rendquery(int type, int state,
- dir_connection_t *connection_dir_get_by_purpose_and_resource(
- int state, const char *resource);
-
-+int any_other_active_or_conns(const or_connection_t *this_conn);
-+
- #define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR)
- int connection_is_listener(connection_t *conn);
- int connection_state_is_open(connection_t *conn);
-diff --git a/src/or/connection_or.c b/src/or/connection_or.c
-index 8e7cd9e..8684f18 100644
---- a/src/or/connection_or.c
-+++ b/src/or/connection_or.c
-@@ -645,7 +645,8 @@ connection_or_about_to_close(or_connection_t *or_conn)
- reason);
- if (!authdir_mode_tests_reachability(options))
- control_event_bootstrap_problem(
-- orconn_end_reason_to_control_string(reason), reason);
-+ orconn_end_reason_to_control_string(reason),
-+ reason, or_conn);
- }
- }
- } else if (conn->hold_open_until_flushed) {
-@@ -1008,7 +1009,7 @@ connection_or_connect_failed(or_connection_t *conn,
- {
- control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, reason);
- if (!authdir_mode_tests_reachability(get_options()))
-- control_event_bootstrap_problem(msg, reason);
-+ control_event_bootstrap_problem(msg, reason, conn);
- }
-
- /** <b>conn</b> got an error in connection_handle_read_impl() or
-@@ -1638,7 +1639,8 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
- if (!authdir_mode_tests_reachability(options))
- control_event_bootstrap_problem(
- "Unexpected identity in router certificate",
-- END_OR_CONN_REASON_OR_IDENTITY);
-+ END_OR_CONN_REASON_OR_IDENTITY,
-+ conn);
- return -1;
- }
- if (authdir_mode_tests_reachability(options)) {
-diff --git a/src/or/control.c b/src/or/control.c
-index a88de12..cd2c55c 100644
---- a/src/or/control.c
-+++ b/src/or/control.c
-@@ -4696,10 +4696,12 @@ control_event_bootstrap(bootstrap_status_t status, int progress)
-
- /** Called when Tor has failed to make bootstrapping progress in a way
- * that indicates a problem. <b>warn</b> gives a hint as to why, and
-- * <b>reason</b> provides an "or_conn_end_reason" tag.
-+ * <b>reason</b> provides an "or_conn_end_reason" tag. <b>or_conn</b>
-+ * is the connection that caused this problem.
- */
- void
--control_event_bootstrap_problem(const char *warn, int reason)
-+control_event_bootstrap_problem(const char *warn, int reason,
-+ const or_connection_t *or_conn)
- {
- int status = bootstrap_percent;
- const char *tag, *summary;
-@@ -4721,9 +4723,10 @@ control_event_bootstrap_problem(const char *warn, int reason)
- if (reason == END_OR_CONN_REASON_NO_ROUTE)
- recommendation = "warn";
-
-- if (get_options()->UseBridges &&
-- !any_bridge_descriptors_known() &&
-- !any_pending_bridge_descriptor_fetches())
-+ /* If we are using bridges and all our OR connections are now
-+ closed, it means that we totally failed to connect to our
-+ bridges. Throw a warning. */
-+ if (get_options()->UseBridges && !any_other_active_or_conns(or_conn))
- recommendation = "warn";
-
- if (we_are_hibernating())
-diff --git a/src/or/control.h b/src/or/control.h
-index 61062da..1d90a90 100644
---- a/src/or/control.h
-+++ b/src/or/control.h
-@@ -85,7 +85,8 @@ void enable_control_logging(void);
- void monitor_owning_controller_process(const char *process_spec);
-
- void control_event_bootstrap(bootstrap_status_t status, int progress);
--void control_event_bootstrap_problem(const char *warn, int reason);
-+void control_event_bootstrap_problem(const char *warn, int reason,
-+ const or_connection_t *or_conn);
-
- void control_event_clients_seen(const char *controller_str);
-
-diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
-index 2aa063c..b145c94 100644
---- a/src/or/entrynodes.c
-+++ b/src/or/entrynodes.c
-@@ -2134,27 +2134,6 @@ any_bridge_descriptors_known(void)
- return choose_random_entry(NULL) != NULL;
- }
-
--/** Return 1 if there are any directory conns fetching bridge descriptors
-- * that aren't marked for close. We use this to guess if we should tell
-- * the controller that we have a problem. */
--int
--any_pending_bridge_descriptor_fetches(void)
--{
-- smartlist_t *conns = get_connection_array();
-- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
-- if (conn->type == CONN_TYPE_DIR &&
-- conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
-- TO_DIR_CONN(conn)->router_purpose == ROUTER_PURPOSE_BRIDGE &&
-- !conn->marked_for_close &&
-- conn->linked &&
-- conn->linked_conn && !conn->linked_conn->marked_for_close) {
-- log_debug(LD_DIR, "found one: %s", conn->address);
-- return 1;
-- }
-- } SMARTLIST_FOREACH_END(conn);
-- return 0;
--}
--
- /** Return 1 if we have at least one descriptor for an entry guard
- * (bridge or member of EntryNodes) and all descriptors we know are
- * down. Else return 0. If <b>act</b> is 1, then mark the down guards
-diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
-index 52b8dc0..f6c07d9 100644
---- a/src/or/entrynodes.h
-+++ b/src/or/entrynodes.h
-@@ -104,7 +104,6 @@ void retry_bridge_descriptor_fetch_directly(const char *digest);
- void fetch_bridge_descriptors(const or_options_t *options, time_t now);
- void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);
- int any_bridge_descriptors_known(void);
--int any_pending_bridge_descriptor_fetches(void);
- int entries_known_but_down(const or_options_t *options);
- void entries_retry_all(const or_options_t *options);
-
---
-1.8.1.2
-
diff --git a/gitian/patches/bug11156.patch b/gitian/patches/bug11156.patch
deleted file mode 100644
index d9f8e7a..0000000
--- a/gitian/patches/bug11156.patch
+++ /dev/null
@@ -1,275 +0,0 @@
-From af42f9b9125fb3f50f7383e63fb02bab1df82db9 Mon Sep 17 00:00:00 2001
-From: George Kadianakis <desnacked(a)riseup.net>
-Date: Wed, 12 Mar 2014 20:25:05 -0700
-Subject: [PATCH] Don't do directory fetches before all PTs have been
- configured.
-
----
- src/or/microdesc.c | 2 +-
- src/or/networkstatus.c | 36 ++++++++++++++++++++++++++++++------
- src/or/networkstatus.h | 2 +-
- src/or/nodelist.c | 8 ++++----
- src/or/routerlist.c | 6 +++---
- 5 files changed, 39 insertions(+), 15 deletions(-)
-
-diff --git a/src/or/microdesc.c b/src/or/microdesc.c
-index 90ac0ac..1f12347 100644
---- a/src/or/microdesc.c
-+++ b/src/or/microdesc.c
-@@ -725,7 +725,7 @@ update_microdesc_downloads(time_t now)
- smartlist_t *missing;
- digestmap_t *pending;
-
-- if (should_delay_dir_fetches(options))
-+ if (should_delay_dir_fetches(options, NULL))
- return;
- if (directory_too_idle_to_fetch_descriptors(options, now))
- return;
-diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
-index 1b5c6db..bcadc52 100644
---- a/src/or/networkstatus.c
-+++ b/src/or/networkstatus.c
-@@ -31,6 +31,7 @@
- #include "router.h"
- #include "routerlist.h"
- #include "routerparse.h"
-+#include "transports.h"
-
- /* For tracking v2 networkstatus documents. Only caches do this now. */
-
-@@ -1380,14 +1381,37 @@ update_consensus_networkstatus_fetch_time(time_t now)
-
- /** Return 1 if there's a reason we shouldn't try any directory
- * fetches yet (e.g. we demand bridges and none are yet known).
-- * Else return 0. */
-+ * Else return 0.
-+
-+ * If we return 1 and <b>msg_out</b> is provided, set <b>msg_out</b>
-+ * to an explanation of why directory fetches are delayed. (If we
-+ * return 0, we set msg_out to NULL.)
-+ */
- int
--should_delay_dir_fetches(const or_options_t *options)
-+should_delay_dir_fetches(const or_options_t *options, const char **msg_out)
- {
-- if (options->UseBridges && !any_bridge_descriptors_known()) {
-- log_info(LD_DIR, "delaying dir fetches (no running bridges known)");
-- return 1;
-+ if (msg_out) {
-+ *msg_out = NULL;
- }
-+
-+ if (options->UseBridges) {
-+ if (!any_bridge_descriptors_known()) {
-+ if (msg_out) {
-+ *msg_out = "No running bridges";
-+ }
-+ log_info(LD_DIR, "Delaying dir fetches (no running bridges known)");
-+ return 1;
-+ }
-+
-+ if (pt_proxies_configuration_pending()) {
-+ if (msg_out) {
-+ *msg_out = "Pluggable transport proxies still configuring";
-+ }
-+ log_info(LD_DIR, "Delaying dir fetches (pt proxies still configuring)");
-+ return 1;
-+ }
-+ }
-+
- return 0;
- }
-
-@@ -1397,7 +1421,7 @@ void
- update_networkstatus_downloads(time_t now)
- {
- const or_options_t *options = get_options();
-- if (should_delay_dir_fetches(options))
-+ if (should_delay_dir_fetches(options, NULL))
- return;
- if (authdir_mode_any_main(options) || options->FetchV2Networkstatus)
- update_v2_networkstatus_cache_downloads(now);
-diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
-index 761f8e7..f50f6f1 100644
---- a/src/or/networkstatus.h
-+++ b/src/or/networkstatus.h
-@@ -69,7 +69,7 @@ int networkstatus_nickname_is_unnamed(const char *nickname);
- void networkstatus_consensus_download_failed(int status_code,
- const char *flavname);
- void update_consensus_networkstatus_fetch_time(time_t now);
--int should_delay_dir_fetches(const or_options_t *options);
-+int should_delay_dir_fetches(const or_options_t *options,const char **msg_out);
- void update_networkstatus_downloads(time_t now);
- void update_certificate_downloads(time_t now);
- int consensus_is_waiting_for_certs(void);
-diff --git a/src/or/nodelist.c b/src/or/nodelist.c
-index 178f084..600a1fd 100644
---- a/src/or/nodelist.c
-+++ b/src/or/nodelist.c
-@@ -1439,6 +1439,7 @@ update_router_have_minimum_dir_info(void)
- const networkstatus_t *consensus =
- networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
- int using_md;
-+ const char *delay_fetches_msg = NULL;
-
- if (!consensus) {
- if (!networkstatus_get_latest_consensus())
-@@ -1451,10 +1452,9 @@ update_router_have_minimum_dir_info(void)
- goto done;
- }
-
-- if (should_delay_dir_fetches(get_options())) {
-- log_notice(LD_DIR, "no known bridge descriptors running yet; stalling");
-- strlcpy(dir_info_status, "No live bridge descriptors.",
-- sizeof(dir_info_status));
-+ if (should_delay_dir_fetches(get_options(), &delay_fetches_msg)) {
-+ log_notice(LD_DIR, "Delaying dir fetches: %s", delay_fetches_msg);
-+ strlcpy(dir_info_status, "%s", sizeof(dir_info_status));
- res = 0;
- goto done;
- }
-diff --git a/src/or/routerlist.c b/src/or/routerlist.c
-index cb39729..d78c7bb 100644
---- a/src/or/routerlist.c
-+++ b/src/or/routerlist.c
-@@ -684,7 +684,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now)
- char id_digest_str[2*DIGEST_LEN+1];
- char sk_digest_str[2*DIGEST_LEN+1];
-
-- if (should_delay_dir_fetches(get_options()))
-+ if (should_delay_dir_fetches(get_options(), NULL))
- return;
-
- pending_cert = fp_pair_map_new();
-@@ -4901,7 +4901,7 @@ void
- update_router_descriptor_downloads(time_t now)
- {
- const or_options_t *options = get_options();
-- if (should_delay_dir_fetches(options))
-+ if (should_delay_dir_fetches(options, NULL))
- return;
- if (!we_fetch_router_descriptors(options))
- return;
-@@ -4925,7 +4925,7 @@ update_extrainfo_downloads(time_t now)
- int n_no_ei = 0, n_pending = 0, n_have = 0, n_delay = 0;
- if (! options->DownloadExtraInfo)
- return;
-- if (should_delay_dir_fetches(options))
-+ if (should_delay_dir_fetches(options, NULL))
- return;
- if (!router_have_minimum_dir_info())
- return;
---
-1.8.1.2
-
-From 1a3eb5c72dd0feb43a542ca465c57dd0801ff7cc Mon Sep 17 00:00:00 2001
-From: George Kadianakis <desnacked(a)riseup.net>
-Date: Tue, 8 Apr 2014 16:59:46 +0100
-Subject: [PATCH 1/4] Don't halt bootstrap to figure out if we should restart
- PT proxies.
-
-Instead, figure out if we should restart PT proxies _immediately_ after
-we re-read the config file.
----
- changes/bug11156 | 5 +++++
- src/or/config.c | 6 ++++++
- src/or/transports.c | 3 +--
- 3 files changed, 12 insertions(+), 2 deletions(-)
- create mode 100644 changes/bug11156
-
-diff --git a/changes/bug11156 b/changes/bug11156
-new file mode 100644
-index 0000000..bb20ed1e
---- /dev/null
-+++ b/changes/bug11156
-@@ -0,0 +1,5 @@
-+ o Minor bugfixes (clients):
-+ - Fix a bug where a client-side Tor with pluggable transports
-+ would take 60 seconds to bootstrap if a config re-read was
-+ triggered at just the right timing during bootstrap. Refixes bug
-+ 11156; bugfix on 0.2.5.3-alpha.
-\ No newline at end of file
-diff --git a/src/or/config.c b/src/or/config.c
-index dbf643c..c2d6545 100644
---- a/src/or/config.c
-+++ b/src/or/config.c
-@@ -1433,6 +1433,12 @@ options_act(const or_options_t *old_options)
- sweep_transport_list();
- sweep_proxy_list();
-
-+ /* Start the PT proxy configuration. By doing this configuration
-+ here, we also figure out which proxies need to be restarted and
-+ which not. */
-+ if (pt_proxies_configuration_pending())
-+ pt_configure_remaining_proxies();
-+
- /* Bail out at this point if we're not going to be a client or server:
- * we want to not fork, and to log stuff to stderr. */
- if (!running_tor)
-diff --git a/src/or/transports.c b/src/or/transports.c
-index 7e496fe..e1876d6 100644
---- a/src/or/transports.c
-+++ b/src/or/transports.c
-@@ -534,8 +534,7 @@ launch_managed_proxy(managed_proxy_t *mp)
- }
-
- /** Check if any of the managed proxies we are currently trying to
-- * configure have anything new to say. This is called from
-- * run_scheduled_events(). */
-+ * configure has anything new to say. */
- void
- pt_configure_remaining_proxies(void)
- {
---
-1.8.1.2
-
-From 4719a2f5248b8cf6d70daef91fd1cf9fd65628f4 Mon Sep 17 00:00:00 2001
-From: George Kadianakis <desnacked(a)riseup.net>
-Date: Mon, 21 Apr 2014 14:17:35 +0300
-Subject: [PATCH 4/4] fixup! Don't halt bootstrap to figure out if we should
- restart PT proxies.
-
----
- src/or/config.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/or/config.c b/src/or/config.c
-index c2d6545..551b09f 100644
---- a/src/or/config.c
-+++ b/src/or/config.c
-@@ -1436,7 +1436,7 @@ options_act(const or_options_t *old_options)
- /* Start the PT proxy configuration. By doing this configuration
- here, we also figure out which proxies need to be restarted and
- which not. */
-- if (pt_proxies_configuration_pending())
-+ if (pt_proxies_configuration_pending() && !net_is_disabled())
- pt_configure_remaining_proxies();
-
- /* Bail out at this point if we're not going to be a client or server:
---
-1.8.1.2
-
-From dfcbc4500aad07a641e9e856d442c848d86d2c7e Mon Sep 17 00:00:00 2001
-From: George Kadianakis <desnacked(a)riseup.net>
-Date: Thu, 1 May 2014 17:32:29 +0100
-Subject: [PATCH] fixup! Fix a misuse of strlcpy() introduced by the #11156
- patch.
-
----
- changes/bug11654 | 4 ++++
- 1 file changed, 4 insertions(+)
- create mode 100644 changes/bug11654
-
-diff --git a/changes/bug11654 b/changes/bug11654
-new file mode 100644
-index 0000000..97c70b2
---- /dev/null
-+++ b/changes/bug11654
-@@ -0,0 +1,4 @@
-+ o Minor bugfixes:
-+ - Fix a broken log message about delayed directory fetches that
-+ was caused by a misuse of strlcpy(). Fixes bug 11654; bugfix on
-+ 0.2.5.3-alpha.
---
-1.9.1
-
diff --git a/gitian/patches/bug11200-hang-0.2.5.patch b/gitian/patches/bug11200-hang-0.2.5.patch
deleted file mode 100644
index 76cd159..0000000
--- a/gitian/patches/bug11200-hang-0.2.5.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From fcac4b4467427e8f6ad948e8c8e6f34a0131e716 Mon Sep 17 00:00:00 2001
-From: Roger Dingledine <arma(a)torproject.org>
-Date: Tue, 5 Aug 2014 16:54:46 -0400
-Subject: [PATCH] Build circuits more readily when DisableNetwork goes to 0
-
-When Tor starts with DisabledNetwork set, it would correctly
-conclude that it shouldn't try making circuits, but it would
-mistakenly cache this conclusion and continue believing it even
-when DisableNetwork is set to 0. Fixes the bug introduced by the
-fix for bug 11200; bugfix on 0.2.5.4-alpha.
----
- changes/bug11200-caching | 7 +++++++
- src/or/nodelist.c | 21 ++++++++++++---------
- 2 files changed, 19 insertions(+), 9 deletions(-)
- create mode 100644 changes/bug11200-caching
-
-diff --git a/changes/bug11200-caching b/changes/bug11200-caching
-new file mode 100644
-index 0000000..e3fbaec
---- /dev/null
-+++ b/changes/bug11200-caching
-@@ -0,0 +1,7 @@
-+ o Major bugfixes:
-+ - When Tor starts with DisabledNetwork set, it would correctly
-+ conclude that it shouldn't try making circuits, but it would
-+ mistakenly cache this conclusion and continue believing it even
-+ when DisableNetwork is set to 0. Fixes the bug introduced by the
-+ fix for bug 11200; bugfix on 0.2.5.4-alpha.
-+
-diff --git a/src/or/nodelist.c b/src/or/nodelist.c
-index 8f87081..7b1f338 100644
---- a/src/or/nodelist.c
-+++ b/src/or/nodelist.c
-@@ -1275,10 +1275,21 @@ static char dir_info_status[256] = "";
- int
- router_have_minimum_dir_info(void)
- {
-+ static int logged_delay=0;
-+ const char *delay_fetches_msg = NULL;
-+ if (should_delay_dir_fetches(get_options(), &delay_fetches_msg)) {
-+ if (!logged_delay)
-+ log_notice(LD_DIR, "Delaying directory fetches: %s", delay_fetches_msg);
-+ logged_delay=1;
-+ strlcpy(dir_info_status, delay_fetches_msg, sizeof(dir_info_status));
-+ return 0;
-+ }
-+ logged_delay = 0; /* reset it if we get this far */
-+
- if (PREDICT_UNLIKELY(need_to_update_have_min_dir_info)) {
- update_router_have_minimum_dir_info();
-- need_to_update_have_min_dir_info = 0;
- }
-+
- return have_min_dir_info;
- }
-
-@@ -1498,7 +1509,6 @@ update_router_have_minimum_dir_info(void)
- const networkstatus_t *consensus =
- networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
- int using_md;
-- const char *delay_fetches_msg = NULL;
-
- if (!consensus) {
- if (!networkstatus_get_latest_consensus())
-@@ -1511,13 +1521,6 @@ update_router_have_minimum_dir_info(void)
- goto done;
- }
-
-- if (should_delay_dir_fetches(get_options(), &delay_fetches_msg)) {
-- log_notice(LD_DIR, "Delaying directory fetches: %s", delay_fetches_msg);
-- strlcpy(dir_info_status, delay_fetches_msg, sizeof(dir_info_status));
-- res = 0;
-- goto done;
-- }
--
- using_md = consensus->flavor == FLAV_MICRODESC;
-
- {
---
-1.9.1
-
diff --git a/gitian/patches/bug11200.patch b/gitian/patches/bug11200.patch
deleted file mode 100644
index 040309a..0000000
--- a/gitian/patches/bug11200.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 6770153d4ced726e54305ad38d14ea82df0d639e Mon Sep 17 00:00:00 2001
-From: Nick Mathewson <nickm(a)torproject.org>
-Date: Sat, 29 Mar 2014 21:49:32 -0700
-Subject: [PATCH] should_disable_dir_fetches() now returns 1 if
- DisableNetwork==1
-
-This change prevents LD_BUG warnings and bootstrap failure messages
-when we try to do directory fetches when starting with
-DisableNetwork == 1, a consensus present, but no descriptors (or
-insufficient descriptors) yet.
-
-Fixes bug 11200 and bug 10405. It's a bugfix on 0.2.3.9-alpha.
-Thanks to mcs for walking me through the repro instructions!
----
- src/or/networkstatus.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
-index bcadc52..9a1824b 100644
---- a/src/or/networkstatus.c
-+++ b/src/or/networkstatus.c
-@@ -1394,6 +1394,14 @@ should_delay_dir_fetches(const or_options_t *options, const char **msg_out)
- *msg_out = NULL;
- }
-
-+ if (options->DisableNetwork) {
-+ if (msg_out) {
-+ *msg_out = "DisableNetwork is set.";
-+ }
-+ log_info(LD_DIR, "Delaying dir fetches (DisableNetwork is set)");
-+ return 1;
-+ }
-+
- if (options->UseBridges) {
- if (!any_bridge_descriptors_known()) {
- if (msg_out) {
---
-1.8.1.2
-
diff --git a/gitian/patches/bug5018.patch b/gitian/patches/bug5018.patch
deleted file mode 100644
index b0ac8e6..0000000
--- a/gitian/patches/bug5018.patch
+++ /dev/null
@@ -1,225 +0,0 @@
-From 3394daa34842a397561e65002a33c13355df651d Mon Sep 17 00:00:00 2001
-From: George Kadianakis <desnacked(a)riseup.net>
-Date: Thu, 28 Feb 2013 18:58:36 +0200
-Subject: [PATCH 1/4] Only launch transport proxies that provide useful
- transports.
-
----
- changes/bug5018 | 3 +++
- src/or/config.c | 20 ++++++++++++++++----
- src/or/entrynodes.c | 23 +++++++++++++++++++++++
- src/or/entrynodes.h | 1 +
- 4 files changed, 43 insertions(+), 4 deletions(-)
- create mode 100644 changes/bug5018
-
-diff --git a/changes/bug5018 b/changes/bug5018
-new file mode 100644
-index 0000000..c5c12ef
---- /dev/null
-+++ b/changes/bug5018
-@@ -0,0 +1,3 @@
-+ o Minor features:
-+ - Don't launch pluggable transport proxies that contribute
-+ transports we don't need. Resolves ticket 5018.
-diff --git a/src/or/config.c b/src/or/config.c
-index ef02946..47510c5 100644
---- a/src/or/config.c
-+++ b/src/or/config.c
-@@ -4242,7 +4242,8 @@ parse_client_transport_line(const char *line, int validate_only)
- int is_managed=0;
- char **proxy_argv=NULL;
- char **tmp=NULL;
-- int proxy_argc,i;
-+ int proxy_argc, i;
-+ int is_useless_proxy=1;
-
- int line_length;
-
-@@ -4264,11 +4265,16 @@ parse_client_transport_line(const char *line, int validate_only)
- smartlist_split_string(transport_list, transports, ",",
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) {
-+ /* validate transport names */
- if (!string_is_C_identifier(transport_name)) {
- log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
- transport_name);
- goto err;
- }
-+
-+ /* see if we actually need the transports provided by this proxy */
-+ if (!validate_only && transport_is_needed(transport_name))
-+ is_useless_proxy = 0;
- } SMARTLIST_FOREACH_END(transport_name);
-
- /* field2 is either a SOCKS version or "exec" */
-@@ -4287,9 +4293,15 @@ parse_client_transport_line(const char *line, int validate_only)
- }
-
- if (is_managed) { /* managed */
-- if (!validate_only) { /* if we are not just validating, use the
-- rest of the line as the argv of the proxy
-- to be launched */
-+ if (!validate_only && is_useless_proxy) {
-+ log_warn(LD_GENERAL, "Pluggable transport proxy (%s) does not provide "
-+ "any needed transports and will not be launched.", line);
-+ }
-+
-+ /* If we are not just validating, use the rest of the line as the
-+ argv of the proxy to be launched. Also, make sure that we are
-+ only launching proxies that contribute useful transports. */
-+ if (!validate_only && !is_useless_proxy) {
- proxy_argc = line_length-2;
- tor_assert(proxy_argc > 0);
- proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1));
-diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
-index 2aa063c..4062cee 100644
---- a/src/or/entrynodes.c
-+++ b/src/or/entrynodes.c
-@@ -1773,6 +1773,29 @@ bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port,
- } SMARTLIST_FOREACH_END(bridge);
- }
-
-+/** Return True if we have a bridge that uses a transport with name
-+ * <b>transport_name</b>. */
-+int
-+transport_is_needed(const char *transport_name)
-+{
-+ int retval;
-+ smartlist_t *needed_transports = NULL;
-+
-+ if (!bridge_list)
-+ return 0;
-+
-+ needed_transports = smartlist_new();
-+
-+ SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
-+ if (bridge->transport_name)
-+ smartlist_add(needed_transports, bridge->transport_name);
-+ } SMARTLIST_FOREACH_END(bridge);
-+
-+ retval = smartlist_string_isin(needed_transports, transport_name);
-+ smartlist_free(needed_transports);
-+ return retval;
-+}
-+
- /** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b>
- * is set, it tells us the identity key too. If we already had the
- * bridge in our list, unmark it, and don't actually add anything new.
-diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
-index 52b8dc0..b02cd48 100644
---- a/src/or/entrynodes.h
-+++ b/src/or/entrynodes.h
-@@ -118,6 +118,7 @@ struct transport_t;
- int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
- const struct transport_t **transport);
-
-+int transport_is_needed(const char *transport_name);
- int validate_pluggable_transports_config(void);
-
- double pathbias_get_close_success_count(entry_guard_t *guard);
---
-1.8.1.2
-
-From 54f75531a9613ee7b964be93b0051bc75322e7e3 Mon Sep 17 00:00:00 2001
-From: David Fifield <david(a)bamsoftware.com>
-Date: Sat, 26 Oct 2013 14:34:48 -0700
-Subject: [PATCH 2/4] Simplify transport_is_needed.
-
-By Roger at
-https://trac.torproject.org/projects/tor/ticket/5018#comment:11.
----
- src/or/entrynodes.c | 14 ++++----------
- 1 file changed, 4 insertions(+), 10 deletions(-)
-
-diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
-index 4062cee..98a01c5 100644
---- a/src/or/entrynodes.c
-+++ b/src/or/entrynodes.c
-@@ -1778,22 +1778,16 @@ bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port,
- int
- transport_is_needed(const char *transport_name)
- {
-- int retval;
-- smartlist_t *needed_transports = NULL;
--
- if (!bridge_list)
- return 0;
-
-- needed_transports = smartlist_new();
--
- SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
-- if (bridge->transport_name)
-- smartlist_add(needed_transports, bridge->transport_name);
-+ if (bridge->transport_name &&
-+ !strcmp(bridge->transport_name, transport_name))
-+ return 1;
- } SMARTLIST_FOREACH_END(bridge);
-
-- retval = smartlist_string_isin(needed_transports, transport_name);
-- smartlist_free(needed_transports);
-- return retval;
-+ return 0;
- }
-
- /** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b>
---
-1.8.1.2
-
-From 936ff64974b00a898fa0e77e3fd6f9b2df57f448 Mon Sep 17 00:00:00 2001
-From: David Fifield <david(a)bamsoftware.com>
-Date: Sat, 26 Oct 2013 14:37:50 -0700
-Subject: [PATCH 3/4] Document that unneeded transports are ignored.
-
-Suggested by Roger in
-https://trac.torproject.org/projects/tor/ticket/5018#comment:11.
----
- src/or/config.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/or/config.c b/src/or/config.c
-index 47510c5..435d981 100644
---- a/src/or/config.c
-+++ b/src/or/config.c
-@@ -4220,7 +4220,8 @@ parse_bridge_line(const char *line, int validate_only)
- * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
- * isn't.
- *
-- * If <b>validate_only</b> is 0, and the line is well-formed:
-+ * If <b>validate_only</b> is 0, the line is well-formed, and the
-+ * transport is needed by some bridge:
- * - If it's an external proxy line, add the transport described in the line to
- * our internal transport list.
- * - If it's a managed proxy line, launch the managed proxy. */
---
-1.8.1.2
-
-From a4cf8514af1d2dbfd15857af83076577b7dcc4ee Mon Sep 17 00:00:00 2001
-From: George Kadianakis <desnacked(a)riseup.net>
-Date: Mon, 10 Mar 2014 22:05:31 +0000
-Subject: [PATCH 4/4] Tone down the log message for when we don't need a PT
- proxy.
-
-Conflicts:
- changes/bug5018
----
- src/or/config.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/or/config.c b/src/or/config.c
-index 435d981..914c3de 100644
---- a/src/or/config.c
-+++ b/src/or/config.c
-@@ -4295,8 +4295,8 @@ parse_client_transport_line(const char *line, int validate_only)
-
- if (is_managed) { /* managed */
- if (!validate_only && is_useless_proxy) {
-- log_warn(LD_GENERAL, "Pluggable transport proxy (%s) does not provide "
-- "any needed transports and will not be launched.", line);
-+ log_notice(LD_GENERAL, "Pluggable transport proxy (%s) does not provide "
-+ "any needed transports and will not be launched.", line);
- }
-
- /* If we are not just validating, use the rest of the line as the
---
-1.8.1.2
-
diff --git a/gitian/patches/bug8402.patch b/gitian/patches/bug8402.patch
deleted file mode 100644
index 2aa74c6..0000000
--- a/gitian/patches/bug8402.patch
+++ /dev/null
@@ -1,437 +0,0 @@
-From 88ddabbce1e15627f51b1bd6aef06f1b3515dd15 Mon Sep 17 00:00:00 2001
-From: Yawning Angel <yawning(a)schwanenlied.me>
-Date: Thu, 1 May 2014 03:57:29 +0000
-Subject: [PATCH 1/2] Allow ClientTransportPlugins to use proxies
-
-This change allows using Socks4Proxy, Socks5Proxy and HTTPSProxy with
-ClientTransportPlugins via the TOR_PT_PROXY extension to the
-pluggable transport specification.
-
-This fixes bug #8402.
-
-WARNING:
-
-This is a backport to tor-0.2.4.x of a unmerged patch. Differences
-at the time of writing from my real branch are:
- * Unit tests.
- * get_proxy_type() is removed in the backport, 0.2.5.x uses the
- routine elsewhere, so it is left intact (with modifications).
----
- src/or/config.c | 24 +++++++----
- src/or/connection.c | 55 ++++++++++---------------
- src/or/transports.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++--
- src/or/transports.h | 3 ++
- 4 files changed, 152 insertions(+), 44 deletions(-)
-
-diff --git a/src/or/config.c b/src/or/config.c
-index 09fdc0c..3fe5b73 100644
---- a/src/or/config.c
-+++ b/src/or/config.c
-@@ -490,7 +490,9 @@ static int options_transition_affects_descriptor(
- static int check_nickname_list(const char *lst, const char *name, char **msg);
-
- static int parse_bridge_line(const char *line, int validate_only);
--static int parse_client_transport_line(const char *line, int validate_only);
-+static int parse_client_transport_line(const or_options_t *options,
-+ const char *line,
-+ int validate_only);
-
- static int parse_server_transport_line(const char *line, int validate_only);
- static char *get_bindaddr_from_transport_listen_line(const char *line,
-@@ -1337,7 +1339,7 @@ options_act(const or_options_t *old_options)
- pt_prepare_proxy_list_for_config_read();
- if (options->ClientTransportPlugin) {
- for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
-- if (parse_client_transport_line(cl->value, 0)<0) {
-+ if (parse_client_transport_line(options, cl->value, 0)<0) {
- log_warn(LD_BUG,
- "Previously validated ClientTransportPlugin line "
- "could not be added!");
-@@ -2954,11 +2956,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
- }
- }
-
-- /* Check if more than one proxy type has been enabled. */
-+ /* Check if more than one exclusive proxy type has been enabled. */
- if (!!options->Socks4Proxy + !!options->Socks5Proxy +
-- !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1)
-+ !!options->HTTPSProxy > 1)
- REJECT("You have configured more than one proxy type. "
-- "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)");
-+ "(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
-
- /* Check if the proxies will give surprising behavior. */
- if (options->HTTPProxy && !(options->Socks4Proxy ||
-@@ -3073,7 +3075,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
- }
-
- for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
-- if (parse_client_transport_line(cl->value, 1)<0)
-+ if (parse_client_transport_line(options, cl->value, 1)<0)
- REJECT("Transport line did not parse. See logs for details.");
- }
-
-@@ -4229,7 +4231,8 @@ parse_bridge_line(const char *line, int validate_only)
- * our internal transport list.
- * - If it's a managed proxy line, launch the managed proxy. */
- static int
--parse_client_transport_line(const char *line, int validate_only)
-+parse_client_transport_line(const or_options_t *options, const char *line,
-+ int validate_only)
- {
- smartlist_t *items = NULL;
- int r;
-@@ -4308,6 +4311,13 @@ parse_client_transport_line(const char *line, int validate_only)
- pt_kickstart_client_proxy(transport_list, proxy_argv);
- }
- } else { /* external */
-+ /* ClientTransportPlugins connecting through a proxy is managed only. */
-+ if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
-+ log_warn(LD_CONFIG, "You have configured an external proxy with another "
-+ "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)");
-+ goto err;
-+ }
-+
- if (smartlist_len(transport_list) != 1) {
- log_warn(LD_CONFIG, "You can't have an external proxy with "
- "more than one transports.");
-diff --git a/src/or/connection.c b/src/or/connection.c
-index 4f74a1d..683cf46 100644
---- a/src/or/connection.c
-+++ b/src/or/connection.c
-@@ -81,7 +81,6 @@ static const char *connection_proxy_state_to_string(int state);
- static int connection_read_https_proxy_response(connection_t *conn);
- static void connection_send_socks5_connect(connection_t *conn);
- static const char *proxy_type_to_string(int proxy_type);
--static int get_proxy_type(void);
-
- /** The last addresses that our network interface seemed to have been
- * binding to. We use this as one way to detect when our IP changes.
-@@ -4390,6 +4389,27 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
- {
- const or_options_t *options = get_options();
-
-+ /* Client Transport Plugins can use another proxy, but that should be hidden
-+ * from the rest of tor (as the plugin is responsible for dealing with the
-+ * proxy), check it first, then check the rest of the proxy types to allow
-+ * the config to have unused ClientTransportPlugin entries.
-+ */
-+ if (options->ClientTransportPlugin) {
-+ const transport_t *transport = NULL;
-+ int r;
-+ r = find_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
-+ if (r<0)
-+ return -1;
-+ if (transport) { /* transport found */
-+ tor_addr_copy(addr, &transport->addr);
-+ *port = transport->port;
-+ *proxy_type = transport->socks_version;
-+ return 0;
-+ }
-+
-+ /* Unused ClientTransportPlugin. */
-+ }
-+
- if (options->HTTPSProxy) {
- tor_addr_copy(addr, &options->HTTPSProxyAddr);
- *port = options->HTTPSProxyPort;
-@@ -4405,43 +4425,12 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
- *port = options->Socks5ProxyPort;
- *proxy_type = PROXY_SOCKS5;
- return 0;
-- } else if (options->ClientTransportPlugin ||
-- options->Bridges) {
-- const transport_t *transport = NULL;
-- int r;
-- r = find_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
-- if (r<0)
-- return -1;
-- if (transport) { /* transport found */
-- tor_addr_copy(addr, &transport->addr);
-- *port = transport->port;
-- *proxy_type = transport->socks_version;
-- return 0;
-- }
- }
-
- *proxy_type = PROXY_NONE;
- return 0;
- }
-
--/** Returns the global proxy type used by tor. */
--static int
--get_proxy_type(void)
--{
-- const or_options_t *options = get_options();
--
-- if (options->HTTPSProxy)
-- return PROXY_CONNECT;
-- else if (options->Socks4Proxy)
-- return PROXY_SOCKS4;
-- else if (options->Socks5Proxy)
-- return PROXY_SOCKS5;
-- else if (options->ClientTransportPlugin)
-- return PROXY_PLUGGABLE;
-- else
-- return PROXY_NONE;
--}
--
- /** Log a failed connection to a proxy server.
- * <b>conn</b> is the connection we use the proxy server for. */
- void
-@@ -4457,7 +4446,7 @@ log_failed_proxy_connection(connection_t *conn)
- log_warn(LD_NET,
- "The connection to the %s proxy server at %s just failed. "
- "Make sure that the proxy server is up and running.",
-- proxy_type_to_string(get_proxy_type()),
-+ proxy_type_to_string(proxy_type),
- fmt_addrport(&proxy_addr, proxy_port));
- }
-
-diff --git a/src/or/transports.c b/src/or/transports.c
-index 3749d6b..cae1f31 100644
---- a/src/or/transports.c
-+++ b/src/or/transports.c
-@@ -103,6 +103,8 @@ static INLINE int proxy_configuration_finished(const managed_proxy_t *mp);
-
- static void managed_proxy_destroy(managed_proxy_t *mp,
- int also_terminate_process);
-+static char* get_pt_proxy_uri(void);
-+static void parse_proxy_error(const char *line);
-
- static void handle_finished_proxy(managed_proxy_t *mp);
- static int configure_proxy(managed_proxy_t *mp);
-@@ -123,6 +125,8 @@ static INLINE void free_execve_args(char **arg);
- #define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
- #define PROTO_CMETHODS_DONE "CMETHODS DONE"
- #define PROTO_SMETHODS_DONE "SMETHODS DONE"
-+#define PROTO_PROXY_DONE "PROXY DONE"
-+#define PROTO_PROXY_ERROR "PROXY-ERROR"
-
- /** The first and only supported - at the moment - configuration
- protocol version. */
-@@ -434,6 +438,17 @@ add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
- static int
- proxy_needs_restart(const managed_proxy_t *mp)
- {
-+ int ret = 1;
-+ char* proxy_uri;
-+
-+ /* If the PT proxy config has changed, then all existing pluggable transports
-+ * should be restarted.
-+ */
-+
-+ proxy_uri = get_pt_proxy_uri();
-+ if (strcmp_opt(proxy_uri, mp->proxy_uri) != 0)
-+ goto needs_restart;
-+
- /* mp->transport_to_launch is populated with the names of the
- transports that must be launched *after* the SIGHUP.
- mp->transports is populated with the transports that were
-@@ -454,10 +469,10 @@ proxy_needs_restart(const managed_proxy_t *mp)
-
- } SMARTLIST_FOREACH_END(t);
-
-- return 0;
--
-- needs_restart:
-- return 1;
-+ ret = 0;
-+needs_restart:
-+ tor_free(proxy_uri);
-+ return ret;
- }
-
- /** Managed proxy <b>mp</b> must be restarted. Do all the necessary
-@@ -488,6 +503,11 @@ proxy_prepare_for_restart(managed_proxy_t *mp)
- SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
- smartlist_clear(mp->transports);
-
-+ /* Reset the proxy's HTTPS/SOCKS proxy */
-+ tor_free(mp->proxy_uri);
-+ mp->proxy_uri = get_pt_proxy_uri();
-+ mp->proxy_supported = 0;
-+
- /* flag it as an infant proxy so that it gets launched on next tick */
- mp->conf_state = PT_PROTO_INFANT;
- unconfigured_proxies_n++;
-@@ -718,12 +738,52 @@ managed_proxy_destroy(managed_proxy_t *mp,
- /* free the argv */
- free_execve_args(mp->argv);
-
-+ /* free the outgoing proxy URI */
-+ tor_free(mp->proxy_uri);
-+
- tor_process_handle_destroy(mp->process_handle, also_terminate_process);
- mp->process_handle = NULL;
-
- tor_free(mp);
- }
-
-+/** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY. */
-+static char *
-+get_pt_proxy_uri(void)
-+{
-+ const or_options_t *options = get_options();
-+ char *uri = NULL;
-+
-+ if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
-+ char addr[TOR_ADDR_BUF_LEN+1];
-+
-+ if (options->Socks4Proxy) {
-+ tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
-+ tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
-+ } else if (options->Socks5Proxy) {
-+ tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
-+ if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
-+ tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
-+ } else {
-+ tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
-+ options->Socks5ProxyUsername,
-+ options->Socks5ProxyPassword,
-+ addr, options->Socks5ProxyPort);
-+ }
-+ } else if (options->HTTPSProxy) {
-+ tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
-+ if (!options->HTTPSProxyAuthenticator) {
-+ tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
-+ } else {
-+ tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
-+ addr, options->HTTPSProxyPort);
-+ }
-+ }
-+ }
-+
-+ return uri;
-+}
-+
- /** Handle a configured or broken managed proxy <b>mp</b>. */
- static void
- handle_finished_proxy(managed_proxy_t *mp)
-@@ -736,6 +796,12 @@ handle_finished_proxy(managed_proxy_t *mp)
- managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
- break;
- case PT_PROTO_CONFIGURED: /* if configured correctly: */
-+ if (mp->proxy_uri && !mp->proxy_supported) {
-+ log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
-+ "specified outgoing proxy.", mp->argv[0]);
-+ managed_proxy_destroy(mp, 1); /* annihilate it. */
-+ break;
-+ }
- register_proxy(mp); /* register its transports */
- mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
- break;
-@@ -854,6 +920,22 @@ handle_proxy_line(const char *line, managed_proxy_t *mp)
- goto err;
-
- return;
-+ } else if (!strcmpstart(line, PROTO_PROXY_DONE)) {
-+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
-+ goto err;
-+
-+ if (mp->proxy_uri) {
-+ mp->proxy_supported = 1;
-+ return;
-+ }
-+
-+ /* No proxy was configured, this should log */
-+ } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
-+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
-+ goto err;
-+
-+ parse_proxy_error(line);
-+ goto err;
- } else if (!strcmpstart(line, SPAWN_ERROR_MESSAGE)) {
- /* managed proxy launch failed: parse error message to learn why. */
- int retval, child_state, saved_errno;
-@@ -1105,6 +1187,21 @@ parse_cmethod_line(const char *line, managed_proxy_t *mp)
- return r;
- }
-
-+/** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */
-+static void
-+parse_proxy_error(const char *line)
-+{
-+ /* (Length of the protocol string) plus (a space) and (the first char of
-+ the error message) */
-+ if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
-+ log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
-+ "message.", PROTO_PROXY_ERROR);
-+
-+ log_warn(LD_CONFIG, "Managed proxy failed to configure the "
-+ "pluggable transport's outgoing proxy. (%s)",
-+ line+strlen(PROTO_PROXY_ERROR)+1);
-+}
-+
- /** Return the string that tor should place in TOR_PT_SERVER_BINDADDR
- * while configuring the server managed proxy in <b>mp</b>. The
- * string is stored in the heap, and it's the the responsibility of
-@@ -1193,6 +1290,14 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
- * variable in Tor's environment and crash PTs that try to parse
- * it even when not run in server mode.) */
- smartlist_add(envs, tor_strdup("TOR_PT_EXTENDED_SERVER_PORT="));
-+ } else {
-+ /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
-+ * TOR_PT_PROXY line.
-+ */
-+
-+ if (mp->proxy_uri) {
-+ smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
-+ }
- }
-
- SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
-@@ -1225,6 +1330,7 @@ managed_proxy_create(const smartlist_t *transport_list,
- mp->is_server = is_server;
- mp->argv = proxy_argv;
- mp->transports = smartlist_new();
-+ mp->proxy_uri = get_pt_proxy_uri();
-
- mp->transports_to_launch = smartlist_new();
- SMARTLIST_FOREACH(transport_list, const char *, transport,
-diff --git a/src/or/transports.h b/src/or/transports.h
-index 6ee82f4..f13de5d 100644
---- a/src/or/transports.h
-+++ b/src/or/transports.h
-@@ -74,6 +74,9 @@ typedef struct {
- char **argv; /* the cli arguments of this proxy */
- int conf_protocol; /* the configuration protocol version used */
-
-+ char *proxy_uri; /* the outgoing proxy in TOR_PT_PROXY URI format */
-+ int proxy_supported : 1; /* the proxy claims to honor TOR_PT_PROXY */
-+
- int is_server; /* is it a server proxy? */
-
- /* A pointer to the process handle of this managed proxy. */
---
-1.8.1.2
-
-From 34004139ee9380c5c468d28037520d02681dd7cf Mon Sep 17 00:00:00 2001
-From: Yawning Angel <yawning(a)schwanenlied.me>
-Date: Thu, 1 May 2014 19:01:34 +0000
-Subject: [PATCH 2/2] Improve the log message when a transport doesn't support
- proxies.
-
-Per feedback, explicltly note that the transport will be killed when it
-does not acknowledge the configured outgoing proxy.
----
- src/or/transports.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/or/transports.c b/src/or/transports.c
-index cae1f31..917d12a 100644
---- a/src/or/transports.c
-+++ b/src/or/transports.c
-@@ -798,7 +798,8 @@ handle_finished_proxy(managed_proxy_t *mp)
- case PT_PROTO_CONFIGURED: /* if configured correctly: */
- if (mp->proxy_uri && !mp->proxy_supported) {
- log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
-- "specified outgoing proxy.", mp->argv[0]);
-+ "specified outgoing proxy and will be terminated.",
-+ mp->argv[0]);
- managed_proxy_destroy(mp, 1); /* annihilate it. */
- break;
- }
---
-1.8.1.2
-
diff --git a/gitian/patches/bug9665.patch b/gitian/patches/bug9665.patch
deleted file mode 100644
index aeab37b..0000000
--- a/gitian/patches/bug9665.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From 08ae53e400ff6fa2d8147aad440c38173c106cae Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?F=C3=A1bio=20J=2E=20Bertinatto?= <fabiojrb(a)gmail.com>
-Date: Tue, 5 Nov 2013 00:50:16 -0200
-Subject: [PATCH 1/3] Fix bug9665
-
----
- src/or/connection_or.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/src/or/connection_or.c b/src/or/connection_or.c
-index 04ad2cc..ba3ac00 100644
---- a/src/or/connection_or.c
-+++ b/src/or/connection_or.c
-@@ -1195,6 +1195,11 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
- "your pluggable transport proxy stopped running.",
- fmt_addrport(&TO_CONN(conn)->addr, TO_CONN(conn)->port),
- transport_name, transport_name);
-+
-+ control_event_bootstrap_problem(
-+ "Can't connect to bridge",
-+ END_OR_CONN_REASON_NO_ROUTE);
-+
- } else {
- log_warn(LD_GENERAL, "Tried to connect to '%s' through a proxy, but "
- "the proxy address could not be found.",
---
-1.8.1.2
-
-From 754a50592c412d95d2eb48038784d0ef725a7dc2 Mon Sep 17 00:00:00 2001
-From: Nick Mathewson <nickm(a)torproject.org>
-Date: Mon, 7 Apr 2014 13:41:07 -0400
-Subject: [PATCH 2/3] Forward-port bug9665 fix to work with our fix for 11069
-
----
- src/or/connection_or.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/or/connection_or.c b/src/or/connection_or.c
-index ba3ac00..01ff4dc 100644
---- a/src/or/connection_or.c
-+++ b/src/or/connection_or.c
-@@ -1198,7 +1198,8 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
-
- control_event_bootstrap_problem(
- "Can't connect to bridge",
-- END_OR_CONN_REASON_NO_ROUTE);
-+ END_OR_CONN_REASON_NO_ROUTE,
-+ conn);
-
- } else {
- log_warn(LD_GENERAL, "Tried to connect to '%s' through a proxy, but "
---
-1.8.1.2
-
-From 90341b4852bf88f1fdf9fd150fa2f5c47f88b2cb Mon Sep 17 00:00:00 2001
-From: Nick Mathewson <nickm(a)torproject.org>
-Date: Mon, 7 Apr 2014 13:44:22 -0400
-Subject: [PATCH 3/3] For missing transport, say "PT_MISSING" not "NO_ROUTE"
-
----
- src/or/connection_or.c | 2 +-
- src/or/or.h | 3 ++-
- src/or/reasons.c | 2 ++
- 3 files changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/src/or/connection_or.c b/src/or/connection_or.c
-index 01ff4dc..6572a91 100644
---- a/src/or/connection_or.c
-+++ b/src/or/connection_or.c
-@@ -1198,7 +1198,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
-
- control_event_bootstrap_problem(
- "Can't connect to bridge",
-- END_OR_CONN_REASON_NO_ROUTE,
-+ END_OR_CONN_REASON_PT_MISSING,
- conn);
-
- } else {
-diff --git a/src/or/or.h b/src/or/or.h
-index 38ab176..1b35c1f 100644
---- a/src/or/or.h
-+++ b/src/or/or.h
-@@ -604,7 +604,8 @@ typedef enum {
- #define END_OR_CONN_REASON_NO_ROUTE 6 /* no route to host/net */
- #define END_OR_CONN_REASON_IO_ERROR 7 /* read/write error */
- #define END_OR_CONN_REASON_RESOURCE_LIMIT 8 /* sockets, buffers, etc */
--#define END_OR_CONN_REASON_MISC 9
-+#define END_OR_CONN_REASON_PT_MISSING 9 /* PT failed or not available */
-+#define END_OR_CONN_REASON_MISC 10
-
- /* Reasons why we (or a remote OR) might close a stream. See tor-spec.txt for
- * documentation of these. The values must match. */
-diff --git a/src/or/reasons.c b/src/or/reasons.c
-index 0674474..750e89b 100644
---- a/src/or/reasons.c
-+++ b/src/or/reasons.c
-@@ -231,6 +231,8 @@ orconn_end_reason_to_control_string(int r)
- return "RESOURCELIMIT";
- case END_OR_CONN_REASON_MISC:
- return "MISC";
-+ case END_OR_CONN_REASON_PT_MISSING:
-+ return "PT_MISSING";
- case 0:
- return "";
- default:
---
-1.8.1.2
-
1
0
[tor-browser-bundle/master] Bug 8405: Add Tor patch for domain isolation.
by mikeperry@torproject.org 29 Oct '14
by mikeperry@torproject.org 29 Oct '14
29 Oct '14
commit 1eeb621e9a20afc065518f34e6a6c87c35109fa3
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Tue Oct 28 17:50:47 2014 -0700
Bug 8405: Add Tor patch for domain isolation.
Also clean up our patch application.
---
gitian/descriptors/linux/gitian-tor.yml | 20 ++-----
gitian/descriptors/mac/gitian-tor.yml | 20 ++-----
gitian/descriptors/windows/gitian-tor.yml | 20 ++-----
gitian/patches/bug8405.patch | 84 +++++++++++++++++++++++++++++
4 files changed, 99 insertions(+), 45 deletions(-)
diff --git a/gitian/descriptors/linux/gitian-tor.yml b/gitian/descriptors/linux/gitian-tor.yml
index e678203..68a5bae 100644
--- a/gitian/descriptors/linux/gitian-tor.yml
+++ b/gitian/descriptors/linux/gitian-tor.yml
@@ -27,6 +27,7 @@ files:
- "bug9665.patch"
- "bug8402.patch"
- "bug8402-master.patch"
+- "bug8405.patch"
- "dzip.sh"
- "openssl-linux32-utils.zip"
- "openssl-linux64-utils.zip"
@@ -82,23 +83,12 @@ script: |
export GIT_COMMITTER_NAME="nobody"
export GIT_COMMITTER_EMAIL="nobody@localhost"
export GIT_COMMITTER_DATE="$REFERENCE_DATETIME"
- if [ ${TOR_TAG::9} == "tor-0.2.4" ];
+ if [ ${TOR_TAG::9} == "tor-0.2.5" ];
then
- git am ~/build/bug10297.patch
- fi
- if [ $BUILD_PT_BUNDLES ]; then
- if [ ${TOR_TAG::9} == "tor-0.2.4" ];
- then
- git am ~/build/bug5018.patch
- git am ~/build/bug11069.patch
- git am ~/build/bug11156.patch
- git am ~/build/bug9665.patch
- git am ~/build/bug11200.patch
- git am ~/build/bug8402.patch
- elif [ ${TOR_TAG::9} == "tor-0.2.5" ];
- then
+ git am ~/build/bug8405.patch
git am ~/build/bug8402-master.patch
- fi
+ else # 0.2.6 and master
+ git am ~/build/bug8405.patch
fi
mkdir -p $OUTDIR/src
#git archive HEAD | tar -x -C $OUTDIR/src
diff --git a/gitian/descriptors/mac/gitian-tor.yml b/gitian/descriptors/mac/gitian-tor.yml
index 6022c0b..36b5b0f 100644
--- a/gitian/descriptors/mac/gitian-tor.yml
+++ b/gitian/descriptors/mac/gitian-tor.yml
@@ -23,6 +23,7 @@ files:
- "bug9665.patch"
- "bug8402.patch"
- "bug8402-master.patch"
+- "bug8405.patch"
- "apple-uni-sdk-10.6_20110407-0.flosoft1_i386.deb"
- "multiarch-darwin11-cctools127.2-gcc42-5666.3-llvmgcc42-2336.1-Linux-120724.tar.xz"
- "dzip.sh"
@@ -60,23 +61,12 @@ script: |
export GIT_COMMITTER_NAME="nobody"
export GIT_COMMITTER_EMAIL="nobody@localhost"
export GIT_COMMITTER_DATE="$REFERENCE_DATETIME"
- if [ ${TOR_TAG::9} == "tor-0.2.4" ];
+ if [ ${TOR_TAG::9} == "tor-0.2.5" ];
then
- git am ~/build/bug10297.patch
- fi
- if [ $BUILD_PT_BUNDLES ]; then
- if [ ${TOR_TAG::9} == "tor-0.2.4" ];
- then
- git am ~/build/bug5018.patch
- git am ~/build/bug11069.patch
- git am ~/build/bug11156.patch
- git am ~/build/bug9665.patch
- git am ~/build/bug11200.patch
- git am ~/build/bug8402.patch
- elif [ ${TOR_TAG::9} == "tor-0.2.5" ];
- then
+ git am ~/build/bug8405.patch
git am ~/build/bug8402-master.patch
- fi
+ else # 0.2.6 and master
+ git am ~/build/bug8405.patch
fi
mkdir -p $OUTDIR/src
#git archive HEAD | tar -x -C $OUTDIR/src
diff --git a/gitian/descriptors/windows/gitian-tor.yml b/gitian/descriptors/windows/gitian-tor.yml
index 0ac603c..6be93b5 100644
--- a/gitian/descriptors/windows/gitian-tor.yml
+++ b/gitian/descriptors/windows/gitian-tor.yml
@@ -23,6 +23,7 @@ files:
- "bug9665.patch"
- "bug8402.patch"
- "bug8402-master.patch"
+- "bug8405.patch"
- "binutils.tar.bz2"
- "dzip.sh"
- "mingw-w64-win32-utils.zip"
@@ -60,23 +61,12 @@ script: |
export GIT_COMMITTER_NAME="nobody"
export GIT_COMMITTER_EMAIL="nobody@localhost"
export GIT_COMMITTER_DATE="$REFERENCE_DATETIME"
- if [ ${TOR_TAG::9} == "tor-0.2.4" ];
+ if [ ${TOR_TAG::9} == "tor-0.2.5" ];
then
- git am ~/build/bug10297.patch
- fi
- if [ $BUILD_PT_BUNDLES ]; then
- if [ ${TOR_TAG::9} == "tor-0.2.4" ];
- then
- git am ~/build/bug5018.patch
- git am ~/build/bug11069.patch
- git am ~/build/bug11156.patch
- git am ~/build/bug9665.patch
- git am ~/build/bug11200.patch
- git am ~/build/bug8402.patch
- elif [ ${TOR_TAG::9} == "tor-0.2.5" ];
- then
+ git am ~/build/bug8405.patch
git am ~/build/bug8402-master.patch
- fi
+ else # 0.2.6 and master
+ git am ~/build/bug8405.patch
fi
mkdir -p $OUTDIR/src
#git archive HEAD | tar -x -C $OUTDIR/src
diff --git a/gitian/patches/bug8405.patch b/gitian/patches/bug8405.patch
new file mode 100644
index 0000000..3c40632
--- /dev/null
+++ b/gitian/patches/bug8405.patch
@@ -0,0 +1,84 @@
+From a298c77f7eba232154ff08ca1119b05ccd9eee9e Mon Sep 17 00:00:00 2001
+From: Arthur Edelstein <arthuredelstein(a)gmail.com>
+Date: Tue, 15 Jul 2014 21:27:59 -0700
+Subject: [PATCH] Bug #8405: Report SOCKS username/password in CIRC status
+ events
+
+Introduces two new circuit status name-value parameters: SOCKS_USERNAME
+and SOCKS_PASSWORD. Values are enclosing in quotes and unusual characters
+are escaped.
+
+Example:
+
+ 650 CIRC 5 EXTENDED [...] SOCKS_USERNAME="my_username" SOCKS_PASSWORD="my_password"
+---
+ src/common/util.c | 14 ++++++++++++++
+ src/common/util.h | 1 +
+ src/or/control.c | 14 ++++++++++++++
+ 3 files changed, 29 insertions(+)
+
+diff --git a/src/common/util.c b/src/common/util.c
+index 8589344..64cee56 100644
+--- a/src/common/util.c
++++ b/src/common/util.c
+@@ -1222,6 +1222,20 @@ esc_for_log(const char *s)
+ return result;
+ }
+
++/** Similar to esc_for_log. Allocate and return a new string representing
++ * the first n characters in <b>chars</b>, surround by quotes and using
++ * standard C escapes. If a NUL character is encountered in <b>chars</b>,
++ * the resulting string will be terminated there.
++ */
++char *
++esc_for_log_len(const char *chars, size_t n)
++{
++ char *string = tor_strndup(chars, n);
++ char *string_escaped = esc_for_log(string);
++ tor_free(string);
++ return string_escaped;
++}
++
+ /** Allocate and return a new string representing the contents of <b>s</b>,
+ * surrounded by quotes and using standard C escapes.
+ *
+diff --git a/src/common/util.h b/src/common/util.h
+index 97367a9..50c5a3d 100644
+--- a/src/common/util.h
++++ b/src/common/util.h
+@@ -229,6 +229,7 @@ int tor_mem_is_zero(const char *mem, size_t len);
+ int tor_digest_is_zero(const char *digest);
+ int tor_digest256_is_zero(const char *digest);
+ char *esc_for_log(const char *string) ATTR_MALLOC;
++char *esc_for_log_len(const char *chars, size_t n) ATTR_MALLOC;
+ const char *escaped(const char *string);
+
+ char *tor_escape_str_for_pt_args(const char *string,
+diff --git a/src/or/control.c b/src/or/control.c
+index 9285fc5..aa46df6 100644
+--- a/src/or/control.c
++++ b/src/or/control.c
+@@ -1862,6 +1862,20 @@ circuit_describe_status_for_controller(origin_circuit_t *circ)
+ smartlist_add_asprintf(descparts, "TIME_CREATED=%s", tbuf);
+ }
+
++ // Show username and/or password if available.
++ if (circ->socks_username_len > 0) {
++ char* socks_username_escaped = esc_for_log_len(circ->socks_username,
++ (size_t) circ->socks_username_len);
++ smartlist_add_asprintf(descparts, "SOCKS_USERNAME=%s", socks_username_escaped);
++ tor_free(socks_username_escaped);
++ }
++ if (circ->socks_password_len > 0) {
++ char* socks_password_escaped = esc_for_log_len(circ->socks_password,
++ (size_t) circ->socks_password_len);
++ smartlist_add_asprintf(descparts, "SOCKS_PASSWORD=%s", socks_password_escaped);
++ tor_free(socks_password_escaped);
++ }
++
+ rv = smartlist_join_strings(descparts, " ", 0, NULL);
+
+ SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
+--
+1.8.3.4 (Apple Git-47)
+
1
0
[tor-browser-bundle/master] Switch nightlies and alpha to new Tor Browser branch.
by mikeperry@torproject.org 28 Oct '14
by mikeperry@torproject.org 28 Oct '14
28 Oct '14
commit 42d1b7373a8dbb9f6359c1c1a3589af392878d7b
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Tue Oct 28 16:15:39 2014 -0700
Switch nightlies and alpha to new Tor Browser branch.
---
gitian/versions.alpha | 2 +-
gitian/versions.nightly | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/gitian/versions.alpha b/gitian/versions.alpha
index 0fb2bd0..6c49137 100755
--- a/gitian/versions.alpha
+++ b/gitian/versions.alpha
@@ -8,7 +8,7 @@ FIREFOX_VERSION=31.2.0esr
TORBROWSER_UPDATE_CHANNEL=alpha
-TORBROWSER_TAG=tor-browser-${FIREFOX_VERSION}-4.x-1-build3
+TORBROWSER_TAG=tor-browser-${FIREFOX_VERSION}-4.5-1-build1
TOR_TAG=tor-0.2.5.10
TORLAUNCHER_TAG=0.2.7.0.1
TORBUTTON_TAG=1.7.0.1
diff --git a/gitian/versions.nightly b/gitian/versions.nightly
index dc545ae..e6ea2a1 100755
--- a/gitian/versions.nightly
+++ b/gitian/versions.nightly
@@ -8,7 +8,7 @@ FIREFOX_VERSION=31.2.0esr
TORBROWSER_UPDATE_CHANNEL=default
-TORBROWSER_TAG=tor-browser-${FIREFOX_VERSION}-4.x-1
+TORBROWSER_TAG=tor-browser-${FIREFOX_VERSION}-4.5-1
TOR_TAG=master
TORLAUNCHER_TAG=master
TORBUTTON_TAG=master
1
0
[tor-browser-bundle/master] Bug 12903: Integrate obfs4proxy into Tor Browser.
by mikeperry@torproject.org 28 Oct '14
by mikeperry@torproject.org 28 Oct '14
28 Oct '14
commit 0a916fb562dcc744e4f3ce7b491669bcfd41b64c
Merge: 3fd3351 bb6389f
Author: Georg Koppen <gk(a)torproject.org>
Date: Mon Oct 13 15:27:00 2014 +0000
Bug 12903: Integrate obfs4proxy into Tor Browser.
We start shipping obfs4proxy in Tor Browser nightlies and the alpha
series.
.../Docs/Licenses/PluggableTransports/LICENSE | 77 +++++++++++++++++---
Bundle-Data/PTConfigs/bridge_prefs.js | 4 +
.../PTConfigs/linux/torrc-defaults-appendix | 6 +-
Bundle-Data/PTConfigs/mac/torrc-defaults-appendix | 5 +-
.../PTConfigs/windows/torrc-defaults-appendix | 5 +-
.../linux/gitian-pluggable-transports.yml | 54 ++++++++++++++
.../mac/gitian-pluggable-transports.yml | 54 ++++++++++++++
.../windows/gitian-pluggable-transports.yml | 54 ++++++++++++++
gitian/fetch-inputs.sh | 17 ++++-
gitian/gpg/obfs4proxy.gpg | Bin 0 -> 34128 bytes
gitian/mkbundle-linux.sh | 3 +-
gitian/mkbundle-mac.sh | 3 +-
gitian/mkbundle-windows.sh | 3 +-
gitian/verify-tags.sh | 5 +-
gitian/versions.alpha | 9 +++
gitian/versions.nightly | 9 +++
16 files changed, 291 insertions(+), 17 deletions(-)
diff --cc gitian/versions.nightly
index 9dc6f3f,3867629..5bd9d63
--- a/gitian/versions.nightly
+++ b/gitian/versions.nightly
@@@ -95,7 -100,8 +100,9 @@@ PY2EXE_HASH=610a8800de3d973ed5ed4ac505a
SETUPTOOLS_HASH=75d288687066ed124311d6ca5f40ffa92a0e81adcd7fff318c6e84082713cf39
PARSLEY_HASH=50d30cee70770fd44db7cea421cb2fb75af247c3a1cd54885c06b30a7c85dd23
GO_HASH=1bb6fde89cfe8b9756a875af55d994cce0994861227b5dc0f268c143d91cd5ff
+GCC_HASH=d334781a124ada6f38e63b545e2a3b8c2183049515a1abab6d513f109f1d717e
+ GOCRYPTO_HASH=a8e301714f5724999321f0397b867a5670a5e5c4f808ba157bdd93ee0d028827
+ GONET_HASH=1812fec55256e1a6fe546111cc658520b80972f38826c94ec11ef24315d32353
## Non-git package URLs
OPENSSL_URL=https://www.openssl.org/source/${OPENSSL_PACKAGE}
1
0
[tor-browser-bundle/master] Merge remote-tracking branch 'gk/bug_12903_squashed_v3'
by mikeperry@torproject.org 28 Oct '14
by mikeperry@torproject.org 28 Oct '14
28 Oct '14
commit 104bd981bfb47563d3eb8c28069a1d87deea03ed
Merge: 875f231 0a916fb
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Tue Oct 28 15:40:50 2014 -0700
Merge remote-tracking branch 'gk/bug_12903_squashed_v3'
.../Docs/Licenses/PluggableTransports/LICENSE | 77 +++++++++++++++++---
Bundle-Data/PTConfigs/bridge_prefs.js | 4 +
.../PTConfigs/linux/torrc-defaults-appendix | 6 +-
Bundle-Data/PTConfigs/mac/torrc-defaults-appendix | 5 +-
.../PTConfigs/windows/torrc-defaults-appendix | 5 +-
.../linux/gitian-pluggable-transports.yml | 54 ++++++++++++++
.../mac/gitian-pluggable-transports.yml | 54 ++++++++++++++
.../windows/gitian-pluggable-transports.yml | 54 ++++++++++++++
gitian/fetch-inputs.sh | 17 ++++-
gitian/gpg/obfs4proxy.gpg | Bin 0 -> 34128 bytes
gitian/mkbundle-linux.sh | 3 +-
gitian/mkbundle-mac.sh | 3 +-
gitian/mkbundle-windows.sh | 3 +-
gitian/verify-tags.sh | 5 +-
gitian/versions.alpha | 9 +++
gitian/versions.nightly | 9 +++
16 files changed, 291 insertions(+), 17 deletions(-)
1
0
[tor-browser-bundle/master] Update versions file for 4.5-alpha.
by mikeperry@torproject.org 28 Oct '14
by mikeperry@torproject.org 28 Oct '14
28 Oct '14
commit 329adc09efb6e7f7bcf36297313ddeaad979287f
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Tue Oct 28 15:51:00 2014 -0700
Update versions file for 4.5-alpha.
---
gitian/versions.alpha | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/gitian/versions.alpha b/gitian/versions.alpha
index 0912b5d..0fb2bd0 100755
--- a/gitian/versions.alpha
+++ b/gitian/versions.alpha
@@ -1,35 +1,32 @@
-TORBROWSER_VERSION=4.0-alpha-3
+TORBROWSER_VERSION=4.5-alpha-1
BUNDLE_LOCALES="ar de es-ES fa fr it ko nl pl pt-PT ru tr vi zh-CN"
BUILD_PT_BUNDLES=1
VERIFY_TAGS=1
-FIREFOX_VERSION=24.8.1esr
+FIREFOX_VERSION=31.2.0esr
TORBROWSER_UPDATE_CHANNEL=alpha
-TORBROWSER_TAG=tor-browser-${FIREFOX_VERSION}-4.x-1-build1
-TOR_TAG=tor-0.2.5.8-rc
-TORLAUNCHER_TAG=25bc6349f5f1e43c7d383883e6d6822b8edb41bc # 0.2.7.0
-TORBUTTON_TAG=1.6.12.3
+TORBROWSER_TAG=tor-browser-${FIREFOX_VERSION}-4.x-1-build3
+TOR_TAG=tor-0.2.5.10
+TORLAUNCHER_TAG=0.2.7.0.1
+TORBUTTON_TAG=1.7.0.1
HTTPSE_TAG=3.5.3 # XXX: HTTPSE_VER is used instead, pending #11630
NSIS_TAG=v0.2
ZLIB_TAG=v1.2.8
LIBEVENT_TAG=release-2.0.21-stable
-MINGW_TAG=9418eaa1854320b57f40e29ec5bbc4f5717ecd58 # tag v3.1.0
+MINGW_TAG=469ed5d227202b373409c8a3b4c1358be39b9983 # XXX: ???
PYPTLIB_TAG=pyptlib-0.0.6
OBFSPROXY_TAG=obfsproxy-0.2.12
FLASHPROXY_TAG=1.6
-LIBFTE_TAG=58734a5aec563600fa8d82fb48ea9d6b8e26556c # tag 0.1.0
+LIBFTE_TAG=85ef8ae58dbf0d02ea26b627e343784b5574c428 # sketch master with fix
FTEPROXY_TAG=597f8378f6f4f3de570b8e1064c2e4cb8d67fbd0 # tag 0.2.19
LIBDMG_TAG=dfd5e5cc3dc1191e37d3c3a6118975afdd1d7014
TXSOCKSX_TAG=216eb0894a1755872f4789f9458aa6cf543b8433 # unsigned habnabit/1.13.0.2
GOPTLIB_TAG=0.2
MEEK_TAG=0.11
FAKETIME_TAG=70aa6b394d9341522dffe8a5a5cf5929e82cc6b9 # unsigned v0.9.6
-GOED25519_TAG=c4161f4c7483313562781c61b9a20aba73daf9de
-GOSIPHASH_TAG=42ba037e748c9062a75e0924705c43b893edefcd
-OBFS4_TAG=obfs4proxy-0.0.3
GITIAN_TAG=tor-browser-builder-3.x-7
@@ -38,7 +35,7 @@ GMP_VER=5.1.3
FIREFOX_LANG_VER=$FIREFOX_VERSION
FIREFOX_LANG_BUILD=build1
BINUTILS_VER=2.24
-GCC_VER=4.8.3
+GCC_VER=4.9.1
PYTHON_VER=2.7.5
PYCRYPTO_VER=2.6.1
ARGPARSE_VER=1.2.1
@@ -56,7 +53,7 @@ GO_VER=1.3.3
## File names for the source packages
OPENSSL_PACKAGE=openssl-${OPENSSL_VER}.tar.gz
GMP_PACKAGE=gmp-${GMP_VER}.tar.bz2
-NOSCRIPT_PACKAGE=noscript_security_suite-2.6.8.42-fx+fn+sm.xpi
+NOSCRIPT_PACKAGE=noscript_security_suite-2.6.9.3-sm+fn+fx.xpi
HTTPSE_PACKAGE=https-everywhere-${HTTPSE_VER}.xpi
TOOLCHAIN4_PACKAGE=x86_64-apple-darwin10.tar.xz
TOOLCHAIN4_OLD_PACKAGE=multiarch-darwin11-cctools127.2-gcc42-5666.3-llvmgcc42-2336.1-Linux-120724.tar.xz
@@ -86,7 +83,7 @@ GMP_HASH=752079520b4690531171d0f4532e40f08600215feefede70b24fabdc6f1ab160
OSXSDK_HASH=6602d8d5ddb371fbc02e2a5967d9bd0cd7358d46f9417753c8234b923f2ea6fc
TOOLCHAIN4_HASH=7b71bfe02820409b994c5c33a7eab81a81c72550f5da85ff7af70da3da244645
TOOLCHAIN4_OLD_HASH=65c1b2d302358a6b95a26c6828a66908a199276193bb0b268f2dcc1a997731e9
-NOSCRIPT_HASH=b474156fd6b9957b38054a34c8acb581204f08733cce898ed581c67d425dda33
+NOSCRIPT_HASH=d399d724953fe032ccca758e577c2136b8fd6c377cea0e3f42ed999b796d290a
HTTPSE_HASH=6feb4982d13f89656b61435b6b49e1996c61bc79e52d046d02312879376028e3
MSVCR100_HASH=1221a09484964a6f38af5e34ee292b9afefccb3dc6e55435fd3aaf7c235d9067
PYCRYPTO_HASH=f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c
@@ -99,6 +96,7 @@ PY2EXE_HASH=610a8800de3d973ed5ed4ac505ab42ad058add18a68609ac09e6cf3598ef056c
SETUPTOOLS_HASH=75d288687066ed124311d6ca5f40ffa92a0e81adcd7fff318c6e84082713cf39
PARSLEY_HASH=50d30cee70770fd44db7cea421cb2fb75af247c3a1cd54885c06b30a7c85dd23
GO_HASH=1bb6fde89cfe8b9756a875af55d994cce0994861227b5dc0f268c143d91cd5ff
+GCC_HASH=d334781a124ada6f38e63b545e2a3b8c2183049515a1abab6d513f109f1d717e
GOCRYPTO_HASH=a8e301714f5724999321f0397b867a5670a5e5c4f808ba157bdd93ee0d028827
GONET_HASH=1812fec55256e1a6fe546111cc658520b80972f38826c94ec11ef24315d32353
1
0
[tor-browser-bundle/master] Bug 12903: Integrate obfs4proxy into Tor Browser.
by mikeperry@torproject.org 28 Oct '14
by mikeperry@torproject.org 28 Oct '14
28 Oct '14
commit bb6389fbe7aa9539c4dce2aba0659e61ae8a376a
Author: Georg Koppen <gk(a)torproject.org>
Date: Mon Oct 13 11:42:46 2014 +0000
Bug 12903: Integrate obfs4proxy into Tor Browser.
We start shipping obfs4proxy in Tor Browser nightlies and the alpha
series.
---
.../Docs/Licenses/PluggableTransports/LICENSE | 77 +++++++++++++++++---
Bundle-Data/PTConfigs/bridge_prefs.js | 4 +
.../PTConfigs/linux/torrc-defaults-appendix | 6 +-
Bundle-Data/PTConfigs/mac/torrc-defaults-appendix | 5 +-
.../PTConfigs/windows/torrc-defaults-appendix | 5 +-
.../linux/gitian-pluggable-transports.yml | 54 ++++++++++++++
.../mac/gitian-pluggable-transports.yml | 54 ++++++++++++++
.../windows/gitian-pluggable-transports.yml | 54 ++++++++++++++
gitian/fetch-inputs.sh | 17 ++++-
gitian/gpg/obfs4proxy.gpg | Bin 0 -> 34128 bytes
gitian/mkbundle-linux.sh | 3 +-
gitian/mkbundle-mac.sh | 3 +-
gitian/mkbundle-windows.sh | 3 +-
gitian/verify-tags.sh | 5 +-
gitian/versions.alpha | 9 +++
gitian/versions.nightly | 9 +++
16 files changed, 291 insertions(+), 17 deletions(-)
diff --git a/Bundle-Data/Docs/Licenses/PluggableTransports/LICENSE b/Bundle-Data/Docs/Licenses/PluggableTransports/LICENSE
index 749986b..c6efd2c 100644
--- a/Bundle-Data/Docs/Licenses/PluggableTransports/LICENSE
+++ b/Bundle-Data/Docs/Licenses/PluggableTransports/LICENSE
@@ -13,15 +13,6 @@ file LICENSE.PYTHON.
===============================================================================
-Go
-
-Some pluggable transports are written in Go and the binary packages include
-parts of the Go runtime library. A copy of the Go license (which itself
-includes the licenses of some of Go's components) is included in the file
-LICENSE.GO.
-
-===============================================================================
-
OpenSSL
(From http://openssl.org/source/license.html.)
@@ -447,3 +438,71 @@ To the extent possible under law, the authors have dedicated all
copyright and related and neighboring rights to this software to the
public domain worldwide. This software is distributed without any
warranty. See LICENSE.CC0.
+
+===============================================================================
+
+obfs4
+
+Copyright (c) 2014, Yawning Angel <yawning at torproject dot org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+===============================================================================
+
+go.net
+
+Copyright 2009 The Go Authors. All rights reserved.
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file.
+
+For details about the Go License, please see LICENSE.GO.
+
+===============================================================================
+
+go.crypto
+
+Copyright 2009 The Go Authors. All rights reserved.
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file.
+
+For details about the Go License, please see LICENSE.GO.
+
+===============================================================================
+
+agl/ed25519
+
+Copyright 2013 The Go Authors. All rights reserved.
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file.
+
+For details about the Go License, please see LICENSE.GO.
+
+===============================================================================
+
+dchest/siphash
+
+To the extent possible under law, the authors have dedicated all
+copyright and related and neighboring rights to this software to the
+public domain worldwide. This software is distributed without any
+warranty. See LICENSE.CC0.
diff --git a/Bundle-Data/PTConfigs/bridge_prefs.js b/Bundle-Data/PTConfigs/bridge_prefs.js
index d9c2049..7684fec 100644
--- a/Bundle-Data/PTConfigs/bridge_prefs.js
+++ b/Bundle-Data/PTConfigs/bridge_prefs.js
@@ -30,6 +30,10 @@ pref("extensions.torlauncher.default_bridge.scramblesuit.1", "scramblesuit 188.4
pref("extensions.torlauncher.default_bridge.scramblesuit.2", "scramblesuit 188.226.213.208:54278 AA5A86C1490296EF4FACA946CC5A182FCD1C5B1E password=MD2VRP7WXAMSG7MKIGMHI4CB4BMSNO7T");
pref("extensions.torlauncher.default_bridge.scramblesuit.3", "scramblesuit 83.212.101.3:443 A09D536DD1752D542E1FBB3C9CE4449D51298239 password=XTCXLG2JAMJKZW2POLBAOWOQETQSMASH");
+pref("extensions.torlauncher.default_bridge.obfs4.1", "obfs4 178.209.52.110:443 67E72FF33D7D41BF11C569646A0A7B4B188340DF cert=Z+cv8z19Qb8RxWlkagp7SxiDQN++b7D2Tntowhf+j4D15/kLuj3EoSSGvuREGPc3h60Ofw iat-mode=0");
+pref("extensions.torlauncher.default_bridge.obfs4.2", "obfs4 83.212.101.3:41213 A09D536DD1752D542E1FBB3C9CE4449D51298239 cert=lPRQ/MXdD1t5SRZ9MquYQNT9m5DV757jtdXdlePmRCudUU9CFUOX1Tm7/meFSyPOsud7Cw iat-mode=0");
+pref("extensions.torlauncher.default_bridge.obfs4.3", "obfs4 104.131.108.182:56880 EF577C30B9F788B0E1801CF7E433B3B77792B77A cert=0SFhfDQrKjUJP8Qq6wrwSICEPf3Vl/nJRsYxWbg3QRoSqhl2EB78MPS2lQxbXY4EW1wwXA iat-mode=0");
+
pref("extensions.torlauncher.default_bridge.meek-google.1", "meek 0.0.2.0:1 url=https://meek-reflect.appspot.com/ front=www.google.com");
pref("extensions.torlauncher.default_bridge.meek-amazon.1", "meek 0.0.2.0:2 url=https://d2zfqthxsdq309.cloudfront.net/ front=a0.awsstatic.com");
pref("extensions.torlauncher.default_bridge.meek-azure.1", "meek 0.0.2.0:3 url=https://az668014.vo.msecnd.net/ front=ajax.aspnetcdn.com");
diff --git a/Bundle-Data/PTConfigs/linux/torrc-defaults-appendix b/Bundle-Data/PTConfigs/linux/torrc-defaults-appendix
index d019d19..50e03fd 100644
--- a/Bundle-Data/PTConfigs/linux/torrc-defaults-appendix
+++ b/Bundle-Data/PTConfigs/linux/torrc-defaults-appendix
@@ -2,7 +2,11 @@
ClientTransportPlugin fte exec ./TorBrowser/Tor/PluggableTransports/fteproxy.bin --managed
## obfsproxy configuration
-ClientTransportPlugin obfs2,obfs3,scramblesuit exec ./TorBrowser/Tor/PluggableTransports/obfsproxy.bin managed
+ClientTransportPlugin scramblesuit exec ./TorBrowser/Tor/PluggableTransports/obfsproxy.bin managed
+
+## obfs4proxy configuration
+ClientTransportPlugin obfs2,obfs3,obfs4 exec ./TorBrowser/Tor/PluggableTransports/obfs4proxy
+
## flash proxy configuration
#
# Change the second number here (9000) to the number of a port that can
diff --git a/Bundle-Data/PTConfigs/mac/torrc-defaults-appendix b/Bundle-Data/PTConfigs/mac/torrc-defaults-appendix
index d6ec189..604098f 100644
--- a/Bundle-Data/PTConfigs/mac/torrc-defaults-appendix
+++ b/Bundle-Data/PTConfigs/mac/torrc-defaults-appendix
@@ -2,7 +2,10 @@
ClientTransportPlugin fte exec PluggableTransports/fteproxy.bin --managed
## obfsproxy configuration
-ClientTransportPlugin obfs2,obfs3,scramblesuit exec PluggableTransports/obfsproxy.bin managed
+ClientTransportPlugin scramblesuit exec PluggableTransports/obfsproxy.bin managed
+
+## obfs4proxy configuration
+ClientTransportPlugin obfs2,obfs3,obfs4 exec PluggableTransports/obfs4proxy
## flash proxy configuration
#
diff --git a/Bundle-Data/PTConfigs/windows/torrc-defaults-appendix b/Bundle-Data/PTConfigs/windows/torrc-defaults-appendix
index f1b103d..d92d201 100644
--- a/Bundle-Data/PTConfigs/windows/torrc-defaults-appendix
+++ b/Bundle-Data/PTConfigs/windows/torrc-defaults-appendix
@@ -2,7 +2,10 @@
ClientTransportPlugin fte exec TorBrowser\Tor\PluggableTransports\fteproxy --managed
## obfsproxy configuration
-ClientTransportPlugin obfs2,obfs3,scramblesuit exec TorBrowser\Tor\PluggableTransports\obfsproxy managed
+ClientTransportPlugin scramblesuit exec TorBrowser\Tor\PluggableTransports\obfsproxy managed
+
+## obfs4proxy configuration
+ClientTransportPlugin obfs2,obfs3,obfs4 exec TorBrowser\Tor\PluggableTransports\obfs4proxy
## flash proxy configuration
#
diff --git a/gitian/descriptors/linux/gitian-pluggable-transports.yml b/gitian/descriptors/linux/gitian-pluggable-transports.yml
index 7e23ec5..daa1225 100644
--- a/gitian/descriptors/linux/gitian-pluggable-transports.yml
+++ b/gitian/descriptors/linux/gitian-pluggable-transports.yml
@@ -32,6 +32,12 @@ remotes:
"dir": "goptlib"
- "url": "https://git.torproject.org/pluggable-transports/meek.git"
"dir": "meek"
+- "url": "https://github.com/agl/ed25519.git"
+ "dir": "ed25519"
+- "url": "https://github.com/dchest/siphash.git"
+ "dir": "siphash"
+- "url": "https://git.torproject.org/pluggable-transports/obfs4.git"
+ "dir": "obfs4"
files:
- "pycrypto.tar.gz"
- "argparse.tar.gz"
@@ -46,6 +52,8 @@ files:
- "gmp-linux64-utils.zip"
- "openssl-linux32-utils.zip"
- "openssl-linux64-utils.zip"
+- "go.crypto.tar.bz2"
+- "go.net.tar.bz2"
script: |
INSTDIR="$HOME/install"
PTDIR="$INSTDIR/Tor/PluggableTransports"
@@ -217,6 +225,52 @@ script: |
cp -a README doc/*.1 $INSTDIR/Docs/meek
cd ..
+ # Building go ed25519
+ cd ed25519
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/github.com/agl/"
+ ln -sf "$PWD" "$GOPATH/src/github.com/agl/ed25519"
+ go install github.com/agl/ed25519/extra25519
+ cd ..
+
+ # Building go siphash
+ cd siphash
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/github.com/dchest/"
+ ln -sf "$PWD" "$GOPATH/src/github.com/dchest/siphash"
+ go install github.com/dchest/siphash
+ cd ..
+
+ # Building go.crypto
+ tar xjf go.crypto.tar.bz2
+ cd go.crypto
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/code.google.com/p/"
+ ln -sf "$PWD" "$GOPATH/src/code.google.com/p/go.crypto"
+ go install code.google.com/p/go.crypto/curve25519
+ go install code.google.com/p/go.crypto/hkdf
+ go install code.google.com/p/go.crypto/nacl/secretbox
+ cd ..
+
+ # Building go.net
+ tar xjf go.net.tar.bz2
+ cd go.net
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/code.google.com/p/"
+ ln -sf "$PWD" "$GOPATH/src/code.google.com/p/go.net"
+ go install code.google.com/p/go.net/proxy
+ cd ..
+
+ # Building obfs4proxy
+ cd obfs4
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/git.torproject.org/pluggable-transports"
+ ln -sf "$PWD" "$GOPATH/src/git.torproject.org/pluggable-transports/obfs4.git"
+ cd obfs4proxy
+ go build -ldflags '-s'
+ cp -a obfs4proxy $PTDIR
+ cd ../..
+
# Grabbing the results
cd $INSTDIR
~/build/dzip.sh pluggable-transports-linux$GBUILD_BITS-gbuilt.zip Tor/ Docs/
diff --git a/gitian/descriptors/mac/gitian-pluggable-transports.yml b/gitian/descriptors/mac/gitian-pluggable-transports.yml
index 33df49f..4c25f07 100644
--- a/gitian/descriptors/mac/gitian-pluggable-transports.yml
+++ b/gitian/descriptors/mac/gitian-pluggable-transports.yml
@@ -30,6 +30,12 @@ remotes:
"dir": "goptlib"
- "url": "https://git.torproject.org/pluggable-transports/meek.git"
"dir": "meek"
+- "url": "https://github.com/agl/ed25519.git"
+ "dir": "ed25519"
+- "url": "https://github.com/dchest/siphash.git"
+ "dir": "siphash"
+- "url": "https://git.torproject.org/pluggable-transports/obfs4.git"
+ "dir": "obfs4"
files:
- "pycrypto.tar.gz"
- "argparse.tar.gz"
@@ -44,6 +50,8 @@ files:
- "dzip.sh"
- "gmp-mac32-utils.zip"
- "openssl-mac32-utils.zip"
+- "go.crypto.tar.bz2"
+- "go.net.tar.bz2"
script: |
INSTDIR="$HOME/install"
TBDIR="$INSTDIR/TorBrowserBundle.app/TorBrowser"
@@ -245,6 +253,52 @@ script: |
cp -a README doc/*.1 $TBDIR/Docs/meek
cd ..
+ # Building go ed25519
+ cd ed25519
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/github.com/agl/"
+ ln -sf "$PWD" "$GOPATH/src/github.com/agl/ed25519"
+ go install github.com/agl/ed25519/extra25519
+ cd ..
+
+ # Building go siphash
+ cd siphash
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/github.com/dchest/"
+ ln -sf "$PWD" "$GOPATH/src/github.com/dchest/siphash"
+ go install github.com/dchest/siphash
+ cd ..
+
+ # Building go.crypto
+ tar xjf go.crypto.tar.bz2
+ cd go.crypto
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/code.google.com/p/"
+ ln -sf "$PWD" "$GOPATH/src/code.google.com/p/go.crypto"
+ go install code.google.com/p/go.crypto/curve25519
+ go install code.google.com/p/go.crypto/hkdf
+ go install code.google.com/p/go.crypto/nacl/secretbox
+ cd ..
+
+ # Building go.net
+ tar xjf go.net.tar.bz2
+ cd go.net
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/code.google.com/p/"
+ ln -sf "$PWD" "$GOPATH/src/code.google.com/p/go.net"
+ go install code.google.com/p/go.net/proxy
+ cd ..
+
+ # Building obfs4proxy
+ cd obfs4
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/git.torproject.org/pluggable-transports"
+ ln -sf "$PWD" "$GOPATH/src/git.torproject.org/pluggable-transports/obfs4.git"
+ cd obfs4proxy
+ go build -ldflags '-s'
+ cp -a obfs4proxy $PTDIR
+ cd ../..
+
# Grabbing the result
cd $INSTDIR
~/build/dzip.sh pluggable-transports-mac$GBUILD_BITS-gbuilt.zip TorBrowserBundle.app
diff --git a/gitian/descriptors/windows/gitian-pluggable-transports.yml b/gitian/descriptors/windows/gitian-pluggable-transports.yml
index 6a6301d..bd3189b 100644
--- a/gitian/descriptors/windows/gitian-pluggable-transports.yml
+++ b/gitian/descriptors/windows/gitian-pluggable-transports.yml
@@ -29,6 +29,12 @@ remotes:
"dir": "goptlib"
- "url": "https://git.torproject.org/pluggable-transports/meek.git"
"dir": "meek"
+- "url": "https://github.com/agl/ed25519.git"
+ "dir": "ed25519"
+- "url": "https://github.com/dchest/siphash.git"
+ "dir": "siphash"
+- "url": "https://git.torproject.org/pluggable-transports/obfs4.git"
+ "dir": "obfs4"
files:
- "setuptools.tar.gz"
- "pycrypto.tar.gz"
@@ -49,6 +55,8 @@ files:
- "openssl-win32-utils.zip"
- "gmp-win32-utils.zip"
- "gcclibs-win32-utils.zip"
+- "go.crypto.tar.bz2"
+- "go.net.tar.bz2"
script: |
# Set the timestamp on every .pyc file in a zip file, and re-dzip the zip file.
function py2exe_zip_timestomp {
@@ -323,6 +331,52 @@ script: |
cp -a README doc/*.1.txt $INSTDIR/Docs/meek
cd ..
+ # Building go ed25519
+ cd ed25519
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/github.com/agl/"
+ ln -sf "$PWD" "$GOPATH/src/github.com/agl/ed25519"
+ go install github.com/agl/ed25519/extra25519
+ cd ..
+
+ # Building go siphash
+ cd siphash
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/github.com/dchest/"
+ ln -sf "$PWD" "$GOPATH/src/github.com/dchest/siphash"
+ go install github.com/dchest/siphash
+ cd ..
+
+ # Building go.crypto
+ tar xjf go.crypto.tar.bz2
+ cd go.crypto
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/code.google.com/p/"
+ ln -sf "$PWD" "$GOPATH/src/code.google.com/p/go.crypto"
+ go install code.google.com/p/go.crypto/curve25519
+ go install code.google.com/p/go.crypto/hkdf
+ go install code.google.com/p/go.crypto/nacl/secretbox
+ cd ..
+
+ # Building go.net
+ tar xjf go.net.tar.bz2
+ cd go.net
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/code.google.com/p/"
+ ln -sf "$PWD" "$GOPATH/src/code.google.com/p/go.net"
+ go install code.google.com/p/go.net/proxy
+ cd ..
+
+ # Building obfs4proxy
+ cd obfs4
+ find -type f | xargs touch --date="$REFERENCE_DATETIME"
+ mkdir -p "$GOPATH/src/git.torproject.org/pluggable-transports"
+ ln -sf "$PWD" "$GOPATH/src/git.torproject.org/pluggable-transports/obfs4.git"
+ cd obfs4proxy
+ go build -ldflags '-s'
+ cp -a obfs4proxy.exe $PTDIR
+ cd ../..
+
# http://bugs.winehq.org/show_bug.cgi?id=3591
cp -a $INSTDIR/python/python27.dll $PTDIR/
diff --git a/gitian/fetch-inputs.sh b/gitian/fetch-inputs.sh
index ef4dbf7..049824a 100755
--- a/gitian/fetch-inputs.sh
+++ b/gitian/fetch-inputs.sh
@@ -6,6 +6,7 @@
MIRROR_URL=https://people.torproject.org/~mikeperry/mirrors/sources/
MIRROR_URL_DCF=https://people.torproject.org/~dcf/mirrors/sources/
MIRROR_URL_ASN=https://people.torproject.org/~asn/mirrors/sources/
+MIRROR_URL_YAWNING=https://people.torproject.org/~yawning/mirrors/sources/
set -e
set -u
umask 0022
@@ -179,6 +180,15 @@ do
get "${!PACKAGE}" "${!URL}"
done
+# XXX/Yawning. As far as I can tell, this gitian thing doesn't support
+# fetching from hg repositories.
+for i in GOCRYPTO GONET
+do
+ PACKAGE="${i}_PACKAGE"
+ URL="${MIRROR_URL_YAWNING}${!PACKAGE}"
+ get "${!PACKAGE}" "${MIRROR_URL_YAWNING}${!PACKAGE}"
+done
+
# Verify packages with weak or no signatures via multipath downloads
# (OpenSSL is signed with MD5, and OSXSDK is not signed at all)
# XXX: Google won't allow wget -N.. We need to re-download the whole
@@ -208,7 +218,7 @@ wget -U "" -N ${HTTPSE_URL}
# Verify packages with weak or no signatures via direct sha256 check
# (OpenSSL is signed with MD5, and OSXSDK is not signed at all)
-for i in OSXSDK TOOLCHAIN4 TOOLCHAIN4_OLD NOSCRIPT HTTPSE MSVCR100 PYCRYPTO ARGPARSE PYYAML ZOPEINTERFACE TWISTED M2CRYPTO SETUPTOOLS OPENSSL GMP PARSLEY GO GCC
+for i in OSXSDK TOOLCHAIN4 TOOLCHAIN4_OLD NOSCRIPT HTTPSE MSVCR100 PYCRYPTO ARGPARSE PYYAML ZOPEINTERFACE TWISTED M2CRYPTO SETUPTOOLS OPENSSL GMP PARSLEY GO GCC GOCRYPTO GONET
do
PACKAGE="${i}_PACKAGE"
HASH="${i}_HASH"
@@ -262,6 +272,8 @@ ln -sf "$GMP_PACKAGE" gmp.tar.bz2
ln -sf "$LXML_PACKAGE" lxml.tar.gz
ln -sf "$PARSLEY_PACKAGE" parsley.tar.gz
ln -sf "$GO_PACKAGE" go.tar.gz
+ln -sf "$GONET_PACKAGE" go.net.tar.bz2
+ln -sf "$GOCRYPTO_PACKAGE" go.crypto.tar.bz2
# Fetch latest gitian-builder itself
# XXX - this is broken if a non-standard inputs dir is selected using the command line flag.
@@ -295,6 +307,9 @@ txsocksx https://github.com/habnabit/txsocksx.git $TXSOCKSX_TAG
goptlib https://git.torproject.org/pluggable-transports/goptlib.git $GOPTLIB_TAG
meek https://git.torproject.org/pluggable-transports/meek.git $MEEK_TAG
faketime https://github.com/wolfcw/libfaketime $FAKETIME_TAG
+ed25519 https://github.com/agl/ed25519.git $GOED25519_TAG
+siphash https://github.com/dchest/siphash.git $GOSIPHASH_TAG
+obfs4 https://git.torproject.org/pluggable-transports/obfs4.git $OBFS4_TAG
EOF
exit 0
diff --git a/gitian/gpg/obfs4proxy.gpg b/gitian/gpg/obfs4proxy.gpg
new file mode 100644
index 0000000..b9c490a
Binary files /dev/null and b/gitian/gpg/obfs4proxy.gpg differ
diff --git a/gitian/mkbundle-linux.sh b/gitian/mkbundle-linux.sh
index 8321ffe..45f4f9b 100755
--- a/gitian/mkbundle-linux.sh
+++ b/gitian/mkbundle-linux.sh
@@ -94,6 +94,7 @@ then
PYPTLIB_TAG=refs/tags/$PYPTLIB_TAG
OBFSPROXY_TAG=refs/tags/$OBFSPROXY_TAG
FLASHPROXY_TAG=refs/tags/$FLASHPROXY_TAG
+ OBFS4_TAG=refs/tags/$OBFS4_TAG
fi
cd $GITIAN_DIR
@@ -221,7 +222,7 @@ then
echo "****** Starting Pluggable Transports Component of Linux Bundle (4/5 for Linux) ******"
echo
- ./bin/gbuild -j $NUM_PROCS -m $VM_MEMORY --commit pyptlib=$PYPTLIB_TAG,obfsproxy=$OBFSPROXY_TAG,flashproxy=$FLASHPROXY_TAG,libfte=$LIBFTE_TAG,fteproxy=$FTEPROXY_TAG,txsocksx=$TXSOCKSX_TAG,goptlib=$GOPTLIB_TAG,meek=$MEEK_TAG $DESCRIPTOR_DIR/linux/gitian-pluggable-transports.yml
+ ./bin/gbuild -j $NUM_PROCS -m $VM_MEMORY --commit pyptlib=$PYPTLIB_TAG,obfsproxy=$OBFSPROXY_TAG,flashproxy=$FLASHPROXY_TAG,libfte=$LIBFTE_TAG,fteproxy=$FTEPROXY_TAG,txsocksx=$TXSOCKSX_TAG,goptlib=$GOPTLIB_TAG,meek=$MEEK_TAG,ed25519=$GOED25519_TAG,siphash=$GOSIPHASH_TAG,obfs4=$OBFS4_TAG $DESCRIPTOR_DIR/linux/gitian-pluggable-transports.yml
if [ $? -ne 0 ];
then
#mv var/build.log ./pluggable-transports-fail-linux.log.`date +%Y%m%d%H%M%S`
diff --git a/gitian/mkbundle-mac.sh b/gitian/mkbundle-mac.sh
index 9c5d99b..807319b 100755
--- a/gitian/mkbundle-mac.sh
+++ b/gitian/mkbundle-mac.sh
@@ -99,6 +99,7 @@ then
PYPTLIB_TAG=refs/tags/$PYPTLIB_TAG
OBFSPROXY_TAG=refs/tags/$OBFSPROXY_TAG
FLASHPROXY_TAG=refs/tags/$FLASHPROXY_TAG
+ OBFS4_TAG=refs/tags/$OBFS4_TAG
fi
cd $GITIAN_DIR
@@ -187,7 +188,7 @@ then
echo "****** Starting Pluggable Transports Component of Mac Bundle (4/5 for Mac) ******"
echo
- ./bin/gbuild -j $NUM_PROCS -m $VM_MEMORY --commit pyptlib=$PYPTLIB_TAG,obfsproxy=$OBFSPROXY_TAG,flashproxy=$FLASHPROXY_TAG,libfte=$LIBFTE_TAG,fteproxy=$FTEPROXY_TAG,txsocksx=$TXSOCKSX_TAG,goptlib=$GOPTLIB_TAG,meek=$MEEK_TAG $DESCRIPTOR_DIR/mac/gitian-pluggable-transports.yml
+ ./bin/gbuild -j $NUM_PROCS -m $VM_MEMORY --commit pyptlib=$PYPTLIB_TAG,obfsproxy=$OBFSPROXY_TAG,flashproxy=$FLASHPROXY_TAG,libfte=$LIBFTE_TAG,fteproxy=$FTEPROXY_TAG,txsocksx=$TXSOCKSX_TAG,goptlib=$GOPTLIB_TAG,meek=$MEEK_TAG,ed25519=$GOED25519_TAG,siphash=$GOSIPHASH_TAG,obfs4=$OBFS4_TAG $DESCRIPTOR_DIR/mac/gitian-pluggable-transports.yml
if [ $? -ne 0 ];
then
#mv var/build.log ./firefox-fail-mac.log.`date +%Y%m%d%H%M%S`
diff --git a/gitian/mkbundle-windows.sh b/gitian/mkbundle-windows.sh
index 7600e07..38d1eff 100755
--- a/gitian/mkbundle-windows.sh
+++ b/gitian/mkbundle-windows.sh
@@ -92,6 +92,7 @@ then
PYPTLIB_TAG=refs/tags/$PYPTLIB_TAG
OBFSPROXY_TAG=refs/tags/$OBFSPROXY_TAG
FLASHPROXY_TAG=refs/tags/$FLASHPROXY_TAG
+ OBFS4_TAG=refs/tags/$OBFS4_TAG
fi
cd $GITIAN_DIR
@@ -190,7 +191,7 @@ then
echo "****** Starting Pluggable Transports Component of Windows Bundle (4/5 for Windows) ******"
echo
- ./bin/gbuild -j $NUM_PROCS -m $VM_MEMORY --commit pyptlib=$PYPTLIB_TAG,obfsproxy=$OBFSPROXY_TAG,flashproxy=$FLASHPROXY_TAG,libfte=$LIBFTE_TAG,fteproxy=$FTEPROXY_TAG,txsocksx=$TXSOCKSX_TAG,goptlib=$GOPTLIB_TAG,meek=$MEEK_TAG $DESCRIPTOR_DIR/windows/gitian-pluggable-transports.yml
+ ./bin/gbuild -j $NUM_PROCS -m $VM_MEMORY --commit pyptlib=$PYPTLIB_TAG,obfsproxy=$OBFSPROXY_TAG,flashproxy=$FLASHPROXY_TAG,libfte=$LIBFTE_TAG,fteproxy=$FTEPROXY_TAG,txsocksx=$TXSOCKSX_TAG,goptlib=$GOPTLIB_TAG,meek=$MEEK_TAG,ed25519=$GOED25519_TAG,siphash=$GOSIPHASH_TAG,obfs4=$OBFS4_TAG $DESCRIPTOR_DIR/windows/gitian-pluggable-transports.yml
if [ $? -ne 0 ];
then
#mv var/build.log ./pluggable-transports-fail-win32.log.`date +%Y%m%d%H%M%S`
diff --git a/gitian/verify-tags.sh b/gitian/verify-tags.sh
index b7a89f1..09454bb 100755
--- a/gitian/verify-tags.sh
+++ b/gitian/verify-tags.sh
@@ -101,6 +101,7 @@ obfsproxy obfsproxy.gpg $OBFSPROXY_TAG
flashproxy flashproxy.gpg $FLASHPROXY_TAG
goptlib goptlib.gpg $GOPTLIB_TAG
meek meek.gpg $MEEK_TAG
+obfs4 obfs4proxy.gpg $OBFS4_TAG
EOF
#https-everywhere https-everywhere.gpg $HTTPSE_TAG
@@ -113,6 +114,8 @@ libfte $LIBFTE_TAG
fteproxy $FTEPROXY_TAG
txsocksx $TXSOCKSX_TAG
faketime $FAKETIME_TAG
+ed25519 $GOED25519_TAG
+siphash $GOSIPHASH_TAG
EOF
# Verify signatures on signed packages
@@ -136,7 +139,7 @@ done
# Verify packages with weak or no signatures via direct sha256 check
# (OpenSSL is signed with MD5, and OSXSDK is not signed at all)
-for i in OSXSDK TOOLCHAIN4 TOOLCHAIN4_OLD NOSCRIPT HTTPSE MSVCR100 PYCRYPTO ARGPARSE PYYAML ZOPEINTERFACE TWISTED M2CRYPTO SETUPTOOLS OPENSSL GMP PARSLEY GO GCC
+for i in OSXSDK TOOLCHAIN4 TOOLCHAIN4_OLD NOSCRIPT HTTPSE MSVCR100 PYCRYPTO ARGPARSE PYYAML ZOPEINTERFACE TWISTED M2CRYPTO SETUPTOOLS OPENSSL GMP PARSLEY GO GCC GOCRYPTO GONET
do
PACKAGE="${i}_PACKAGE"
HASH="${i}_HASH"
diff --git a/gitian/versions.alpha b/gitian/versions.alpha
index e17b071..0912b5d 100755
--- a/gitian/versions.alpha
+++ b/gitian/versions.alpha
@@ -27,6 +27,9 @@ TXSOCKSX_TAG=216eb0894a1755872f4789f9458aa6cf543b8433 # unsigned habnabit/1.13.0
GOPTLIB_TAG=0.2
MEEK_TAG=0.11
FAKETIME_TAG=70aa6b394d9341522dffe8a5a5cf5929e82cc6b9 # unsigned v0.9.6
+GOED25519_TAG=c4161f4c7483313562781c61b9a20aba73daf9de
+GOSIPHASH_TAG=42ba037e748c9062a75e0924705c43b893edefcd
+OBFS4_TAG=obfs4proxy-0.0.3
GITIAN_TAG=tor-browser-builder-3.x-7
@@ -74,6 +77,8 @@ SETUPTOOLS_PACKAGE=setuptools-${SETUPTOOLS_VER}.tar.gz
LXML_PACKAGE=lxml-${LXML_VER}.tar.gz
PARSLEY_PACKAGE=Parsley-${PARSLEY_VER}.tar.gz
GO_PACKAGE=go${GO_VER}.src.tar.gz
+GOCRYPTO_PACKAGE=go.crypto-5478be1963aa.tar.bz2
+GONET_PACKAGE=go.net-9c0f9daaa74b.tar.bz2
# Hashes for packages with weak sigs or no sigs
OPENSSL_HASH=3c179f46ca77069a6a0bac70212a9b3b838b2f66129cb52d568837fc79d8fcc7
@@ -94,6 +99,8 @@ PY2EXE_HASH=610a8800de3d973ed5ed4ac505ab42ad058add18a68609ac09e6cf3598ef056c
SETUPTOOLS_HASH=75d288687066ed124311d6ca5f40ffa92a0e81adcd7fff318c6e84082713cf39
PARSLEY_HASH=50d30cee70770fd44db7cea421cb2fb75af247c3a1cd54885c06b30a7c85dd23
GO_HASH=1bb6fde89cfe8b9756a875af55d994cce0994861227b5dc0f268c143d91cd5ff
+GOCRYPTO_HASH=a8e301714f5724999321f0397b867a5670a5e5c4f808ba157bdd93ee0d028827
+GONET_HASH=1812fec55256e1a6fe546111cc658520b80972f38826c94ec11ef24315d32353
## Non-git package URLs
OPENSSL_URL=https://www.openssl.org/source/${OPENSSL_PACKAGE}
@@ -119,3 +126,5 @@ SETUPTOOLS_URL=https://pypi.python.org/packages/source/s/setuptools/${SETUP…
LXML_URL=https://pypi.python.org/packages/source/l/lxml/${LXML_PACKAGE}
PARSLEY_URL=https://pypi.python.org/packages/source/P/Parsley/${PARSLEY_PAC…
GO_URL=http://golang.org/dl/${GO_PACKAGE}
+GOCRYPTO_URL=https://people.torproject.org/~yawning/mirrors/sources/${GOCRYPTO_PACKAGE}
+GONET_URL=https://people.torproject.org/~yawning/mirrors/sources/${GONET_PACKAGE}
diff --git a/gitian/versions.nightly b/gitian/versions.nightly
index 5541ded..3867629 100755
--- a/gitian/versions.nightly
+++ b/gitian/versions.nightly
@@ -28,6 +28,9 @@ TXSOCKSX_TAG=216eb0894a1755872f4789f9458aa6cf543b8433 # unsigned habnabit/1.13.0
GOPTLIB_TAG=master
MEEK_TAG=master
FAKETIME_TAG=70aa6b394d9341522dffe8a5a5cf5929e82cc6b9 # unsigned v0.9.6
+GOED25519_TAG=c4161f4c7483313562781c61b9a20aba73daf9de
+GOSIPHASH_TAG=42ba037e748c9062a75e0924705c43b893edefcd
+OBFS4_TAG=master
GITIAN_TAG=tor-browser-builder-3.x-7
@@ -75,6 +78,8 @@ SETUPTOOLS_PACKAGE=setuptools-${SETUPTOOLS_VER}.tar.gz
LXML_PACKAGE=lxml-${LXML_VER}.tar.gz
PARSLEY_PACKAGE=Parsley-${PARSLEY_VER}.tar.gz
GO_PACKAGE=go${GO_VER}.src.tar.gz
+GOCRYPTO_PACKAGE=go.crypto-5478be1963aa.tar.bz2
+GONET_PACKAGE=go.net-9c0f9daaa74b.tar.bz2
# Hashes for packages with weak sigs or no sigs
OPENSSL_HASH=3c179f46ca77069a6a0bac70212a9b3b838b2f66129cb52d568837fc79d8fcc7
@@ -95,6 +100,8 @@ PY2EXE_HASH=610a8800de3d973ed5ed4ac505ab42ad058add18a68609ac09e6cf3598ef056c
SETUPTOOLS_HASH=75d288687066ed124311d6ca5f40ffa92a0e81adcd7fff318c6e84082713cf39
PARSLEY_HASH=50d30cee70770fd44db7cea421cb2fb75af247c3a1cd54885c06b30a7c85dd23
GO_HASH=1bb6fde89cfe8b9756a875af55d994cce0994861227b5dc0f268c143d91cd5ff
+GOCRYPTO_HASH=a8e301714f5724999321f0397b867a5670a5e5c4f808ba157bdd93ee0d028827
+GONET_HASH=1812fec55256e1a6fe546111cc658520b80972f38826c94ec11ef24315d32353
## Non-git package URLs
OPENSSL_URL=https://www.openssl.org/source/${OPENSSL_PACKAGE}
@@ -120,3 +127,5 @@ SETUPTOOLS_URL=https://pypi.python.org/packages/source/s/setuptools/${SETUP…
LXML_URL=https://pypi.python.org/packages/source/l/lxml/${LXML_PACKAGE}
PARSLEY_URL=https://pypi.python.org/packages/source/P/Parsley/${PARSLEY_PAC…
GO_URL=http://golang.org/dl/${GO_PACKAGE}
+GOCRYPTO_URL=https://people.torproject.org/~yawning/mirrors/sources/${GOCRYPTO_PACKAGE}
+GONET_URL=https://people.torproject.org/~yawning/mirrors/sources/${GONET_PACKAGE}
1
0
commit 875f231364067b4092cfd000761010b04acc9e52
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Sat Oct 25 15:28:55 2014 -0700
Bump TBB version.
---
gitian/versions | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gitian/versions b/gitian/versions
index 30222f7..b6ec79f 100755
--- a/gitian/versions
+++ b/gitian/versions
@@ -1,4 +1,4 @@
-TORBROWSER_VERSION=4.0
+TORBROWSER_VERSION=4.0.1
BUNDLE_LOCALES="ar de es-ES fa fr it ko nl pl pt-PT ru tr vi zh-CN"
BUILD_PT_BUNDLES=1
1
0
25 Oct '14
commit 2fd4c60edcd6946728f62072f20f88a4eaf9ad50
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Sat Oct 25 01:07:28 2014 -0700
Pick up new #13091 fix.
---
Bundle-Data/Docs/ChangeLog.txt | 1 +
gitian/versions | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/Bundle-Data/Docs/ChangeLog.txt b/Bundle-Data/Docs/ChangeLog.txt
index fe53b58..b99e049 100644
--- a/Bundle-Data/Docs/ChangeLog.txt
+++ b/Bundle-Data/Docs/ChangeLog.txt
@@ -6,6 +6,7 @@ Tor Browser 4.0.1 -- Oct 30 2014
* Bug 13460: Fix MSVC compilation issue
* Windows
* Bug 13443: Disable DirectShow to prevent crashes on many sites
+ * Bug 13091: Make app name "Tor Browser" instead of "Tor"
Tor Browser 4.0 -- Oct 15 2014
* All Platforms
diff --git a/gitian/versions b/gitian/versions
index 8d8c4c9..30222f7 100755
--- a/gitian/versions
+++ b/gitian/versions
@@ -8,7 +8,7 @@ FIREFOX_VERSION=31.2.0esr
TORBROWSER_UPDATE_CHANNEL=release
-TORBROWSER_TAG=tor-browser-${FIREFOX_VERSION}-4.x-1-build2
+TORBROWSER_TAG=tor-browser-${FIREFOX_VERSION}-4.x-1-build3
TOR_TAG=tor-0.2.5.10
TORLAUNCHER_TAG=0.2.7.0.1
TORBUTTON_TAG=1.7.0.1
1
0
[tor-browser/tor-browser-31.2.0esr-4.x-1] fixup! Bug 13091: include spaces in Win resources.
by mikeperry@torproject.org 25 Oct '14
by mikeperry@torproject.org 25 Oct '14
25 Oct '14
commit 26735f870de9ec7cb7b9e6aa5bbf4fd9f92ea4fd
Author: Kathy Brade <brade(a)pearlcrescent.com>
Date: Fri Oct 24 14:07:03 2014 -0400
fixup! Bug 13091: include spaces in Win resources.
Our app display name, "Tor Browser", was truncated to "Tor" within Windows
resources (FileDescription, InternalName, and ProductName fields). Fixed by
adding quotes around parameters passed to the version_win.pl program.
---
config/version.mk | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/version.mk b/config/version.mk
index 414a1eb..219ac60 100644
--- a/config/version.mk
+++ b/config/version.mk
@@ -15,7 +15,7 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
ifndef RESFILE
RCFILE=./module.rc
RESFILE=./module.res
-_RC_STRING = -QUIET 1 -DEPTH $(DEPTH) -TOPSRCDIR $(topsrcdir) -OBJDIR . -SRCDIR $(srcdir) -DISPNAME $(MOZ_APP_DISPLAYNAME) -APPVERSION $(MOZ_APP_VERSION)
+_RC_STRING = -QUIET 1 -DEPTH $(DEPTH) -TOPSRCDIR $(topsrcdir) -OBJDIR . -SRCDIR $(srcdir) -DISPNAME "$(MOZ_APP_DISPLAYNAME)" -APPVERSION "$(MOZ_APP_VERSION)"
ifdef MOZILLA_OFFICIAL
_RC_STRING += -OFFICIAL 1
endif
1
0
[tor-browser/tor-browser-31.2.0esr-4.x-1] Merge remote-tracking branch 'brade/bug13091-02' into tor-browser-31.2.0esr-4.x-1
by mikeperry@torproject.org 25 Oct '14
by mikeperry@torproject.org 25 Oct '14
25 Oct '14
commit 5d1ed040472bfcfe66445fe44ae41e37e94c2eb1
Merge: 3dd8fa4 26735f8
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Sat Oct 25 01:01:10 2014 -0700
Merge remote-tracking branch 'brade/bug13091-02' into tor-browser-31.2.0esr-4.x-1
config/version.mk | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
1
0
[tor-browser-bundle/master] Use pre-gitified version of the TOR_TAG for the "expert bundle".
by mikeperry@torproject.org 25 Oct '14
by mikeperry@torproject.org 25 Oct '14
25 Oct '14
commit da82bae559cc2203a43bf58bd1afd6beabc790c2
Author: Mike Perry <mikeperry-git(a)torproject.org>
Date: Fri Oct 24 23:41:57 2014 -0700
Use pre-gitified version of the TOR_TAG for the "expert bundle".
---
gitian/mkbundle-windows.sh | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/gitian/mkbundle-windows.sh b/gitian/mkbundle-windows.sh
index c686983..673344a 100755
--- a/gitian/mkbundle-windows.sh
+++ b/gitian/mkbundle-windows.sh
@@ -74,6 +74,7 @@ die_msg() {
LIBEVENT_TAG_ORIG=$LIBEVENT_TAG
ZLIB_TAG_ORIG=$ZLIB_TAG
+TOR_TAG_ORIG=$TOR_TAG
if [ "z$VERIFY_TAGS" = "z1" ];
then
@@ -223,7 +224,7 @@ then
mkdir -p $WRAPPER_DIR/$TORBROWSER_VERSION/
cp -a build/out/*.exe $WRAPPER_DIR/$TORBROWSER_VERSION/ || exit 1
cp -a build/out/*.mar $WRAPPER_DIR/$TORBROWSER_VERSION/ || exit 1
- cp -a inputs/tor-win32-gbuilt.zip $WRAPPER_DIR/$TORBROWSER_VERSION/tor-win32-${TOR_TAG}.zip || exit 1
+ cp -a inputs/tor-win32-gbuilt.zip $WRAPPER_DIR/$TORBROWSER_VERSION/tor-win32-${TOR_TAG_ORIG}.zip || exit 1
touch inputs/bundle-windows.gbuilt
else
echo
1
0