tbb-commits
Threads by month
- ----- 2025 -----
- 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
- 18563 discussions

[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] 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] 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] 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