Bug 1768583 - Allow having a PerformanceResourceTiming entry for cross origin redirects r=necko-reviewers,dragana

According to the latest Fetch spec, we should generate a opaque
PerformanceResourceTiming entry for cross origin redirects, rather than
not generating it at all.

Plus the timings for cross-origin redirects won't be leaked unless all
redirects pass the TAO check.

Differential Revision: https://phabricator.services.mozilla.com/D146580
This commit is contained in:
Sean Feng 2022-06-16 14:09:31 +00:00
Родитель d0027d4880
Коммит 0294dfaf7a
7 изменённых файлов: 34 добавлений и 466 удалений

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

@ -15,6 +15,21 @@
#include "PerformanceTiming.h" #include "PerformanceTiming.h"
namespace mozilla::dom { namespace mozilla::dom {
#define IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(name) \
DOMHighResTimeStamp name(Maybe<nsIPrincipal*>& aSubjectPrincipal) const { \
bool allowed = !mTimingData->RedirectCountReal() \
? TimingAllowedForCaller(aSubjectPrincipal) \
: ReportRedirectForCaller(aSubjectPrincipal, false); \
return allowed ? mTimingData->name##HighRes(mPerformance) : 0; \
}
#define IMPL_RESOURCE_TIMING_TAO_PROTECTED_SIZE_PROP(name) \
uint64_t name(Maybe<nsIPrincipal*>& aSubjectPrincipal) const { \
bool allowed = !mTimingData->RedirectCountReal() \
? TimingAllowedForCaller(aSubjectPrincipal) \
: ReportRedirectForCaller(aSubjectPrincipal, false); \
return allowed ? mTimingData->name() : 0; \
}
// http://www.w3.org/TR/resource-timing/#performanceresourcetiming // http://www.w3.org/TR/resource-timing/#performanceresourcetiming
class PerformanceResourceTiming : public PerformanceEntry { class PerformanceResourceTiming : public PerformanceEntry {
@ -48,7 +63,9 @@ class PerformanceResourceTiming : public PerformanceEntry {
} }
void GetNextHopProtocol(nsAString& aNextHopProtocol) const { void GetNextHopProtocol(nsAString& aNextHopProtocol) const {
aNextHopProtocol = mTimingData->NextHopProtocol(); if (mTimingData->TimingAllowed()) {
aNextHopProtocol = mTimingData->NextHopProtocol();
}
} }
DOMHighResTimeStamp WorkerStart() const { DOMHighResTimeStamp WorkerStart() const {
@ -91,80 +108,33 @@ class PerformanceResourceTiming : public PerformanceEntry {
false /* aEnsureSameOriginAndIgnoreTAO */); false /* aEnsureSameOriginAndIgnoreTAO */);
} }
DOMHighResTimeStamp DomainLookupStart( IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(DomainLookupStart)
Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->DomainLookupStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp DomainLookupEnd( IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(DomainLookupEnd)
Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->DomainLookupEndHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp ConnectStart( IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(ConnectStart)
Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->ConnectStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp ConnectEnd( IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(ConnectEnd)
Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->ConnectEndHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp RequestStart( IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(RequestStart)
Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->RequestStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp ResponseStart( IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(ResponseStart)
Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->ResponseStartHighRes(mPerformance)
: 0;
}
DOMHighResTimeStamp ResponseEnd() const { DOMHighResTimeStamp ResponseEnd() const {
return mTimingData->ResponseEndHighRes(mPerformance); return mTimingData->ResponseEndHighRes(mPerformance);
} }
DOMHighResTimeStamp SecureConnectionStart( IMPL_RESOURCE_TIMING_TAO_PROTECTED_TIMING_PROP(SecureConnectionStart)
Maybe<nsIPrincipal*>& aSubjectPrincipal) const {
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->SecureConnectionStartHighRes(mPerformance)
: 0;
}
virtual const PerformanceResourceTiming* ToResourceTiming() const override { virtual const PerformanceResourceTiming* ToResourceTiming() const override {
return this; return this;
} }
uint64_t TransferSize(Maybe<nsIPrincipal*>& aSubjectPrincipal) const { IMPL_RESOURCE_TIMING_TAO_PROTECTED_SIZE_PROP(TransferSize)
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->TransferSize()
: 0;
}
uint64_t EncodedBodySize(Maybe<nsIPrincipal*>& aSubjectPrincipal) const { IMPL_RESOURCE_TIMING_TAO_PROTECTED_SIZE_PROP(EncodedBodySize)
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->EncodedBodySize()
: 0;
}
uint64_t DecodedBodySize(Maybe<nsIPrincipal*>& aSubjectPrincipal) const { IMPL_RESOURCE_TIMING_TAO_PROTECTED_SIZE_PROP(DecodedBodySize)
return TimingAllowedForCaller(aSubjectPrincipal)
? mTimingData->DecodedBodySize()
: 0;
}
void GetServerTiming(nsTArray<RefPtr<PerformanceServerTiming>>& aRetval, void GetServerTiming(nsTArray<RefPtr<PerformanceServerTiming>>& aRetval,
Maybe<nsIPrincipal*>& aSubjectPrincipal); Maybe<nsIPrincipal*>& aSubjectPrincipal);

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

@ -143,9 +143,13 @@ function checkRedirectedSameOrigin(entry) {
} }
// The final entry passes the timing-allow-check, // The final entry passes the timing-allow-check,
// but one of the redirects does not. redirectStart/End are 0. // but one of the redirects does not. redirectStart/End and the rest of the
// attributes are 0 because all redirects need to pass TAO check.
function checkRedirectCrossOriginResourceSameOrigin(entry) { function checkRedirectCrossOriginResourceSameOrigin(entry) {
const checks = { "redirectStart": 0, "redirectEnd": 0 }; const checks = { "redirectStart": 0, "redirectEnd": 0,
"domainLookupStart": 0, "domainLookupEnd": 0,
"connectStart": 0, "connectEnd": 0,
"requestStart": 0, "responseStart": 0 };
checkEntry(entry, checks); checkEntry(entry, checks);
} }

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

@ -4781,8 +4781,6 @@ nsresult HttpBaseChannel::SetupReplacementChannel(nsIURI* newURI,
MOZ_ASSERT(NS_SUCCEEDED(rv)); MOZ_ASSERT(NS_SUCCEEDED(rv));
} }
// This channel has been redirected. Don't report timing info.
StoreTimingEnabled(false);
return NS_OK; return NS_OK;
} }

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

@ -1,7 +1,4 @@
[SO-XO-SO-redirect-chain-tao.https.html] [SO-XO-SO-redirect-chain-tao.https.html]
[Verify that cross origin resources' timings are not exposed when same-origin=>cross-origin=>same-origin redirects have no `Timing-Allow-Origin:` headers.]
expected: FAIL
[Verify that cross origin resources' timings are not exposed when same-origin=>cross-origin=>same-origin redirects have `Timing-Allow-Origin:` headers only on some of the responses.] [Verify that cross origin resources' timings are not exposed when same-origin=>cross-origin=>same-origin redirects have `Timing-Allow-Origin:` headers only on some of the responses.]
expected: FAIL expected: FAIL

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

@ -1,253 +0,0 @@
[TAO-match.html]
expected:
if os == "android": OK
TIMEOUT
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a case-sensitive match. (iframe)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains the origin and a wildcard. (iframe)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only the origin. (iframe)]
expected:
if os == "android": PASS
TIMEOUT
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a case-sensitive match. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains the origin and a wildcard. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only the origin. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a case-sensitive match. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains the origin and a wildcard. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only the origin. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a case-sensitive match. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains the origin and a wildcard. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only the origin. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only a wildcard. (iframe)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a wildcard. (iframe)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value list contains a null origin. (iframe)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains multiple wildcards. (iframe)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains only the uppercased origin. (iframe)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains the origin, a space, then a wildcard. (iframe)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header is not present. (iframe)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only a wildcard. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a wildcard. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value list contains a null origin. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains multiple wildcards. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains only the uppercased origin. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains the origin, a space, then a wildcard. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header is not present. (image)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only a wildcard. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a wildcard. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value list contains a null origin. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains multiple wildcards. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains only the uppercased origin. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains the origin, a space, then a wildcard. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header is not present. (script)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only a wildcard. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a wildcard. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value list contains a null origin. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains multiple wildcards. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains only the uppercased origin. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains the origin, a space, then a wildcard. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header is not present. (stylesheet)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only the origin. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value contains only a wildcard. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a case-sensitive match. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains the origin and a wildcard. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains a wildcard. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value list contains a null origin. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will pass when the Timing-Allow-Origin header value list contains multiple wildcards. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains only the uppercased origin. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header value contains the origin, a space, then a wildcard. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN
[The timing allow check algorithm will fail when the Timing-Allow-Origin header is not present. (XMLHttpRequest)]
expected:
if os == "android": PASS
NOTRUN

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

@ -1,72 +0,0 @@
[cross-origin-redirects.html]
disabled:
if win10_2004 and ccov: https://bugzilla.mozilla.org/show_bug.cgi?id=1733368
expected:
if os == "android": OK
TIMEOUT
max-asserts: 2
[Verify that a redirect chain through cross-origin resources do not have their timings exposed when any of the TAO checks fail. (FAIL -> PASS -> FAIL)]
expected:
if (os == "win") and ccov: FAIL
if os == "android": FAIL
NOTRUN
[Verify that a redirect chain through cross-origin resources do not have their timings exposed when any of the TAO checks fail. (PASS -> FAIL -> PASS)]
expected:
if (os == "win") and ccov: FAIL
if os == "android": FAIL
NOTRUN
[Verify that a redirected cross-origin resources' timings aren't exposed when the TAO check fails.]
expected:
if (os == "win") and ccov: PASS
if os == "android": PASS
NOTRUN
[Verify that a redirect chain through cross-origin resources do not have their timings exposed when any of the TAO checks fail. (FAIL -> FAIL -> PASS)]
expected:
if (os == "win") and ccov: FAIL
if os == "android": FAIL
NOTRUN
[Verify that cross-origin resources' timings are exposed when the TAO check succeeds. Also verify that secureConnectionStart is 0 since the original request was over HTTP.]
expected:
if (os == "win") and ccov: PASS
if os == "android": PASS
NOTRUN
[Verify that a redirect chain through cross-origin resources do not have their timings exposed when any of the TAO checks fail. (FAIL -> PASS -> PASS)]
expected:
if (os == "win") and ccov: FAIL
if os == "android": FAIL
NOTRUN
[Verify that a redirect chain through cross-origin resources do not have their timings exposed when any of the TAO checks fail. (PASS -> FAIL -> FAIL)]
expected:
if (os == "win") and ccov: FAIL
if os == "android": FAIL
NOTRUN
[Verify that a redirect chain through cross-origin resources do not have their timings exposed when any of the TAO checks fail. (FAIL -> FAIL -> FAIL)]
expected:
if (os == "win") and ccov: FAIL
if os == "android": FAIL
NOTRUN
[Verify that a redirect chain through cross-origin resources have their timings exposed when all TAO checks succeed. Also verify that secureConnectionStart is 0 since the original request was over HTTP.]
expected:
if (os == "win") and ccov: PASS
if os == "android": PASS
NOTRUN
[Verify that a redirect chain through cross-origin resources do not have their timings exposed when any of the TAO checks fail. (PASS -> PASS -> FAIL)]
expected:
if (os == "win") and ccov: FAIL
if os == "android": FAIL
NOTRUN
[Verify that cross-origin resources' timings aren't exposed through HTTP redirects.]
expected:
if (os == "win") and ccov: PASS
if os == "android": PASS
TIMEOUT

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

@ -1,76 +0,0 @@
[nextHopProtocol-is-tao-protected.https.html]
expected:
if os == "android": OK
TIMEOUT
[Fetch TAO-less font from remote origin. Make sure nextHopProtocol is the empty string.]
expected: FAIL
[Fetch TAO-less iframe from remote origin. Make sure nextHopProtocol is the empty string.]
expected:
if os == "android": FAIL
TIMEOUT
[Fetch TAO'd iframe from remote origin. Make sure nextHopProtocol is not the empty string.]
expected:
if os == "android": PASS
NOTRUN
[Fetch TAO-less image from remote origin. Make sure nextHopProtocol is the empty string.]
expected:
if os == "android": FAIL
NOTRUN
[Fetch TAO'd image from remote origin. Make sure nextHopProtocol is not the empty string.]
expected:
if os == "android": PASS
NOTRUN
[Fetch TAO-less object from remote origin. Make sure nextHopProtocol is the empty string.]
expected:
if os == "android": FAIL
NOTRUN
[Fetch TAO'd object from remote origin. Make sure nextHopProtocol is not the empty string.]
expected:
if os == "android": PASS
NOTRUN
[Fetch TAO-less script from remote origin. Make sure nextHopProtocol is the empty string.]
expected:
if os == "android": FAIL
NOTRUN
[Fetch TAO'd script from remote origin. Make sure nextHopProtocol is not the empty string.]
expected:
if os == "android": PASS
NOTRUN
[Fetch TAO-less stylesheet from remote origin. Make sure nextHopProtocol is the empty string.]
expected:
if os == "android": FAIL
NOTRUN
[Fetch TAO'd stylesheet from remote origin. Make sure nextHopProtocol is not the empty string.]
expected:
if os == "android": PASS
NOTRUN
[Fetch TAO-less synchronous xhr from remote origin. Make sure nextHopProtocol is the empty string.]
expected:
if os == "android": FAIL
NOTRUN
[Fetch TAO'd synchronous xhr from remote origin. Make sure nextHopProtocol is not the empty string.]
expected:
if os == "android": PASS
NOTRUN
[Fetch TAO-less asynchronous xhr from remote origin. Make sure nextHopProtocol is the empty string.]
expected:
if os == "android": FAIL
NOTRUN
[Fetch TAO'd asynchronous xhr from remote origin. Make sure nextHopProtocol is not the empty string.]
expected:
if os == "android": PASS
NOTRUN