Bug 1312794 - Annotate OCSP requests by first party domain. (adapted from Tor Browser patch #13670) r=keeler

--HG--
extra : rebase_source : 1ba4d78756f9170c1ba05738dda06b9ad00a3231
This commit is contained in:
Jonathan Hao 2016-11-03 17:53:52 +08:00
parent ba525e3bc3
commit 736db2051a
6 changed files with 78 additions and 6 deletions

View File

@ -558,7 +558,7 @@ NSSCertDBTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA,
// Owned by arena
SECItem* responseSECItem = nullptr;
Result tempRV =
DoOCSPRequest(arena, url, &ocspRequestItem,
DoOCSPRequest(arena, url, mFirstPartyDomain, &ocspRequestItem,
OCSPFetchingTypeToTimeoutTime(mOCSPFetching),
mOCSPGetConfig == CertVerifier::ocspGetEnabled,
responseSECItem);

View File

@ -74,8 +74,8 @@ AppendEscapedBase64Item(const SECItem* encodedRequest, nsACString& path)
Result
DoOCSPRequest(const UniquePLArenaPool& arena, const char* url,
const SECItem* encodedRequest, PRIntervalTime timeout,
bool useGET,
const char* firstPartyDomain, const SECItem* encodedRequest,
PRIntervalTime timeout, bool useGET,
/*out*/ SECItem*& encodedResponse)
{
MOZ_ASSERT(arena.get());
@ -173,7 +173,8 @@ DoOCSPRequest(const UniquePLArenaPool& arena, const char* url,
nsNSSHttpRequestSession* requestSessionPtr;
rv = nsNSSHttpInterface::createFcn(serverSession.get(), "http", path.get(),
method.get(), timeout, &requestSessionPtr);
method.get(), firstPartyDomain, timeout,
&requestSessionPtr);
if (rv != Success) {
return rv;
}

View File

@ -14,6 +14,7 @@ namespace mozilla { namespace psm {
// The memory returned via |encodedResponse| is owned by the given arena.
Result DoOCSPRequest(const UniquePLArenaPool& arena, const char* url,
const char* firstPartyDomain,
const SECItem* encodedRequest, PRIntervalTime timeout,
bool useGET,
/*out*/ SECItem*& encodedResponse);

View File

@ -114,6 +114,18 @@ nsHTTPDownloadEvent::Run()
chan->SetLoadFlags(nsIRequest::LOAD_ANONYMOUS |
nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
if (!mRequestSession->mFirstPartyDomain.IsEmpty()) {
NeckoOriginAttributes attrs;
attrs.mFirstPartyDomain =
NS_ConvertUTF8toUTF16(mRequestSession->mFirstPartyDomain);
nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo();
if (loadInfo) {
rv = loadInfo->SetOriginAttributes(attrs);
NS_ENSURE_SUCCESS(rv, rv);
}
}
// Create a loadgroup for this new channel. This way if the channel
// is redirected, we'll have a way to cancel the resulting channel.
nsCOMPtr<nsILoadGroup> lg = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
@ -218,6 +230,7 @@ nsNSSHttpRequestSession::createFcn(const nsNSSHttpServerSession* session,
const char* http_protocol_variant,
const char* path_and_query_string,
const char* http_request_method,
const char* first_party_domain,
const PRIntervalTime timeout,
/*out*/ nsNSSHttpRequestSession** pRequest)
{
@ -247,6 +260,8 @@ nsNSSHttpRequestSession::createFcn(const nsNSSHttpServerSession* session,
rs->mURL.AppendInt(session->mPort);
rs->mURL.Append(path_and_query_string);
rs->mFirstPartyDomain.Assign(first_party_domain);
rs->mRequestMethod = http_request_method;
*pRequest = rs;

View File

@ -99,6 +99,7 @@ public:
const char* httpProtocolVariant,
const char* pathAndQueryString,
const char* httpRequestMethod,
const char* firstPartyDomain,
const PRIntervalTime timeout,
/*out*/ nsNSSHttpRequestSession** pRequest);
@ -123,6 +124,8 @@ public:
nsCString mPostData;
nsCString mPostContentType;
nsCString mFirstPartyDomain;
PRIntervalTime mTimeoutInterval;
RefPtr<nsHTTPListener> mListener;
@ -156,13 +159,14 @@ public:
const char* httpProtocolVariant,
const char* pathAndQueryString,
const char* httpRequestMethod,
const char* firstPartyDomain,
const PRIntervalTime timeout,
/*out*/ nsNSSHttpRequestSession** pRequest)
{
return nsNSSHttpRequestSession::createFcn(session, httpProtocolVariant,
pathAndQueryString,
httpRequestMethod, timeout,
pRequest);
httpRequestMethod, firstPartyDomain,
timeout, pRequest);
}
static Result setPostDataFcn(nsNSSHttpRequestSession* request,

View File

@ -223,6 +223,38 @@ function add_tests() {
// This test makes sure that OCSP cache are isolated by firstPartyDomain.
let gObservedCnt = 0;
let protocolProxyService = Cc["@mozilla.org/network/protocol-proxy-service;1"]
.getService(Ci.nsIProtocolProxyService);
// Observe all channels and make sure the firstPartyDomain in their loadInfo's
// origin attributes are aFirstPartyDomain.
function startObservingChannels(aFirstPartyDomain) {
// We use a dummy proxy filter to catch all channels, even those that do not
// generate an "http-on-modify-request" notification.
let proxyFilter = {
applyFilter: function (aProxyService, aChannel, aProxy) {
// We have the channel; provide it to the callback.
if (aChannel.originalURI.spec == "http://localhost:8888/") {
gObservedCnt++;
equal(aChannel.loadInfo.originAttributes.firstPartyDomain,
aFirstPartyDomain, "firstPartyDomain should match");
}
// Pass on aProxy unmodified.
return aProxy;
}
};
protocolProxyService.registerChannelFilter(proxyFilter, 0);
// Return the stop() function:
return () => protocolProxyService.unregisterChannelFilter(proxyFilter);
}
let stopObservingChannels;
add_test(function() {
stopObservingChannels = startObservingChannels("foo.com");
run_next_test();
});
// A good OCSP response will be cached.
add_ocsp_test("ocsp-stapling-none.example.com", PRErrorCodeSuccess,
[respondWithGoodOCSP],
@ -234,12 +266,31 @@ function add_tests() {
"Noted OCSP server failure (firstPartyDomain = foo.com) -> a " +
"fetch should not have been attempted", "foo.com");
add_test(function() {
stopObservingChannels();
equal(gObservedCnt, 1, "should have observed only 1 OCSP requests");
gObservedCnt = 0;
run_next_test();
});
add_test(function() {
stopObservingChannels = startObservingChannels("bar.com");
run_next_test();
});
// But using a different firstPartyDomain should result in a fetch.
add_ocsp_test("ocsp-stapling-none.example.com", PRErrorCodeSuccess,
[respondWithGoodOCSP],
"No stapled response (firstPartyDomain = bar.com) -> a fetch " +
"should have been attempted", "bar.com");
add_test(function() {
stopObservingChannels();
equal(gObservedCnt, 1, "should have observed only 1 OCSP requests");
gObservedCnt = 0;
run_next_test();
});
//---------------------------------------------------------------------------
// Reset state