#612 (from OlgaTPark/14) M1250987 M1309358 M1394399

This commit is contained in:
Cameron Kaiser 2020-10-25 14:27:50 -07:00
parent 81c8a93b94
commit 06bbc2e34c
9 changed files with 75 additions and 41 deletions

View File

@ -1317,7 +1317,10 @@ nsXMLHttpRequest::IsSafeHeader(const nsACString& header, nsIHttpChannel* httpCha
if (!NS_IsValidHTTPToken(token)) {
return false;
}
if (header.Equals(token, nsCaseInsensitiveCStringComparator())) {
if (token.EqualsLiteral("*")) {
isSafe = true;
} else if (header.Equals(token, nsCaseInsensitiveCStringComparator())) {
isSafe = true;
}
}

View File

@ -491,7 +491,8 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
nsAutoCString statusText;
httpChannel->GetResponseStatusText(statusText);
response = new InternalResponse(responseStatus, statusText);
response = new InternalResponse(responseStatus, statusText,
mRequest->GetCredentialsMode());
RefPtr<FillResponseHeaders> visitor = new FillResponseHeaders(response);
rv = httpChannel->VisitResponseHeaders(visitor);
@ -511,7 +512,8 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
result);
MOZ_ASSERT(!result.Failed());
} else {
response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"),
mRequest->GetCredentialsMode());
ErrorResult result;
nsAutoCString contentType;

View File

