Bug 1683464 - Reduce nsContentPolicyType usage. r=ckerschb

Differential Revision: https://phabricator.services.mozilla.com/D100181
This commit is contained in:
Masatoshi Kimura 2021-01-07 15:18:52 +00:00
parent ada333728d
commit 3f402bfcc4
10 changed files with 62 additions and 119 deletions

View File

@ -829,7 +829,7 @@ nsresult EventListenerManager::SetEventHandler(nsAtom* aName,
if (csp) {
bool allowsInlineScript = true;
rv = csp->GetAllowsInline(
nsIContentPolicy::TYPE_SCRIPT,
nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE,
u""_ns, // aNonce
true, // aParserCreated (true because attribute event handler)
aElement,

View File

@ -137,7 +137,7 @@ interface nsIContentSecurityPolicy : nsISerializable
* Whether or not the effects of the inline style should be allowed
* (block the rules if false).
*/
boolean getAllowsInline(in nsContentPolicyType aContentPolicyType,
boolean getAllowsInline(in nsIContentSecurityPolicy_CSPDirective aDirective,
in AString aNonce,
in boolean aParserCreated,
in Element aTriggeringElement,

View File

@ -137,15 +137,16 @@ static bool AllowedByCSP(nsIContentSecurityPolicy* aCSP,
}
bool allowsInlineScript = true;
nsresult rv = aCSP->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
u""_ns, // aNonce
true, // aParserCreated
nullptr, // aElement,
nullptr, // nsICSPEventListener
aContentOfPseudoScript, // aContent
0, // aLineNumber
0, // aColumnNumber
&allowsInlineScript);
nsresult rv =
aCSP->GetAllowsInline(nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE,
u""_ns, // aNonce
true, // aParserCreated
nullptr, // aElement,
nullptr, // nsICSPEventListener
aContentOfPseudoScript, // aContent
0, // aLineNumber
0, // aColumnNumber
&allowsInlineScript);
return (NS_SUCCEEDED(rv) && allowsInlineScript);
}

View File

@ -1643,11 +1643,11 @@ static bool CSPAllowsInlineScript(nsIScriptElement* aElement,
aElement->GetParserCreated() != mozilla::dom::NOT_FROM_PARSER;
bool allowInlineScript = false;
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT, nonce, parserCreated,
scriptContent, nullptr /* nsICSPEventListener */,
u""_ns, aElement->GetScriptLineNumber(),
aElement->GetScriptColumnNumber(),
&allowInlineScript);
rv = csp->GetAllowsInline(
nsIContentSecurityPolicy::SCRIPT_SRC_DIRECTIVE, nonce, parserCreated,
scriptContent, nullptr /* nsICSPEventListener */, u""_ns,
aElement->GetScriptLineNumber(), aElement->GetScriptColumnNumber(),
&allowInlineScript);
return NS_SUCCEEDED(rv) && allowInlineScript;
}

View File

@ -444,8 +444,8 @@ nsCSPContext::GetAllowsEval(bool* outShouldReportViolation,
*outAllowsEval = true;
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
if (!mPolicies[i]->allows(nsIContentPolicy::TYPE_SCRIPT, CSP_UNSAFE_EVAL,
u""_ns, false)) {
if (!mPolicies[i]->allows(SCRIPT_SRC_DIRECTIVE, CSP_UNSAFE_EVAL, u""_ns,
false)) {
// policy is violated: must report the violation and allow the inline
// script if the policy is report-only.
*outShouldReportViolation = true;
@ -459,7 +459,7 @@ nsCSPContext::GetAllowsEval(bool* outShouldReportViolation,
// Helper function to report inline violations
void nsCSPContext::reportInlineViolation(
nsContentPolicyType aContentType, Element* aTriggeringElement,
CSPDirective aDirective, Element* aTriggeringElement,
nsICSPEventListener* aCSPEventListener, const nsAString& aNonce,
const nsAString& aContent, const nsAString& aViolatedDirective,
uint32_t aViolatedPolicyIndex, // TODO, use report only flag for that
@ -469,13 +469,13 @@ void nsCSPContext::reportInlineViolation(
// let's report the hash error; no need to report the unsafe-inline error
// anymore.
if (!aNonce.IsEmpty()) {
observerSubject = (aContentType == nsIContentPolicy::TYPE_SCRIPT)
observerSubject = (aDirective == SCRIPT_SRC_DIRECTIVE)
? NS_LITERAL_STRING_FROM_CSTRING(
SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC)
: NS_LITERAL_STRING_FROM_CSTRING(
STYLE_NONCE_VIOLATION_OBSERVER_TOPIC);
} else {
observerSubject = (aContentType == nsIContentPolicy::TYPE_SCRIPT)
observerSubject = (aDirective == SCRIPT_SRC_DIRECTIVE)
? NS_LITERAL_STRING_FROM_CSTRING(
SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC)
: NS_LITERAL_STRING_FROM_CSTRING(
@ -513,22 +513,15 @@ void nsCSPContext::reportInlineViolation(
}
NS_IMETHODIMP
nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
const nsAString& aNonce, bool aParserCreated,
Element* aTriggeringElement,
nsCSPContext::GetAllowsInline(CSPDirective aDirective, const nsAString& aNonce,
bool aParserCreated, Element* aTriggeringElement,
nsICSPEventListener* aCSPEventListener,
const nsAString& aContentOfPseudoScript,
uint32_t aLineNumber, uint32_t aColumnNumber,
bool* outAllowsInline) {
*outAllowsInline = true;
MOZ_ASSERT(
aContentType ==
nsContentUtils::InternalContentPolicyTypeToExternal(aContentType),
"We should only see external content policy types here.");
if (aContentType != nsIContentPolicy::TYPE_SCRIPT &&
aContentType != nsIContentPolicy::TYPE_STYLESHEET) {
if (aDirective != SCRIPT_SRC_DIRECTIVE && aDirective != STYLE_SRC_DIRECTIVE) {
MOZ_ASSERT(false, "can only allow inline for script or style");
return NS_OK;
}
@ -539,9 +532,9 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
// always iterate all policies, otherwise we might not send out all reports
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
bool allowed =
mPolicies[i]->allows(aContentType, CSP_UNSAFE_INLINE, u""_ns,
mPolicies[i]->allows(aDirective, CSP_UNSAFE_INLINE, u""_ns,
aParserCreated) ||
mPolicies[i]->allows(aContentType, CSP_NONCE, aNonce, aParserCreated);
mPolicies[i]->allows(aDirective, CSP_NONCE, aNonce, aParserCreated);
// If the inlined script or style is allowed by either unsafe-inline or the
// nonce, go ahead and shortcut this loop so we can avoid allocating
@ -565,7 +558,7 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
content = aContentOfPseudoScript;
}
allowed =
mPolicies[i]->allows(aContentType, CSP_HASH, content, aParserCreated);
mPolicies[i]->allows(aDirective, CSP_HASH, content, aParserCreated);
if (!allowed) {
// policy is violoated: deny the load unless policy is report only and
@ -576,8 +569,8 @@ nsCSPContext::GetAllowsInline(nsContentPolicyType aContentType,
nsAutoString violatedDirective;
bool reportSample = false;
mPolicies[i]->getDirectiveStringAndReportSampleForContentType(
aContentType, violatedDirective, &reportSample);
reportInlineViolation(aContentType, aTriggeringElement, aCSPEventListener,
aDirective, violatedDirective, &reportSample);
reportInlineViolation(aDirective, aTriggeringElement, aCSPEventListener,
aNonce, reportSample ? content : EmptyString(),
violatedDirective, i, aLineNumber, aColumnNumber);
}
@ -700,17 +693,18 @@ nsCSPContext::GetAllowsNavigateTo(nsIURI* aURI, bool aIsFormSubmission,
* GetAllowsInline() and do not call this macro, hence we can pass 'false'
* as the argument _aParserCreated_ to allows().
*/
#define CASE_CHECK_AND_REPORT(violationType, contentPolicyType, nonceOrHash, \
keyword, observerTopic) \
#define CASE_CHECK_AND_REPORT(violationType, directive, nonceOrHash, keyword, \
observerTopic) \
case nsIContentSecurityPolicy::VIOLATION_TYPE_##violationType: \
PR_BEGIN_MACRO \
if (!mPolicies[p]->allows(nsIContentPolicy::TYPE_##contentPolicyType, \
keyword, nonceOrHash, false)) { \
static_assert(directive##_SRC_DIRECTIVE == SCRIPT_SRC_DIRECTIVE || \
directive##_SRC_DIRECTIVE == STYLE_SRC_DIRECTIVE); \
if (!mPolicies[p]->allows(directive##_SRC_DIRECTIVE, keyword, nonceOrHash, \
false)) { \
nsAutoString violatedDirective; \
bool reportSample = false; \
mPolicies[p]->getDirectiveStringAndReportSampleForContentType( \
nsIContentPolicy::TYPE_##contentPolicyType, violatedDirective, \
&reportSample); \
directive##_SRC_DIRECTIVE, violatedDirective, &reportSample); \
AsyncReportViolation(aTriggeringElement, aCSPEventListener, nullptr, \
blockedContentSource, nullptr, violatedDirective, \
p, NS_LITERAL_STRING_FROM_CSTRING(observerTopic), \
@ -771,17 +765,17 @@ nsCSPContext::LogViolationDetails(
switch (aViolationType) {
CASE_CHECK_AND_REPORT(EVAL, SCRIPT, u""_ns, CSP_UNSAFE_EVAL,
EVAL_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(INLINE_STYLE, STYLESHEET, u""_ns, CSP_UNSAFE_INLINE,
CASE_CHECK_AND_REPORT(INLINE_STYLE, STYLE, u""_ns, CSP_UNSAFE_INLINE,
INLINE_STYLE_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(INLINE_SCRIPT, SCRIPT, u""_ns, CSP_UNSAFE_INLINE,
INLINE_SCRIPT_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(NONCE_SCRIPT, SCRIPT, aNonce, CSP_UNSAFE_INLINE,
SCRIPT_NONCE_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(NONCE_STYLE, STYLESHEET, aNonce, CSP_UNSAFE_INLINE,
CASE_CHECK_AND_REPORT(NONCE_STYLE, STYLE, aNonce, CSP_UNSAFE_INLINE,
STYLE_NONCE_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(HASH_SCRIPT, SCRIPT, aContent, CSP_UNSAFE_INLINE,
SCRIPT_HASH_VIOLATION_OBSERVER_TOPIC);
CASE_CHECK_AND_REPORT(HASH_STYLE, STYLESHEET, aContent, CSP_UNSAFE_INLINE,
CASE_CHECK_AND_REPORT(HASH_STYLE, STYLE, aContent, CSP_UNSAFE_INLINE,
STYLE_HASH_VIOLATION_OBSERVER_TOPIC);
default:

View File

@ -155,7 +155,7 @@ class nsCSPContext : public nsIContentSecurityPolicy {
bool aParserCreated);
// helper to report inline script/style violations
void reportInlineViolation(nsContentPolicyType aContentType,
void reportInlineViolation(CSPDirective aDirective,
mozilla::dom::Element* aTriggeringElement,
nsICSPEventListener* aCSPEventListener,
const nsAString& aNonce, const nsAString& aContent,

View File

@ -1207,15 +1207,6 @@ void nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const {
}
}
bool nsCSPDirective::restrictsContentType(
nsContentPolicyType aContentType) const {
// make sure we do not check for the default src before any other sources
if (isDefaultDirective()) {
return false;
}
return mDirective == CSP_ContentTypeToDirective(aContentType);
}
void nsCSPDirective::getReportURIs(nsTArray<nsString>& outReportURIs) const {
NS_ASSERTION((mDirective == nsIContentSecurityPolicy::REPORT_URI_DIRECTIVE),
"not a report-uri directive");
@ -1265,19 +1256,6 @@ nsCSPChildSrcDirective::nsCSPChildSrcDirective(CSPDirective aDirective)
nsCSPChildSrcDirective::~nsCSPChildSrcDirective() = default;
bool nsCSPChildSrcDirective::restrictsContentType(
nsContentPolicyType aContentType) const {
if (aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
return mRestrictFrames;
}
if (aContentType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER) {
return mRestrictWorkers;
}
return false;
}
bool nsCSPChildSrcDirective::equals(CSPDirective aDirective) const {
if (aDirective == nsIContentSecurityPolicy::FRAME_SRC_DIRECTIVE) {
return mRestrictFrames;
@ -1295,16 +1273,6 @@ nsCSPScriptSrcDirective::nsCSPScriptSrcDirective(CSPDirective aDirective)
nsCSPScriptSrcDirective::~nsCSPScriptSrcDirective() = default;
bool nsCSPScriptSrcDirective::restrictsContentType(
nsContentPolicyType aContentType) const {
if (aContentType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER ||
aContentType == nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER) {
return mRestrictWorkers;
}
return mDirective == CSP_ContentTypeToDirective(aContentType);
}
bool nsCSPScriptSrcDirective::equals(CSPDirective aDirective) const {
if (aDirective == nsIContentSecurityPolicy::WORKER_SRC_DIRECTIVE) {
return mRestrictWorkers;
@ -1364,12 +1332,6 @@ nsCSPPolicy::~nsCSPPolicy() {
}
}
bool nsCSPPolicy::permits(CSPDirective aDir, nsIURI* aUri,
bool aSpecific) const {
nsString outp;
return this->permits(aDir, aUri, u""_ns, false, aSpecific, false, outp);
}
bool nsCSPPolicy::permits(CSPDirective aDir, nsIURI* aUri,
const nsAString& aNonce, bool aWasRedirected,
bool aSpecific, bool aParserCreated,
@ -1418,8 +1380,7 @@ bool nsCSPPolicy::permits(CSPDirective aDir, nsIURI* aUri,
return true;
}
bool nsCSPPolicy::allows(nsContentPolicyType aContentType,
enum CSPKeyword aKeyword,
bool nsCSPPolicy::allows(CSPDirective aDirective, enum CSPKeyword aKeyword,
const nsAString& aHashOrNonce,
bool aParserCreated) const {
CSPUTILSLOG(("nsCSPPolicy::allows, aKeyWord: %s, a HashOrNonce: %s",
@ -1430,15 +1391,16 @@ bool nsCSPPolicy::allows(nsContentPolicyType aContentType,
// Try to find a matching directive
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
if (mDirectives[i]->restrictsContentType(aContentType)) {
if (mDirectives[i]->isDefaultDirective()) {
defaultDir = mDirectives[i];
continue;
}
if (mDirectives[i]->equals(aDirective)) {
if (mDirectives[i]->allows(aKeyword, aHashOrNonce, aParserCreated)) {
return true;
}
return false;
}
if (mDirectives[i]->isDefaultDirective()) {
defaultDir = mDirectives[i];
}
}
// {nonce,hash}-source should not consult default-src:
@ -1465,11 +1427,6 @@ bool nsCSPPolicy::allows(nsContentPolicyType aContentType,
return true;
}
bool nsCSPPolicy::allows(nsContentPolicyType aContentType,
enum CSPKeyword aKeyword) const {
return allows(aContentType, aKeyword, u""_ns, false);
}
void nsCSPPolicy::toString(nsAString& outStr) const {
StringJoinAppend(outStr, u"; "_ns, mDirectives,
[](nsAString& dest, nsCSPDirective* cspDirective) {
@ -1525,21 +1482,22 @@ bool nsCSPPolicy::allowsNavigateTo(nsIURI* aURI, bool aWasRedirected,
* for the ::permits() function family.
*/
void nsCSPPolicy::getDirectiveStringAndReportSampleForContentType(
nsContentPolicyType aContentType, nsAString& outDirective,
CSPDirective aDirective, nsAString& outDirective,
bool* aReportSample) const {
MOZ_ASSERT(aReportSample);
*aReportSample = false;
nsCSPDirective* defaultDir = nullptr;
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
if (mDirectives[i]->restrictsContentType(aContentType)) {
if (mDirectives[i]->isDefaultDirective()) {
defaultDir = mDirectives[i];
continue;
}
if (mDirectives[i]->equals(aDirective)) {
mDirectives[i]->getDirName(outDirective);
*aReportSample = mDirectives[i]->hasReportSampleKeyword();
return;
}
if (mDirectives[i]->isDefaultDirective()) {
defaultDir = mDirectives[i];
}
}
// if we haven't found a matching directive yet,
// the contentType must be restricted by the default directive

View File

@ -454,8 +454,6 @@ class nsCSPDirective {
mSrcs = aSrcs.Clone();
}
virtual bool restrictsContentType(nsContentPolicyType aContentType) const;
inline bool isDefaultDirective() const {
return mDirective == nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE;
}
@ -492,9 +490,6 @@ class nsCSPChildSrcDirective : public nsCSPDirective {
void setRestrictWorkers() { mRestrictWorkers = true; }
virtual bool restrictsContentType(
nsContentPolicyType aContentType) const override;
virtual bool equals(CSPDirective aDirective) const override;
private:
@ -516,9 +511,6 @@ class nsCSPScriptSrcDirective : public nsCSPDirective {
void setRestrictWorkers() { mRestrictWorkers = true; }
virtual bool restrictsContentType(
nsContentPolicyType aContentType) const override;
virtual bool equals(CSPDirective aDirective) const override;
private:
@ -622,10 +614,8 @@ class nsCSPPolicy {
bool permits(CSPDirective aDirective, nsIURI* aUri, const nsAString& aNonce,
bool aWasRedirected, bool aSpecific, bool aParserCreated,
nsAString& outViolatedDirective) const;
bool permits(CSPDirective aDir, nsIURI* aUri, bool aSpecific) const;
bool allows(nsContentPolicyType aContentType, enum CSPKeyword aKeyword,
bool allows(CSPDirective aDirective, enum CSPKeyword aKeyword,
const nsAString& aHashOrNonce, bool aParserCreated) const;
bool allows(nsContentPolicyType aContentType, enum CSPKeyword aKeyword) const;
void toString(nsAString& outStr) const;
void toDomCSPStruct(mozilla::dom::CSP& outCSP) const;
@ -655,7 +645,7 @@ class nsCSPPolicy {
void getReportURIs(nsTArray<nsString>& outReportURIs) const;
void getDirectiveStringAndReportSampleForContentType(
nsContentPolicyType aContentType, nsAString& outDirective,
CSPDirective aDirective, nsAString& outDirective,
bool* aReportSample) const;
void getDirectiveAsString(CSPDirective aDir, nsAString& outDirective) const;

View File

@ -120,7 +120,7 @@ function run_test() {
makeTest(0, { "blocked-uri": "inline" }, false, function(csp) {
let inlineOK = true;
inlineOK = csp.getAllowsInline(
Ci.nsIContentPolicy.TYPE_SCRIPT,
Ci.nsIContentSecurityPolicy.SCRIPT_SRC_DIRECTIVE,
"", // aNonce
false, // aParserCreated
null, // aTriggeringElement
@ -192,7 +192,7 @@ function run_test() {
makeTest(3, { "blocked-uri": "inline" }, true, function(csp) {
let inlineOK = true;
inlineOK = csp.getAllowsInline(
Ci.nsIContentPolicy.TYPE_SCRIPT,
Ci.nsIContentSecurityPolicy.SCRIPT_SRC_DIRECTIVE,
"", // aNonce
false, // aParserCreated
null, // aTriggeringElement

View File

@ -317,11 +317,11 @@ bool nsStyleUtil::CSPAllowsInlineStyle(
}
bool allowInlineStyle = true;
rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_STYLESHEET, nonce,
false, // aParserCreated only applies to scripts
aElement, nullptr, // nsICSPEventListener
aStyleText, aLineNumber, aColumnNumber,
&allowInlineStyle);
rv = csp->GetAllowsInline(
nsIContentSecurityPolicy::STYLE_SRC_DIRECTIVE, nonce,
false, // aParserCreated only applies to scripts
aElement, nullptr, // nsICSPEventListener
aStyleText, aLineNumber, aColumnNumber, &allowInlineStyle);
NS_ENSURE_SUCCESS(rv, false);
return allowInlineStyle;