Bug 1686828 - Use https OriginAttributes to fetch HTTPS RR r=necko-reviewers,timhuang,dragana

Differential Revision: https://phabricator.services.mozilla.com/D102234
This commit is contained in:
Kershaw Chang 2021-01-21 22:08:26 +00:00
Родитель a14601368c
Коммит 27daadc420
6 изменённых файлов: 69 добавлений и 15 удалений

Просмотреть файл

@ -41,7 +41,16 @@ nsDNSPrefetch::nsDNSPrefetch(nsIURI* aURI,
mTRRMode(aTRRMode),
mListener(do_GetWeakReference(aListener)) {
aURI->GetAsciiHost(mHostname);
mIsHttps = aURI->SchemeIs("https");
}
nsDNSPrefetch::nsDNSPrefetch(nsIURI* aURI,
mozilla::OriginAttributes& aOriginAttributes,
nsIRequest::TRRMode aTRRMode)
: mOriginAttributes(aOriginAttributes),
mStoreTiming(false),
mTRRMode(aTRRMode),
mListener(nullptr) {
aURI->GetAsciiHost(mHostname);
}
nsresult nsDNSPrefetch::Prefetch(uint32_t flags) {
@ -114,17 +123,20 @@ HTTPSRRListener::OnLookupComplete(nsICancelable* aRequest, nsIDNSRecord* aRec,
}; // namespace
nsresult nsDNSPrefetch::FetchHTTPSSVC(
bool aRefreshDNS, std::function<void(nsIDNSHTTPSSVCRecord*)>&& aCallback) {
bool aRefreshDNS, bool aPrefetch,
std::function<void(nsIDNSHTTPSSVCRecord*)>&& aCallback) {
if (!sDNSService) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIEventTarget> target = mozilla::GetCurrentEventTarget();
uint32_t flags = nsIDNSService::GetFlagsFromTRRMode(mTRRMode) |
nsIDNSService::RESOLVE_SPECULATE;
uint32_t flags = nsIDNSService::GetFlagsFromTRRMode(mTRRMode);
if (aRefreshDNS) {
flags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
}
if (aPrefetch) {
flags |= nsIDNSService::RESOLVE_SPECULATE;
}
nsCOMPtr<nsICancelable> tmpOutstanding;
nsCOMPtr<nsIDNSListener> listener = new HTTPSRRListener(std::move(aCallback));

Просмотреть файл

@ -31,6 +31,9 @@ class nsDNSPrefetch final : public nsIDNSListener {
nsDNSPrefetch(nsIURI* aURI, mozilla::OriginAttributes& aOriginAttributes,
nsIRequest::TRRMode aTRRMode, nsIDNSListener* aListener,
bool storeTiming);
// For fetching HTTPS RR.
nsDNSPrefetch(nsIURI* aURI, mozilla::OriginAttributes& aOriginAttributes,
nsIRequest::TRRMode aTRRMode);
bool TimingsValid() const {
return !mStartTimestamp.IsNull() && !mEndTimestamp.IsNull();
}
@ -47,11 +50,11 @@ class nsDNSPrefetch final : public nsIDNSListener {
nsresult PrefetchLow(bool refreshDNS = false);
nsresult FetchHTTPSSVC(
bool aRefreshDNS, std::function<void(nsIDNSHTTPSSVCRecord*)>&& aCallback);
bool aRefreshDNS, bool aPrefetch,
std::function<void(nsIDNSHTTPSSVCRecord*)>&& aCallback);
private:
nsCString mHostname;
bool mIsHttps;
mozilla::OriginAttributes mOriginAttributes;
bool mStoreTiming;
nsIRequest::TRRMode mTRRMode;

Просмотреть файл

@ -6829,12 +6829,20 @@ nsresult nsHttpChannel::MaybeStartDNSPrefetch() {
mDNSBlockingThenable = mDNSBlockingPromise.Ensure(__func__);
}
// When LoadUseHTTPSSVC() is true, we should really "fetch" the HTTPS RR,
// not "prefetch", since DNS prefetch can be disabled by the pref.
if (LoadUseHTTPSSVC() ||
gHttpHandler->UseHTTPSRRForSpeculativeConnection()) {
OriginAttributes originAttributes;
StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(this,
originAttributes);
RefPtr<nsDNSPrefetch> resolver =
new nsDNSPrefetch(mURI, originAttributes, nsIRequest::GetTRRMode());
nsWeakPtr weakPtrThis(
do_GetWeakReference(static_cast<nsIHttpChannel*>(this)));
rv = mDNSPrefetch->FetchHTTPSSVC(
mCaps & NS_HTTP_REFRESH_DNS,
nsresult rv = resolver->FetchHTTPSSVC(
mCaps & NS_HTTP_REFRESH_DNS, !LoadUseHTTPSSVC(),
[weakPtrThis](nsIDNSHTTPSSVCRecord* aRecord) {
nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(weakPtrThis);
RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(channel);

Просмотреть файл

@ -236,6 +236,7 @@ function makeChan(url) {
let chan = NetUtil.newChannel({
uri: url,
loadUsingSystemPrincipal: true,
contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
}).QueryInterface(Ci.nsIHttpChannel);
return chan;
}
@ -285,8 +286,13 @@ add_task(async function testConnectionWithIPHint() {
);
// The connection should be succeeded since the IP hint is 127.0.0.1.
let chan = makeChan(`https://test.iphint.com:8080/`);
let chan = makeChan(`http://test.iphint.com:8080/`);
// Note that the partitionKey stored in DNS cache would be
// "%28https%2Ciphint.com%29". The http request to test.iphint.com will be
// upgraded to https and the ip hint address will be used by the https
// request in the end.
let [req] = await channelOpenPromise(chan);
req.QueryInterface(Ci.nsIHttpChannel);
Assert.equal(req.getResponseHeader("x-connection-http2"), "yes");
certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(

Просмотреть файл

@ -328,10 +328,14 @@ void StoragePrincipalHelper::UpdateOriginAttributesForNetworkState(
aAttributes.SetPartitionKey(aFirstPartyURI);
}
// static
bool StoragePrincipalHelper::GetOriginAttributesForHSTS(
nsIChannel* aChannel, OriginAttributes& aAttributes) {
if (!GetOriginAttributesForNetworkState(aChannel, aAttributes)) {
enum SupportedScheme { HTTP, HTTPS };
static bool GetOriginAttributesWithScheme(nsIChannel* aChannel,
OriginAttributes& aAttributes,
SupportedScheme aScheme) {
const nsString targetScheme = aScheme == HTTP ? u"http"_ns : u"https"_ns;
if (!StoragePrincipalHelper::GetOriginAttributesForNetworkState(
aChannel, aAttributes)) {
return false;
}
@ -358,16 +362,29 @@ bool StoragePrincipalHelper::GetOriginAttributesForHSTS(
nsAutoString scheme;
scheme.Assign(Substring(start, iter));
if (!scheme.EqualsLiteral("https")) {
if (scheme.Equals(targetScheme)) {
return true;
}
nsAutoString key;
key.AssignLiteral("(http");
key += u"("_ns;
key += targetScheme;
key.Append(Substring(iter, end));
aAttributes.SetPartitionKey(key);
return true;
}
// static
bool StoragePrincipalHelper::GetOriginAttributesForHSTS(
nsIChannel* aChannel, OriginAttributes& aAttributes) {
return GetOriginAttributesWithScheme(aChannel, aAttributes, HTTP);
}
// static
bool StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(
nsIChannel* aChannel, OriginAttributes& aAttributes) {
return GetOriginAttributesWithScheme(aChannel, aAttributes, HTTPS);
}
} // namespace mozilla

Просмотреть файл

@ -275,6 +275,14 @@ class StoragePrincipalHelper final {
// For HSTS we want to force 'HTTP' in the partition key.
static bool GetOriginAttributesForHSTS(nsIChannel* aChannel,
OriginAttributes& aAttributes);
// Like the function above, this function forces `HTTPS` in the partition key.
// The OA created by this function is mainly used in DNS cache. The spec
// specifies that the presence of HTTPS RR for an origin also indicates that
// all HTTP resources are available over HTTPS, so we use this function to
// ensure that all HTTPS RRs in DNS cache are accessed by HTTPS requests only.
static bool GetOriginAttributesForHTTPSRR(nsIChannel* aChannel,
OriginAttributes& aAttributes);
};
} // namespace mozilla