@ -300,7 +300,8 @@ InternalHeaders::BasicHeaders(InternalHeaders* aHeaders)
// static
already_AddRefed<InternalHeaders>
InternalHeaders::CORSHeaders(InternalHeaders* aHeaders)
InternalHeaders::CORSHeaders(InternalHeaders* aHeaders,
RequestCredentials aCredentialsMode)
{
RefPtr<InternalHeaders> cors = new InternalHeaders(aHeaders->mGuard);
ErrorResult result;
@ -309,6 +310,7 @@ InternalHeaders::CORSHeaders(InternalHeaders* aHeaders)
aHeaders->Get(NS_LITERAL_CSTRING("Access-Control-Expose-Headers"), acExposedNames, result);
MOZ_ASSERT(!result.Failed());
bool allowAllHeaders = false;
nsAutoTArray<nsCString, 5> exposeNamesArray;
nsCCharSeparatedTokenizer exposeTokens(acExposedNames, ',');
while (exposeTokens.hasMoreTokens()) {
@ -324,19 +326,27 @@ InternalHeaders::CORSHeaders(InternalHeaders* aHeaders)
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.EqualsASCII("cache-control") ||
entry.mName.EqualsASCII("content-language") ||
entry.mName.EqualsASCII("content-type") ||
entry.mName.EqualsASCII("expires") ||
entry.mName.EqualsASCII("last-modified") ||
entry.mName.EqualsASCII("pragma") ||
exposeNamesArray.Contains(entry.mName, comp)) {
if (allowAllHeaders) {
cors->Append(entry.mName, entry.mValue, result);
MOZ_ASSERT(!result.Failed());
} else if (entry.mName.EqualsASCII("cache-control") ||
entry.mName.EqualsASCII("content-language") ||
entry.mName.EqualsASCII("content-type") ||
entry.mName.EqualsASCII("expires") ||
entry.mName.EqualsASCII("last-modified") ||
entry.mName.EqualsASCII("pragma") ||
exposeNamesArray.Contains(entry.mName, comp)) {
cors->Append(entry.mName, entry.mValue, result);
MOZ_ASSERT(!result.Failed());
}

View File

@ -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"
@ -103,7 +104,8 @@ public:
BasicHeaders(InternalHeaders* aHeaders);
static already_AddRefed<InternalHeaders>
CORSHeaders(InternalHeaders* aHeaders);
CORSHeaders(InternalHeaders* aHeaders,
RequestCredentials mCredentialsMode = RequestCredentials::Omit);
void
GetEntries(nsTArray<InternalHeaders::Entry>& aEntries) const;

View File

@ -16,11 +16,14 @@
namespace mozilla {
namespace dom {
InternalResponse::InternalResponse(uint16_t aStatus, const nsACString& aStatusText)
InternalResponse::InternalResponse(uint16_t aStatus,
const nsACString& aStatusText,
RequestCredentials aCredentialsMode)
: mType(ResponseType::Default)
, mStatus(aStatus)
, mStatusText(aStatusText)
, mHeaders(new InternalHeaders(HeadersGuardEnum::Response))
, mCredentialsMode(aCredentialsMode)
{
}
@ -76,7 +79,7 @@ InternalResponse::CORSResponse()
MOZ_ASSERT(!mWrappedResponse, "Can't CORSResponse a already wrapped response");
RefPtr<InternalResponse> cors = CreateIncompleteCopy();
cors->mType = ResponseType::Cors;
cors->mHeaders = InternalHeaders::CORSHeaders(Headers());
cors->mHeaders = InternalHeaders::CORSHeaders(Headers(), mCredentialsMode);
cors->mWrappedResponse = this;
return cors.forget();
}

View File

@ -10,7 +10,9 @@
#include "nsIInputStream.h"
#include "nsISupportsImpl.h"
#include "mozilla/dom/InternalHeaders.h"
#include "mozilla/dom/ResponseBinding.h"
#include "mozilla/dom/RequestBinding.h"
#include "mozilla/dom/ChannelInfo.h"
#include "mozilla/UniquePtr.h"
@ -30,7 +32,8 @@ 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);
already_AddRefed<InternalResponse> Clone();
@ -241,6 +244,7 @@ private:
nsCOMPtr<nsIInputStream> mBody;
ChannelInfo mChannelInfo;
UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
RequestCredentials mCredentialsMode;
// For filtered responses.
// Cache, and SW interception should always serialize/access the underlying

View File

@ -275,7 +275,7 @@ Request::Constructor(const GlobalObject& aGlobal,
request->SetURL(NS_ConvertUTF16toUTF8(requestURL));
fallbackMode = RequestMode::Cors;
fallbackCredentials = RequestCredentials::Omit;
fallbackCredentials = RequestCredentials::Same_origin;
fallbackCache = RequestCache::Default;
}
@ -365,7 +365,8 @@ Request::Constructor(const GlobalObject& aGlobal,
return nullptr;
}
if (aInit.mBody.WasPassed() || temporaryBody) {
if ((aInit.mBody.WasPassed() && !aInit.mBody.Value().IsNull()) ||
temporaryBody) {
// HEAD and GET are not allowed to have a body.
nsAutoCString method;
request->GetMethod(method);
@ -377,29 +378,34 @@ Request::Constructor(const GlobalObject& aGlobal,
}
if (aInit.mBody.WasPassed()) {
const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& bodyInit = aInit.mBody.Value();
nsCOMPtr<nsIInputStream> stream;
nsAutoCString contentType;
aRv = ExtractByteStreamFromBody(bodyInit,
getter_AddRefs(stream), contentType);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
const Nullable<OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>& bodyInitNullable =
aInit.mBody.Value();
if (!bodyInitNullable.IsNull()) {
const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& bodyInit =
bodyInitNullable.Value();
nsCOMPtr<nsIInputStream> stream;
nsAutoCString contentType;
aRv = ExtractByteStreamFromBody(bodyInit,
getter_AddRefs(stream), contentType);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
temporaryBody = stream;
if (!contentType.IsVoid() &&
!requestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
requestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
contentType, aRv);
}
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
request->ClearCreatedByFetchEvent();
request->SetBody(temporaryBody);
}
temporaryBody = stream;
if (!contentType.IsVoid() &&
!requestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
requestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
contentType, aRv);
}
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
request->ClearCreatedByFetchEvent();
request->SetBody(temporaryBody);
}
RefPtr<Request> domRequest = new Request(global, request);

View File

@ -38,7 +38,7 @@ Request implements Body;
dictionary RequestInit {
ByteString method;
HeadersInit headers;
BodyInit body;
BodyInit? body;
RequestMode mode;
RequestCredentials credentials;
RequestCache cache;

View File

@ -1272,7 +1272,11 @@ nsCORSPreflightListener::CheckPreflightRequestApproved(nsIRequest* aRequest)
NS_ConvertUTF8toUTF16(method).get());
return NS_ERROR_DOM_BAD_URI;
}
foundMethod |= mPreflightMethod.Equals(method);
if (method.EqualsLiteral("*") && !mWithCredentials) {
foundMethod = true;
} else {
foundMethod |= mPreflightMethod.Equals(method);
}
}
if (!foundMethod) {
LogBlockedRequest(aRequest, "CORSMethodNotFound", nullptr);