Bug 902654 - refactor CSP call sites for readability r=dholbert r=mrbkap

This commit is contained in:
Garrett Robinson 2013-11-11 14:25:55 -08:00
parent 2699bc1b56
commit 72855f7c75
2 changed files with 132 additions and 117 deletions

View File

@ -412,6 +412,72 @@ ParseTypeAttribute(const nsAString& aType, JSVersion* aVersion)
return true; return true;
} }
bool
CSPAllowsInlineScript(nsIScriptElement *aElement, nsIDocument *aDocument)
{
nsCOMPtr<nsIContentSecurityPolicy> csp;
nsresult rv = aDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
NS_ENSURE_SUCCESS(rv, false);
if (!csp) {
// no CSP --> allow
return true;
}
bool reportViolation = false;
bool allowInlineScript = true;
rv = csp->GetAllowsInlineScript(&reportViolation, &allowInlineScript);
NS_ENSURE_SUCCESS(rv, false);
bool foundNonce = false;
nsAutoString nonce;
if (!allowInlineScript) {
nsCOMPtr<nsIContent> scriptContent = do_QueryInterface(aElement);
foundNonce = scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::nonce, nonce);
if (foundNonce) {
// We can overwrite the outparams from GetAllowsInlineScript because
// if the nonce is correct, then we don't want to report the original
// inline violation (it has been whitelisted by the nonce), and if
// the nonce is incorrect, then we want to return just the specific
// "nonce violation" rather than both a "nonce violation" and
// a generic "inline violation".
rv = csp->GetAllowsNonce(nonce, nsIContentPolicy::TYPE_SCRIPT,
&reportViolation, &allowInlineScript);
NS_ENSURE_SUCCESS(rv, false);
}
}
if (reportViolation) {
// gather information to log with violation report
nsIURI* uri = aDocument->GetDocumentURI();
nsAutoCString asciiSpec;
uri->GetAsciiSpec(asciiSpec);
nsAutoString scriptText;
aElement->GetScriptText(scriptText);
// cap the length of the script sample at 40 chars
if (scriptText.Length() > 40) {
scriptText.Truncate(40);
scriptText.AppendLiteral("...");
}
// The type of violation to report is determined by whether there was
// a nonce present.
unsigned short violationType = foundNonce ?
nsIContentSecurityPolicy::VIOLATION_TYPE_NONCE_SCRIPT :
nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_SCRIPT;
csp->LogViolationDetails(violationType, NS_ConvertUTF8toUTF16(asciiSpec),
scriptText, aElement->GetScriptLineNumber(), nonce);
}
if (!allowInlineScript) {
NS_ASSERTION(reportViolation,
"CSP blocked inline script but is not reporting a violation");
return false;
}
return true;
}
bool bool
nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
{ {
@ -619,64 +685,10 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
return false; return false;
} }
nsCOMPtr<nsIContentSecurityPolicy> csp; // Does CSP allow this inline script to run?
rv = mDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp)); if (!CSPAllowsInlineScript(aElement, mDocument)) {
NS_ENSURE_SUCCESS(rv, false);
if (csp) {
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("New ScriptLoader ****with CSP****"));
bool reportViolation = false;
bool allowInlineScript = true;
rv = csp->GetAllowsInlineScript(&reportViolation, &allowInlineScript);
NS_ENSURE_SUCCESS(rv, false);
bool foundNonce = false;
nsAutoString nonce;
if (!allowInlineScript) {
foundNonce = scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::nonce, nonce);
if (foundNonce) {
// We can overwrite the outparams from GetAllowsInlineScript because
// if the nonce is correct, then we don't want to report the original
// inline violation (it has been whitelisted by the nonce), and if
// the nonce is incorrect, then we want to return just the specific
// "nonce violation" rather than both a "nonce violation" and
// a generic "inline violation".
rv = csp->GetAllowsNonce(nonce, nsIContentPolicy::TYPE_SCRIPT,
&reportViolation, &allowInlineScript);
NS_ENSURE_SUCCESS(rv, false);
}
}
if (reportViolation) {
// gather information to log with violation report
nsIURI* uri = mDocument->GetDocumentURI();
nsAutoCString asciiSpec;
uri->GetAsciiSpec(asciiSpec);
nsAutoString scriptText;
aElement->GetScriptText(scriptText);
// cap the length of the script sample at 40 chars
if (scriptText.Length() > 40) {
scriptText.Truncate(40);
scriptText.AppendLiteral("...");
}
// The type of violation to report is determined by whether there was
// a nonce present.
unsigned short violationType = foundNonce ?
nsIContentSecurityPolicy::VIOLATION_TYPE_NONCE_SCRIPT :
nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_SCRIPT;
csp->LogViolationDetails(violationType, NS_ConvertUTF8toUTF16(asciiSpec),
scriptText, aElement->GetScriptLineNumber(), nonce);
}
if (!allowInlineScript) {
NS_ASSERTION(reportViolation,
"CSP blocked inline script but is not reporting a violation");
return false; return false;
} }
}
// Inline scripts ignore ther CORS mode and are always CORS_NONE // Inline scripts ignore ther CORS mode and are always CORS_NONE
request = new nsScriptLoadRequest(aElement, version, CORS_NONE); request = new nsScriptLoadRequest(aElement, version, CORS_NONE);

View File

@ -468,7 +468,11 @@ nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent,
return false; return false;
} }
if (csp) { if (!csp) {
// No CSP --> the style is allowed
return true;
}
bool reportViolation; bool reportViolation;
bool allowInlineStyle = true; bool allowInlineStyle = true;
rv = csp->GetAllowsInlineStyle(&reportViolation, &allowInlineStyle); rv = csp->GetAllowsInlineStyle(&reportViolation, &allowInlineStyle);
@ -530,7 +534,6 @@ nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent,
// The inline style should be blocked. // The inline style should be blocked.
return false; return false;
} }
} // CSP allows inline styles.
// No CSP or a CSP that allows inline styles.
return true; return true;
} }