From 0f07bc4a3d68dc62d41e0a443a2881317a03b80e Mon Sep 17 00:00:00 2001 From: Kershaw Chang Date: Tue, 16 Jul 2019 08:50:14 +0000 Subject: [PATCH] Bug 1309358 - P1: Add wildcard to Access-Control-Expose-Headers r=baku For requests without credentials, add wildcard to Access-Control-Expose-Headers. Differential Revision: https://phabricator.services.mozilla.com/D36624 --HG-- extra : moz-landing-system : lando --- dom/fetch/FetchDriver.cpp | 6 +++-- dom/fetch/InternalHeaders.cpp | 25 +++++++++++++------ dom/fetch/InternalHeaders.h | 4 ++- dom/fetch/InternalResponse.cpp | 8 +++--- dom/fetch/InternalResponse.h | 6 ++++- dom/xhr/XMLHttpRequestMainThread.cpp | 6 ++++- .../api/cors/cors-expose-star.sub.any.js.ini | 13 ---------- 7 files changed, 39 insertions(+), 29 deletions(-) diff --git a/dom/fetch/FetchDriver.cpp b/dom/fetch/FetchDriver.cpp index 4e61f35afe91..76a7fc2f7f99 100644 --- a/dom/fetch/FetchDriver.cpp +++ b/dom/fetch/FetchDriver.cpp @@ -865,7 +865,8 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest) { rv = httpChannel->GetResponseStatusText(statusText); MOZ_ASSERT(NS_SUCCEEDED(rv)); - response = new InternalResponse(responseStatus, statusText); + response = new InternalResponse(responseStatus, statusText, + mRequest->GetCredentialsMode()); UniquePtr principalInfo( new mozilla::ipc::PrincipalInfo()); @@ -893,7 +894,8 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest) { } MOZ_ASSERT(!result.Failed()); } else { - response = new InternalResponse(200, NS_LITERAL_CSTRING("OK")); + response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"), + mRequest->GetCredentialsMode()); if (!contentType.IsEmpty()) { nsAutoCString contentCharset; diff --git a/dom/fetch/InternalHeaders.cpp b/dom/fetch/InternalHeaders.cpp index e5a8202820a9..378ddb29f77b 100644 --- a/dom/fetch/InternalHeaders.cpp +++ b/dom/fetch/InternalHeaders.cpp @@ -510,7 +510,7 @@ already_AddRefed InternalHeaders::BasicHeaders( // static already_AddRefed InternalHeaders::CORSHeaders( - InternalHeaders* aHeaders) { + InternalHeaders* aHeaders, RequestCredentials aCredentialsMode) { RefPtr cors = new InternalHeaders(aHeaders->mGuard); ErrorResult result; @@ -519,6 +519,7 @@ already_AddRefed InternalHeaders::CORSHeaders( acExposedNames, result); MOZ_ASSERT(!result.Failed()); + bool allowAllHeaders = false; AutoTArray exposeNamesArray; nsCCharSeparatedTokenizer exposeTokens(acExposedNames, ','); while (exposeTokens.hasMoreTokens()) { @@ -536,19 +537,27 @@ already_AddRefed InternalHeaders::CORSHeaders( break; } + if (token.EqualsLiteral("*") && + aCredentialsMode != RequestCredentials::Include) { + allowAllHeaders = true; + } + exposeNamesArray.AppendElement(token); } nsCaseInsensitiveCStringArrayComparator comp; for (uint32_t i = 0; i < aHeaders->mList.Length(); ++i) { const Entry& entry = aHeaders->mList[i]; - if (entry.mName.EqualsIgnoreCase("cache-control") || - entry.mName.EqualsIgnoreCase("content-language") || - entry.mName.EqualsIgnoreCase("content-type") || - entry.mName.EqualsIgnoreCase("expires") || - entry.mName.EqualsIgnoreCase("last-modified") || - entry.mName.EqualsIgnoreCase("pragma") || - exposeNamesArray.Contains(entry.mName, comp)) { + if (allowAllHeaders) { + cors->Append(entry.mName, entry.mValue, result); + MOZ_ASSERT(!result.Failed()); + } else if (entry.mName.EqualsIgnoreCase("cache-control") || + entry.mName.EqualsIgnoreCase("content-language") || + entry.mName.EqualsIgnoreCase("content-type") || + entry.mName.EqualsIgnoreCase("expires") || + entry.mName.EqualsIgnoreCase("last-modified") || + entry.mName.EqualsIgnoreCase("pragma") || + exposeNamesArray.Contains(entry.mName, comp)) { cors->Append(entry.mName, entry.mValue, result); MOZ_ASSERT(!result.Failed()); } diff --git a/dom/fetch/InternalHeaders.h b/dom/fetch/InternalHeaders.h index fdbcd5cd3f72..bd7796862df5 100644 --- a/dom/fetch/InternalHeaders.h +++ b/dom/fetch/InternalHeaders.h @@ -9,6 +9,7 @@ // needed for HeadersGuardEnum. #include "mozilla/dom/HeadersBinding.h" +#include "mozilla/dom/RequestBinding.h" #include "mozilla/dom/UnionTypes.h" #include "nsClassHashtable.h" @@ -113,7 +114,8 @@ class InternalHeaders final { InternalHeaders* aHeaders); static already_AddRefed CORSHeaders( - InternalHeaders* aHeaders); + InternalHeaders* aHeaders, + RequestCredentials mCredentialsMode = RequestCredentials::Omit); void GetEntries(nsTArray& aEntries) const; diff --git a/dom/fetch/InternalResponse.cpp b/dom/fetch/InternalResponse.cpp index 26a5b7bb58cb..922ade82767c 100644 --- a/dom/fetch/InternalResponse.cpp +++ b/dom/fetch/InternalResponse.cpp @@ -28,14 +28,16 @@ const uint32_t kMaxRandomNumber = 102400; } // namespace InternalResponse::InternalResponse(uint16_t aStatus, - const nsACString& aStatusText) + const nsACString& aStatusText, + RequestCredentials aCredentialsMode) : mType(ResponseType::Default), mStatus(aStatus), mStatusText(aStatusText), mHeaders(new InternalHeaders(HeadersGuardEnum::Response)), mBodySize(UNKNOWN_BODY_SIZE), mPaddingSize(UNKNOWN_PADDING_SIZE), - mErrorCode(NS_OK) {} + mErrorCode(NS_OK), + mCredentialsMode(aCredentialsMode) {} InternalResponse::~InternalResponse() {} @@ -93,7 +95,7 @@ already_AddRefed InternalResponse::CORSResponse() { "Can't CORSResponse a already wrapped response"); RefPtr cors = CreateIncompleteCopy(); cors->mType = ResponseType::Cors; - cors->mHeaders = InternalHeaders::CORSHeaders(Headers()); + cors->mHeaders = InternalHeaders::CORSHeaders(Headers(), mCredentialsMode); cors->mWrappedResponse = this; return cors.forget(); } diff --git a/dom/fetch/InternalResponse.h b/dom/fetch/InternalResponse.h index ce9a0cd40444..408f18e02ec7 100644 --- a/dom/fetch/InternalResponse.h +++ b/dom/fetch/InternalResponse.h @@ -13,6 +13,7 @@ #include "nsProxyRelease.h" #include "mozilla/dom/InternalHeaders.h" +#include "mozilla/dom/RequestBinding.h" #include "mozilla/dom/ResponseBinding.h" #include "mozilla/dom/ChannelInfo.h" #include "mozilla/UniquePtr.h" @@ -33,7 +34,9 @@ class InternalResponse final { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalResponse) - InternalResponse(uint16_t aStatus, const nsACString& aStatusText); + InternalResponse( + uint16_t aStatus, const nsACString& aStatusText, + RequestCredentials aCredentialsMode = RequestCredentials::Omit); enum CloneType { eCloneInputStream, @@ -317,6 +320,7 @@ class InternalResponse final { Maybe mPaddingInfo; int64_t mPaddingSize; nsresult mErrorCode; + RequestCredentials mCredentialsMode; // For alternative data such as JS Bytecode cached in the HTTP cache. nsCOMPtr mAlternativeBody; diff --git a/dom/xhr/XMLHttpRequestMainThread.cpp b/dom/xhr/XMLHttpRequestMainThread.cpp index 9e9ac84fd355..c85fcbb64d9a 100644 --- a/dom/xhr/XMLHttpRequestMainThread.cpp +++ b/dom/xhr/XMLHttpRequestMainThread.cpp @@ -1029,10 +1029,14 @@ bool XMLHttpRequestMainThread::IsSafeHeader( if (!NS_IsValidHTTPToken(token)) { return false; } - if (aHeader.Equals(token, nsCaseInsensitiveCStringComparator())) { + + if (token.EqualsLiteral("*") && !mFlagACwithCredentials) { + isSafe = true; + } else if (aHeader.Equals(token, nsCaseInsensitiveCStringComparator())) { isSafe = true; } } + return isSafe; } diff --git a/testing/web-platform/meta/fetch/api/cors/cors-expose-star.sub.any.js.ini b/testing/web-platform/meta/fetch/api/cors/cors-expose-star.sub.any.js.ini index 9b247bfeb2e2..528e32b10b77 100644 --- a/testing/web-platform/meta/fetch/api/cors/cors-expose-star.sub.any.js.ini +++ b/testing/web-platform/meta/fetch/api/cors/cors-expose-star.sub.any.js.ini @@ -1,15 +1,2 @@ [cors-expose-star.sub.any.html] - [Basic Access-Control-Expose-Headers: * support] - expected: FAIL - - [* can be one of several values] - expected: FAIL - - [cors-expose-star.sub.any.worker.html] - [Basic Access-Control-Expose-Headers: * support] - expected: FAIL - - [* can be one of several values] - expected: FAIL -